Chapter 18 · Capstone 3: Secondmate Remote Fleet Scaling Operations
Chapter goals: Upgrade the personal fleet built in Chapter 16 to a scaled deployment — local secondmate + remote home + Relay应答 + /afk on-call mode — and complete a production-grade ops drill.
18.1 Capstone Blueprint and Preparation
In the first two capstones, you only指挥 a single fleet managed directly by the firstmate. This chapter introduces two scaling upgrades:
Before (Capstone 1/2):
captain ──> firstmate ──> crewmate × N (one worktree per task)
After (this chapter):
captain ──> firstmate (primary home)
├──> secondmate A (local isolated FM_HOME)
├──> secondmate B (complete home on a remote host, Herdr fm-remote session)
└──> crewmate × NRecalling the official definition: a secondmate is a crewmate with an isolated firstmate home and a charter, not a second architecture. It has its own persistent FM_HOME — independent state, backlog, projects, and session lock; and secondmates do not spawn secondmates, so config/secondmate-harness only生效 on the primary and is never inherited.
Preparation for this chapter:
- A completed Capstone 2 fleet environment (tmux backend available,
gh auth logincompleted); - An SSH-reachable remote host (cloud server or another Mac/Linux at home);
- An X or Discord account (for Relay drill; can skip).
18.2 Step One: Provision a Local Secondmate
First write the charter for the secondmate, then启动. The charter is its brief (kind=secondmate in data/<id>/brief.md): telling this "deputy" what class of tasks it负责 and who it reports to.
Issue a natural-language指令 to the firstmate to complete provisioning, or启动 directly with the script:
# Execute in the firstmate primary home repo root:
# Have the firstmate建 the home and启动 for a secondmate with id "ops"
bin/fm-spawn.sh ops --secondmateOn launch, the primary解析 the secondmate专用 harness. Specified via the local gitignored file config/secondmate-harness, first line format: <harness> [<model>] [<effort>]:
# config/secondmate-harness —— fix the secondmate to use pi, model and effort optional
piResolution rules to remember:
- When the file is absent or writes
default, fallback toconfig/crew-harness, then to the primary's own harness; - Explicitly passed
--harness/--model/--efforttofm-spawn.shoverride this file, but only for that one spawn; - This file is NOT inherited — because secondmates do not spawn secondmates, this switch naturally stays only in the primary's hands.
18.3 Step Two: Verify Isolated FM_HOME and Session Lock
After launch, verify the deputy truly lives in its own house, not sharing状态 with the primary:
# View the secondmate routing table: host/root/home triplet registered
cat data/secondmates.md
# Validate the routing record (both local and remote forms supported)
bin/fm-home-seed.sh validateConfirm these isolation facts:
| Check | Expected |
|---|---|
FM_HOME | The secondmate has its own data/, state/, config/, projects/ |
| Session lock | Its home has its own session lock; no竞争 with the primary |
| Inherited materials | data/captain-shared.md reaches the secondmate in read-only mode; ownership仍在 primary |
| Spawn权限 | No inherited copy of config/secondmate-harness inside the secondmate |
config/startup-memory-budget is an例外样例: it is a primary-authoritative per-home budget, defaulting to a 7500 estimated token, distributed to each secondmate home via the inheritance契约 — but each home核算s independently, no fleet总量 merge. Verify with tools:
bin/fm-startup-memory-budget.sh read # Validate and print the生效 value
bin/fm-startup-memory-budget.sh report #核算 the three memory files18.4 Step Three: Migrate to a Remote Secondmate (Doctor → Seed → Spawn)
Now move a secondmate's entire home to a remote host. Three iron rules to remember first:
- What moves remote is the entire home, not a single worker; the primary retains路由 and supervision权; the remote home has its own projects, backlog, and workers;
- The remote secondmate agent 永远跑 in the Herdr backend's shared
fm-remotesession — that service belongs to the remote host's own GUI login session, not the SSH connection, so断线 does not带走 the agent endpoint; - An unavailable remote route is marked unknown only; it never降级 to a local replacement.
3.1 Remote Host Pre-bury
Clone FirstMate on the remote host to an absolute path and expose the fixed entry to the non-interactive PATH:
# Execute on the remote host
mkdir -p ~/.local/bin
ln -s /absolute/path/to/firstmate/bin/fm-remote-entrypoint.sh \
~/.local/bin/fm-remote-entrypoint.shThe entry accepts only encoded-argv form真实可执行的 bin/fm-*.sh; it never accepts shell command strings. Note: do not enable agent forwarding — fm-on.sh actively禁用 it on each call, and arms bounded SSH dead-peer detection, so a gone host fails within a有限 window rather than hanging无限.
3.2 Doctor → Seed → Spawn
# Phase 1: doctor — read-only readiness check (human缺口永不全自动修复)
bin/fm-remote-doctor.sh <ssh-alias>
# Phase 2: seed —播 the remote home (after doctor绿灯)
bin/fm-remote-home-seed.sh <id> <ssh-alias> <remote-root> <remote-home> \
myapp=https://github.com/you/myapp.git
# Phase 3: spawn —启动 the secondmate on the remote
bin/fm-spawn.sh <id> --secondmate18.5 Relay: Public Mention应答安全模型
Enable Relay with a local .env paired token:
# .env (gitignored)
RELAY_X_TOKEN=xxx
RELAY_RELAY_DISCORD_TOKEN=xxxThe安全模型核心: Relay only responds to public mentions, never主动 DM or私聊. The firstmate sees the mention, routes it through the normal intake契约, and replies in公开上下文 — never exposing internal state or crewmate工作细节.
Safety boundary: Relay上线先 dry-run — would-be replies are本地留痕,人工审阅后再放行,最多七天内三条公开跟进.
18.6 /afk + Wedge-Alarm:无人值守兜底
Configure config/wedge-alarm to push alerts to your phone:
# config/wedge-alarm
command: curl -X POST https://your-webhook.url -d '{"text":"WEDGE: $MESSAGE"}'Then activate away mode:
> /afkDuring /afk: the bash sub-supervisor handles routine notifications零 token; batches captain-related events into digests; and the wedge-alarm triggers响亮 alerts when delivery wedges. The限频机制 ensures at most one alarm per max-defer window, with a default 10-second timeout.
18.7 次日回岗: /ahoy and /stow
Next day back at the desk, a single /ahoy gives you the event recap since the last real captain message, with unresolved items guided one-by-one in impact order; if /ahoy is the first real message of this session, it退化 to a Bearings summary.
Before closing the session, run:
/stowThis内置技能清扫未捕获的持久知识, persisting known-unarchived or stale work records to disk;策展分层 startup memory with衰减与冷归档策略; enforcing each home's budget约束 (exceeding上报决策 rather than硬塞); cascading同步 to registered secondmates. The budget is the config/startup-memory-budget from Section 18.3, with a stable estimation formula of ceil(UTF-8 bytes / 3) per file — a conservative portability approximation, not any vendor's精确 tokenizer.
18.8 全家桶更新: /updatefirstmate
The final piece of scaled ops:
/updatefirstmateThis skill performs a fast-forward-only origin pull update on the running firstmate and all its secondmates, then re-reads instructions and notifies secondmates. The fast-forward-only保证 the update never creates a历史分叉 — if it cannot pull, itstops and reports rather than强推.
18.9 Production Checklist
固化为周期性运维节奏, check off each item:
□ Safety boundaries: Hard Rules 1–5 recited correctly; projects/ read-only to firstmate;
merge权限 not yolo-ed projects still require explicit approval
□ Credential hygiene: .env (Relay token) confirmed gitignored; config/ LOCAL files未入库;
remote host has no agent forwarding
□ Monitoring rhythm: wedge-alarm channel reachable (trigger once manually to verify);
/afk digest送达正常; fm-tool-update-check.sh's watched-tools.json matches实际依赖
□ Disaster drill: kill the remote session; verify fm-spawn.sh can recover;
SSH断链期间 primary shows unknown且未降级本地; after恢复, pending replies补齐 via correlation-preserving重发
□ Knowledge governance: /stow定期清扫; startup memory核算不超预算;
data/learnings.md and captain.md内容仍然准确
□ Version管理: /updatefirstmate全家桶 fast-forward-only update成功;
remote doctor read-only check绿灯18.10 Chapter Summary
- Secondmate = independent FM_HOME + charter crewmate: own state/backlog/projects/session lock; does not spawn secondmates, so
config/secondmate-harnessonly生效 on primary; - Remote migration three-step:
fm-remote-doctor.shreadiness gate (human缺口永不全自动) →fm-remote-home-seed.shseed →fm-spawn.sh <id> --secondmatelaunch, all in Herdrfm-remotesessions; - Failure semantics must be precise: SSH exit 255 is "unknown" not "dead"; only correlation-preserving重发 is safe; unavailable remote routes投影为 unknown and never降级为本地替换;
- Relay上线先 dry-run: would-be replies locally留痕, human审阅后再放行, max三条公开跟进 in seven days;
/afk+ wedge-alarm form the无人值守兜底: bash sub-supervisor零 token handles routine events, wedge限频响亮 alerts;/stowand/updatefirstmateclose the knowledge governance and version推进 loop.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. Regarding config/secondmate-harness, which statement is correct?
2. After sending an指令 to a remote secondmate and encountering SSH exit 255, what is the correct理解 and做法?
3. In which session does the remote secondmate's agent run? Why?
4. Regarding the wedge-alarm and /afk combination, which description is wrong?
🛠️ Hands-On Exercises
- Add a local secondmate to your fleet: write a限定范围的 charter (e.g., only responsible for code-review scout tasks), fix its harness via
config/secondmate-harness,启动, and verify isolation withdata/secondmates.mdandbin/fm-home-seed.sh validate; send a测试指令 and confirm the reply链路. - Pick an SSH-reachable host for远程化: run the read-only doctor first and记录全部缺口, categorize which are fixable vs human; after修复 and completing the human steps, seed a remote home with a single project; then故意中断 SSH链路 and observe the primary显示 the route as unknown with零本地替代.
- Design your无人值守夜班: configure
config/wedge-alarmto push to your phone via acommand:channel; activate/afk;人为制造一次注入卡顿场景 to验证 the限频告警 triggers; next morning, review the batched digest with/ahoy, complete knowledge清扫 with/stow, and核对 the startup memory未超预算; record the full process as your team's own on-call手册.
Capstone 3 complete. Course complete! You now have a production-grade FirstMate fleet spanning local secondmates, remote homes, Relay public mentions, and无人值守 on-call mode.