Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
128 commits
Select commit Hold shift + click to select a range
d4b910a
feat: add optional host-root mode
YrFnS Jul 26, 2026
039c3bd
no-mistakes(review): Scope host-root lifecycle safeguards correctly
YrFnS Jul 26, 2026
e1749a3
no-mistakes(document): Document host-root overlap and forge scoping
YrFnS Jul 26, 2026
8c6bfdf
no-mistakes(review): Captain: harden host-root cleanup and task admis…
YrFnS Jul 26, 2026
048123f
no-mistakes(review): Harden host-root promotion and logical project r…
YrFnS Jul 26, 2026
cd9fe1f
no-mistakes(document): Consolidate host-root documentation ownership
YrFnS Jul 26, 2026
d58790a
no-mistakes(lint): Suppress intentional literal-dollar ShellCheck war…
YrFnS Jul 26, 2026
ac8af62
no-mistakes(document): Clarify local-only host-root scout documentation
YrFnS Jul 26, 2026
585bf02
no-mistakes(review): Captain: Protect retained metadata and host-boun…
YrFnS Jul 26, 2026
ed61506
fix(host-root): preserve recovery and bind tmux aliases
YrFnS Jul 27, 2026
fce1014
no-mistakes(review): Captain: protect host teardown and preserve Herd…
YrFnS Jul 27, 2026
070af99
no-mistakes(review): Captain: preserve retained host metadata across …
YrFnS Jul 27, 2026
0b93ae0
test(host-root): run nudge from synthetic root
YrFnS Jul 27, 2026
de30280
no-mistakes(review): Captain, preserve host authority across aliases …
YrFnS Jul 27, 2026
b623ed5
no-mistakes(review): Captain, preserve host children during recursive…
YrFnS Jul 27, 2026
8f066b1
no-mistakes(review): Captain, preserve indexed tmux and projected Her…
YrFnS Jul 27, 2026
146166b
no-mistakes(review): Captain, stabilize tmux authority and teardown i…
YrFnS Jul 27, 2026
e685d9e
no-mistakes(review): Harden host-root cleanup and endpoint identity
YrFnS Jul 27, 2026
00c1e39
no-mistakes(review): Bind tmux identity and close cross-window cmux t…
YrFnS Jul 27, 2026
35953fc
no-mistakes(review): Bind host tmux tasks to their creating sockets
YrFnS Jul 27, 2026
b342848
no-mistakes(review): Scope tmux supervision and recognize vanished so…
YrFnS Jul 27, 2026
51a2135
test: bound Herdr abort fixture timing
YrFnS Jul 27, 2026
b0c2ee6
no-mistakes(review): Preserve tmux rollback metadata; Herdr acceptanc…
YrFnS Jul 28, 2026
3cf9357
no-mistakes(review): Captain: complete Herdr host-root decision-inven…
YrFnS Jul 28, 2026
c45a7fd
no-mistakes(document): Align host-root documentation with runtime saf…
YrFnS Jul 28, 2026
a2c2355
no-mistakes(lint): Fix host-root ShellCheck findings
YrFnS Jul 28, 2026
1bf1ee0
fix: reconcile host-root mode with endpoint hardening
YrFnS Jul 29, 2026
981de4a
feat: activate FirstMate from an external Pi host
YrFnS Jul 29, 2026
d46f931
no-mistakes(review): Harden host-root overlap and metadata authority
YrFnS Jul 29, 2026
d5fe892
no-mistakes(review): Enforce runtime host-home root isolation
YrFnS Jul 29, 2026
2fad229
no-mistakes(document): Refresh host-root verification evidence
YrFnS Jul 29, 2026
75836bf
no-mistakes(lint): Captain: fix ShellCheck empty local declaration
YrFnS Jul 29, 2026
0519545
no-mistakes(review): Captain: guard host-root Pi workers from supervi…
YrFnS Jul 30, 2026
94c569c
no-mistakes(document): Document Pi host-root worker activation guard
YrFnS Jul 30, 2026
1642a6a
fix(host-root): launch workers from target worktrees
YrFnS Aug 1, 2026
2eae81f
no-mistakes(review): Captain: fix host-root review regressions
YrFnS Aug 1, 2026
167e999
no-mistakes(document): Consolidate host-root verification evidence
YrFnS Aug 1, 2026
26c8b4e
no-mistakes(document): Clarify host-root semantic-state evidence
YrFnS Aug 1, 2026
4ebef6f
no-mistakes(review): Captain: fix host-root lifecycle and rollback re…
YrFnS Aug 2, 2026
7b42776
no-mistakes(document): Correct host-root verification and startup doc…
YrFnS Aug 2, 2026
088e701
fix(pi): notify supervisor only after worker settles
YrFnS Aug 2, 2026
bbba62a
no-mistakes(review): Gate host-root Pi notifications on successful idle
YrFnS Aug 2, 2026
8df194a
no-mistakes(review): Clarify Pi notification behavior by host mode
YrFnS Aug 2, 2026
ee055ae
feat: add optional host-root mode
YrFnS Jul 26, 2026
e84922a
test: preserve node in spawn harness paths
Aug 2, 2026
3deb0ae
no-mistakes(review): Captain, harden host-root teardown and rollback …
Aug 3, 2026
d82df1b
no-mistakes(document): Document legacy host-root task routing
Aug 3, 2026
997b6ce
no-mistakes(lint): Make shell lint portable across platforms
Aug 3, 2026
fb64ce3
test: restore zellij teardown fixture order
Aug 3, 2026
39b9cae
no-mistakes(document): Document native Windows Herdr support
Aug 3, 2026
9f97148
fix(host-root): align with explicit delivery contracts
Aug 3, 2026
cc9135a
test: pass delivery mode in host parity fixture
Aug 3, 2026
d39b07e
no-mistakes(review): Captain, preserve rollback contracts and prelock…
Aug 3, 2026
6dbac78
no-mistakes(document): Correct Herdr native Windows launch documentation
Aug 3, 2026
345178a
no-mistakes(lint): Fix Herdr launch cleanup quoting
Aug 3, 2026
743456d
Merge upstream/main into feat/host-root-mode-upstream
YrFnS Aug 9, 2026
a4952d3
Fix CI fixture boundaries after upstream merge
YrFnS Aug 9, 2026
593c9cc
ci: install tasks-axi in Herdr job
YrFnS Aug 9, 2026
18f1066
style: retain prior shell formatter fixes
YrFnS Aug 10, 2026
6cfef31
Merge remote-tracking branch 'upstream/main' into fm/firstmate-pr1238…
YrFnS Aug 10, 2026
a6e99bb
fix: stabilize startup locks and Pi wake delivery
YrFnS Aug 10, 2026
6c23df3
no-mistakes(review): Bind durable wakes and host-root lifecycle ident…
YrFnS Aug 10, 2026
6f5e502
feat: add optional host-root mode
YrFnS Jul 26, 2026
a8ee7de
no-mistakes(review): Scope host-root lifecycle safeguards correctly
YrFnS Jul 26, 2026
bb48557
no-mistakes(document): Document host-root overlap and forge scoping
YrFnS Jul 26, 2026
9674c41
no-mistakes(review): Captain: harden host-root cleanup and task admis…
YrFnS Jul 26, 2026
774c0f4
no-mistakes(review): Harden host-root promotion and logical project r…
YrFnS Jul 26, 2026
c9718d1
no-mistakes(document): Consolidate host-root documentation ownership
YrFnS Jul 26, 2026
008025f
no-mistakes(lint): Suppress intentional literal-dollar ShellCheck war…
YrFnS Jul 26, 2026
359306d
no-mistakes(document): Clarify local-only host-root scout documentation
YrFnS Jul 26, 2026
4fe6269
no-mistakes(review): Captain: Protect retained metadata and host-boun…
YrFnS Jul 26, 2026
21c85d9
fix(host-root): preserve recovery and bind tmux aliases
YrFnS Jul 27, 2026
e663735
no-mistakes(review): Captain: protect host teardown and preserve Herd…
YrFnS Jul 27, 2026
899bcb5
no-mistakes(review): Captain: preserve retained host metadata across …
YrFnS Jul 27, 2026
fb5edb5
test(host-root): run nudge from synthetic root
YrFnS Jul 27, 2026
89c3006
no-mistakes(review): Captain, preserve host authority across aliases …
YrFnS Jul 27, 2026
e8cb08c
no-mistakes(review): Captain, preserve host children during recursive…
YrFnS Jul 27, 2026
e41a0cb
no-mistakes(review): Captain, preserve indexed tmux and projected Her…
YrFnS Jul 27, 2026
1cfd0e9
no-mistakes(review): Captain, stabilize tmux authority and teardown i…
YrFnS Jul 27, 2026
8932d64
no-mistakes(review): Harden host-root cleanup and endpoint identity
YrFnS Jul 27, 2026
7173085
no-mistakes(review): Bind tmux identity and close cross-window cmux t…
YrFnS Jul 27, 2026
93ca059
no-mistakes(review): Bind host tmux tasks to their creating sockets
YrFnS Jul 27, 2026
6aef79f
no-mistakes(review): Scope tmux supervision and recognize vanished so…
YrFnS Jul 27, 2026
5f77599
test: bound Herdr abort fixture timing
YrFnS Jul 27, 2026
bbb1b03
no-mistakes(review): Preserve tmux rollback metadata; Herdr acceptanc…
YrFnS Jul 28, 2026
7998520
no-mistakes(review): Captain: complete Herdr host-root decision-inven…
YrFnS Jul 28, 2026
7c13bde
no-mistakes(document): Align host-root documentation with runtime saf…
YrFnS Jul 28, 2026
6858f81
no-mistakes(lint): Fix host-root ShellCheck findings
YrFnS Jul 28, 2026
46f4f29
fix: reconcile host-root mode with endpoint hardening
YrFnS Jul 29, 2026
b0b3f10
feat: activate FirstMate from an external Pi host
YrFnS Jul 29, 2026
1a2a83a
no-mistakes(review): Harden host-root overlap and metadata authority
YrFnS Jul 29, 2026
4431f86
no-mistakes(review): Enforce runtime host-home root isolation
YrFnS Jul 29, 2026
692b491
no-mistakes(document): Refresh host-root verification evidence
YrFnS Jul 29, 2026
8c9849a
no-mistakes(lint): Captain: fix ShellCheck empty local declaration
YrFnS Jul 29, 2026
f844b2d
no-mistakes(review): Captain: guard host-root Pi workers from supervi…
YrFnS Jul 30, 2026
9eb9271
no-mistakes(document): Document Pi host-root worker activation guard
YrFnS Jul 30, 2026
b2b1c2e
fix(host-root): launch workers from target worktrees
YrFnS Aug 1, 2026
d2967a2
no-mistakes(review): Captain: fix host-root review regressions
YrFnS Aug 1, 2026
2cdc51d
no-mistakes(document): Consolidate host-root verification evidence
YrFnS Aug 1, 2026
5b56d69
no-mistakes(document): Clarify host-root semantic-state evidence
YrFnS Aug 1, 2026
f212728
no-mistakes(review): Captain: fix host-root lifecycle and rollback re…
YrFnS Aug 2, 2026
6d3c6fc
no-mistakes(document): Correct host-root verification and startup doc…
YrFnS Aug 2, 2026
49d6e6e
fix(pi): notify supervisor only after worker settles
YrFnS Aug 2, 2026
526a896
no-mistakes(review): Gate host-root Pi notifications on successful idle
YrFnS Aug 2, 2026
bcfb4d8
no-mistakes(review): Clarify Pi notification behavior by host mode
YrFnS Aug 2, 2026
dd8a936
feat: add optional host-root mode
YrFnS Jul 26, 2026
3037d7e
test: preserve node in spawn harness paths
Aug 2, 2026
ffdc9d9
no-mistakes(review): Captain, harden host-root teardown and rollback …
Aug 3, 2026
1aaab68
no-mistakes(document): Document legacy host-root task routing
Aug 3, 2026
f3df1ec
no-mistakes(lint): Make shell lint portable across platforms
Aug 3, 2026
0509da2
test: restore zellij teardown fixture order
Aug 3, 2026
ef38411
no-mistakes(document): Document native Windows Herdr support
Aug 3, 2026
08eb051
fix(host-root): align with explicit delivery contracts
Aug 3, 2026
ddd5d2d
test: pass delivery mode in host parity fixture
Aug 3, 2026
f51e393
no-mistakes(review): Captain, preserve rollback contracts and prelock…
Aug 3, 2026
9465203
no-mistakes(document): Correct Herdr native Windows launch documentation
Aug 3, 2026
c593954
no-mistakes(lint): Fix Herdr launch cleanup quoting
Aug 3, 2026
e9769c1
Fix CI fixture boundaries after upstream merge
YrFnS Aug 9, 2026
78539aa
ci: install tasks-axi in Herdr job
YrFnS Aug 9, 2026
79dc86b
no-mistakes(review): Fix SecondMate recovery and promotion preflight …
Aug 14, 2026
bd5e76d
no-mistakes(document): Confirm host-root documentation remains current
Aug 15, 2026
22fb54e
no-mistakes(lint): Fix ShellCheck assignment and reserved-word warnings
Aug 15, 2026
7c8d467
fix(host-root): bind lifecycle actions to durable ownership
Aug 15, 2026
cd658bd
style: retain no-mistakes formatter changes
YrFnS Aug 16, 2026
44e0f02
Merge recovered no-mistakes review fixes
YrFnS Aug 16, 2026
43d79c4
Merge current PR 1238 head
YrFnS Aug 16, 2026
521930e
Merge current upstream/main
YrFnS Aug 16, 2026
fc45e21
no-mistakes(document): Document Pi wake and host-root ownership contr…
YrFnS Aug 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/skills/firstmate-orca/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Use raw `orca` only when the helper surface cannot answer the inspection questio
## Preflight

Work from the current firstmate home or repo root.
In host-root mode, work instead from the physical `FM_HOST_ROOT` and invoke FirstMate helpers by their absolute `FM_ROOT/bin/` paths under the [four-root contract](../../../docs/configuration.md#host-root-mode-fm_host_root).
If `FM_HOME` is set, remember that operational state lives under `$FM_HOME` while the helper scripts still run from this repo's `bin/`.

Before switching or spawning against Orca:
Expand Down
38 changes: 30 additions & 8 deletions .agents/skills/harness-adapters/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,25 @@ OpenCode uses `.opencode/plugins/fm-primary-watch-arm.js`, which coordinates wit
Pi and pi-signed use the tracked `.pi/extensions/fm-primary-turnend-guard.ts` plus the tracked `.pi/extensions/fm-primary-pi-watch.ts`, both project-local extensions the Pi engine auto-discovers once trusted.
When changing any primary watcher adapter, update `docs/supervision-protocols/`, `docs/turnend-guard.md` if a shared idle or turn-end hook changed, and the relevant concise fact below.

## Host-root task integration

When `FM_HOST_ROOT` is set, only the primary supervisor starts from that physical host root.
Ordinary ship and scout harnesses start from their isolated `FM_TARGET_WORKTREE`, so the target repository's instructions and lifecycle adapters load natively while the host context stays out of focused worker sessions.
FirstMate retains one task completion signal per harness and passes the host and target identities for supervision and recovery without changing the worker cwd:

| Harness | Task completion signal in host-root mode |
|---|---|
| claude | A state-owned settings file passed with `--settings`; target project settings still load from the worker cwd. |
| codex | The existing per-launch `notify` command. |
| opencode | A state-owned task plugin named through `OPENCODE_CONFIG_CONTENT`; target project plugins load from the worker cwd. |
| pi | The existing explicit state-owned `-e` task extension; target project extensions remain subject to target trust. |
| grok | The guarded global FirstMate Stop hook reads a per-process `FM_GROK_TURNEND_TOKEN`. |
| kimi | The guarded global FirstMate Stop hook reads a per-process `FM_KIMI_TURNEND_TOKEN`. |

Secondmate launches explicitly clear inherited `FM_HOST_ROOT` and `FM_TARGET_WORKTREE` and retain their isolated-home adapters.

[`docs/verification/supervision.md`](../../../docs/verification/supervision.md#host-root-task-integration) owns the dated lifecycle evidence and current live-verification limits for these task adapters.

## Launch profile axes

`bin/fm-spawn.sh` accepts concrete `--harness`, `--model`, and `--effort` values chosen by firstmate at intake.
Expand Down Expand Up @@ -301,8 +320,9 @@ Project trust dialog can appear on the first pi run in any not-yet-trusted direc
Accept with Enter.
The decision persists per path in `~/.pi/agent/trust.json`, so later spawns in the same worktree slot skip it.

`fm-spawn` keeps the turn-end extension in `state/`, outside the worktree, because project-local extension files make the trust gate strictly worse and pollute the project.
The extension must listen for pi's `turn_end` event, not `agent_end`, so the watcher wakes after each completed turn instead of only when the whole agent run exits.
`fm-spawn` keeps the completion extension in `state/`, outside the worktree, because project-local extension files make the trust gate strictly worse and pollute the project.
In host-root mode, the extension records semantic busy state at `agent_start`, then uses `agent_settled` with `ctx.isIdle()` to record idle before notifying the supervisor after Pi has no queued continuation.
Ordinary Pi workers retain their existing `turn_end` notification, while host-root workers keep it silent because it fires at inner response boundaries during one logical worker run.
Pi sets `PI_CODING_AGENT=true` for its children; this is its harness-detection env marker.

**Primary-session guard fact (verified 2026-07-09, Pi 0.80.5).**
Expand Down Expand Up @@ -335,7 +355,7 @@ The current tmux and Herdr adapters pass their captures and capability descripto
See `docs/herdr-backend.md` "Composer and injection safety" for Herdr's current boundary and `tests/fm-backend-herdr.test.sh` for regression coverage.

Startup dialog: the "Run Grok Build in a project directory?" project picker appears ONLY when grok is launched from a non-project directory (home, Desktop, Downloads, `/tmp`).
`fm-spawn` launches inside the treehouse worktree (a git repo root), so the picker never appears and grok treats the worktree as a trusted project automatically - no post-launch keystroke is needed.
Every ordinary `fm-spawn`, including host-root mode, launches inside the isolated target worktree, which must be a recognized project directory to avoid the picker.
Pin `[hints] project_picker_disabled = true` in `~/.grok/config.toml` if a non-project launch ever needs to skip it.

**TRUECOLOR placeholder styling: covered (task afk-herdr-false-pending, 2026-07-10).**
Expand All @@ -354,11 +374,12 @@ Turn-end hook: grok fires a `Stop` hook at every turn boundary, giving firstmate
grok loads PROJECT hooks (`<worktree>/.grok/hooks/`, `<worktree>/.claude/settings.local.json`) only after the folder is granted hook-trust in `~/.grok/trusted_folders.toml`, which is not automatic and which firstmate will not establish by editing grok's own managed trust store.
GLOBAL hooks in `~/.grok/hooks/` are always trusted and load on first launch.
So `fm-spawn` installs ONE firstmate-owned global hook, `~/.grok/hooks/fm-turn-end.json`, plus the companion `~/.grok/hooks/fm-turn-end.sh`, guarded as a no-op for every non-firstmate grok session.
Its `Stop` command fires only when the current workspace holds a `.fm-grok-turnend` token pointer that matches the firstmate-owned hook registry under `~/.grok/hooks/fm-turn-end.d/`.
`fm-spawn` writes that per-task pointer (`<worktree>/.fm-grok-turnend`, gitignored via git info/exclude like the other harnesses' worktree hook files) and a matching registry entry naming this task's `state/<id>.turn-ended`.
The hook reads `$GROK_WORKSPACE_ROOT`, which is always set for hooks and equals the worktree.
Its `Stop` command fires only when a launch-scoped `FM_GROK_TURNEND_TOKEN` or the current workspace's `.fm-grok-turnend` pointer matches the firstmate-owned hook registry under `~/.grok/hooks/fm-turn-end.d/`.
`fm-spawn` always writes the matching registry entry naming this task's `state/<id>.turn-ended`.
Default launches write the gitignored pointer under the task worktree, while host-root launches pass the token in the worker environment and write no pointer into the host.
The default pointer path reads `$GROK_WORKSPACE_ROOT`, which Grok sets to the launch workspace.
This keeps the hook outside the worktree, needs no trust grant, and writes only firstmate-owned files.
`fm-teardown` removes the worktree pointer before returning a pooled worktree.
`fm-teardown` removes any default-mode worktree pointer before returning a pooled worktree.
Secondmate spawns skip the pointer (idle panes are healthy, no stale-pane detection for them).

**Primary-session guard fact (verified 2026-07-28, Grok 0.2.112 and 0.2.73).**
Expand Down Expand Up @@ -474,7 +495,8 @@ The delivery-only spinner match covers the full moon-phase glyph set rather than

[`docs/turnend-guard.md`](../../../docs/turnend-guard.md) owns Kimi's verified global hook surface and captain-approved crew wake integration.
`fm-spawn.sh` installs one marker-delimited Firstmate entry in `$HOME/.kimi-code/config.toml`, one silent always-zero hook script, and one private token registry under `$HOME/.kimi-code/fm-turn-end.d/`.
Each Kimi crew worktree receives a gitignored `.fm-kimi-turnend` token pointer, and the global hook touches that task's `state/<id>.turn-ended` only when the Stop payload's `cwd`, pointer, and registry entry all agree.
Default Kimi crew worktrees receive a gitignored `.fm-kimi-turnend` token pointer, while host-root launches pass `FM_KIMI_TURNEND_TOKEN` in the worker environment and write no pointer into the host.
The global hook touches that task's `state/<id>.turn-ended` only when the Stop payload has a cwd and the selected token resolves through the private registry.
A guarded silent hook cannot be verified from absence of effect, so prove invocation with an unguarded probe before concluding that the hook did not fire.
The guarded turn-end signal remains a wake notification; standalone Kimi has no busy-state source until one is live-verified.

Expand Down
19 changes: 8 additions & 11 deletions .agents/skills/secondmate-provisioning/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Release happens only on explicit retirement or seed rollback, never on routine r
`bin/fm-home-seed.sh` copies the charter into the secondmate home as `data/charter.md`.
It also writes the gitignored `.fm-secondmate-parent` durable binding before the required `.fm-secondmate-home` identity marker; the parser header in [`bin/fm-secondmate-parent-lib.sh`](../../../bin/fm-secondmate-parent-lib.sh) owns the record contract, and both files must remain in place.
`bin/fm-spawn.sh --secondmate` launches it through the secondmate harness path, resolving `config/secondmate-harness` -> `config/crew-harness` -> the primary's own harness unless an explicit per-spawn harness override is passed.
Secondmates remain outside optional host-root mode: their launch prefix clears any inherited `FM_HOST_ROOT` and `FM_TARGET_WORKTREE`, their metadata has no `host_root=`, and their startup cwd remains the isolated FirstMate home.

`config/secondmate-harness` may also pin a concrete model and effort for the secondmate agent, in the SAME file rather than a new one: the format is a single whitespace-separated line `<harness> [<model>] [<effort>]`, with only the first non-empty, non-comment line parsed.
A bare `<harness>` (today's format, e.g. `claude`) behaves exactly as before - harness only, no model/effort flag - so this is fully backward-compatible.
Expand Down Expand Up @@ -205,17 +206,13 @@ Do not hand off `local-only` items.

## Recovery

For local `kind=secondmate` meta with no window, treat the secondmate as a dead persistent direct report and respawn it with:

```sh
bin/fm-spawn.sh <id> --secondmate
```

Use the recorded `home=` in meta.
If meta is missing but `data/secondmates.md` still registers the secondmate, respawn from the registry entry and its persistent home.
For a remote route, the same command probes and relaunches only on the configured host.
An SSH transport failure or unreadable remote endpoint remains unknown and must be reconciled on that host; never launch a local replacement.
`stuck-crewmate-recovery`'s remote-secondmate note owns why the endpoint-dead and send-failed verdicts that seem to justify this are themselves unreliable.
Retained `kind=secondmate` metadata remains recovery authority even when its window or endpoint field is missing.
Do not delete or rewrite that metadata, and do not invoke a direct same-id `fm-spawn`; direct spawn refuses retained metadata so an ambiguous or incomplete cleanup cannot create a duplicate secondmate.
The locked session-start liveness sweep owns relaunch after the recorded endpoint and verified harness produce a recovery-grade `dead` or `missing` result.
For a remote route, that sweep probes and relaunches only on the configured host; an SSH transport failure or unreadable endpoint remains unknown and must never launch a local replacement.
An absent endpoint field, ambiguous process, unreadable probe, or unverified harness is not relaunch authority; preserve the recorded `home=`, metadata, and endpoint evidence and report the exact blocker.
`stuck-crewmate-recovery`'s remote-secondmate note owns why endpoint-dead and send-failed verdicts can be unreliable.
If meta is missing but `data/secondmates.md` still registers the secondmate, respawn from the registry entry and its persistent on-disk home.
Respawn re-resolves the secondmate harness from current config, uses the same guarded pre-launch sync, and re-propagates inherited local material, so recovered secondmates converge inherited config items and shared captain preferences whenever their home validates; tracked-file sync remains guarded separately.
If the secondmate is already running and only inherited local material changed, prefer `bin/fm-config-push.sh` over respawning.
To move a live LOCAL secondmate onto a newly pinned harness, model, or effort without a full recovery, set `config/secondmate-harness` and then relaunch it with `bin/fm-control.sh <id> relaunch`, which re-resolves that pin, stops the agent, and launches the replacement in the same home ([`docs/agent-control.md`](../../../docs/agent-control.md)).
Expand Down
1 change: 1 addition & 0 deletions .agents/skills/stuck-crewmate-recovery/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Do not sweep another home's endpoints or infer ownership from a matching window

Before relaunch, prove that no live agent still owns the recorded task and that the existing worktree remains available.
Preserve its uncommitted changes and commits, keep the same task identity, and resume or relaunch the recorded harness in that existing worktree with the same brief plus a concise progress note.
For a host-root task, relaunch the harness from the existing recorded worktree, pass it as `FM_TARGET_WORKTREE`, and retain the recorded physical `host_root=` only as the supervisor authority; [`docs/configuration.md`](../../../docs/configuration.md#host-root-mode-fm_host_root) owns that four-root contract.
Do not use a fresh generic spawn while the recorded worktree is unaccounted for, because allocating another worktree can split one task across two copies.
If the worktree or ownership cannot be reconciled safely, leave all state intact and report the task failed or blocked with the conflicting evidence.

Expand Down
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sh text eol=lf
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ jobs:
# worktree acquisition (presentation, workspace-per-home, autodetect).
bin/fm-install-treehouse.sh "$RUNNER_TEMP/bin"
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
- name: Install tasks-axi
run: |
set -eu
npm install -g tasks-axi
tasks-axi --version
- name: Assert Herdr pin and protocol floor
run: |
set -eu
Expand Down
2 changes: 1 addition & 1 deletion .no-mistakes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ document:
# security, Herdr, tmux, and lifecycle coverage). A full-suite override here
# would duplicate CI and defeat the targeted Test contract.
commands:
lint: 'bin/fm-lint.sh'
lint: 'bash bin/fm-lint.sh'

# Store test evidence in this repo so it is committed alongside the change instead of kept in a temp dir.
test:
Expand Down
1 change: 1 addition & 0 deletions .opencode/plugins/fm-primary-cd-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ async function resolveRoot(anchor) {
}

export const FmPrimaryCdCheck = async ({ directory, worktree }) => {
if (process.env.FM_TARGET_WORKTREE) return {};
const root = worktree ? (() => {
try {
return realpathSync(worktree);
Expand Down
1 change: 1 addition & 0 deletions .opencode/plugins/fm-primary-pretool-check.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ async function resolveRoot(anchor) {
}

export const FmPrimaryPretoolCheck = async ({ directory, worktree }) => {
if (process.env.FM_TARGET_WORKTREE) return {};
const root = worktree ? (() => {
try {
return realpathSync(worktree);
Expand Down
1 change: 1 addition & 0 deletions .opencode/plugins/fm-primary-sessionstart-nudge.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ async function resolveRoot(anchor) {
}

export const FmPrimarySessionstartNudge = async ({ client, directory, worktree }) => {
if (process.env.FM_TARGET_WORKTREE) return {};
const root = worktree ? resolvePath(worktree) : await resolveRoot(directory);

return {
Expand Down
1 change: 1 addition & 0 deletions .opencode/plugins/fm-primary-turnend-guard.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ async function letWatchArmRun(sessionID, client) {
}

export const FmPrimaryTurnendGuard = async ({ client, directory, worktree }) => {
if (process.env.FM_TARGET_WORKTREE) return {};
const root = worktree ? resolvePath(worktree) : await resolveRoot(directory);

return {
Expand Down
1 change: 1 addition & 0 deletions .opencode/plugins/fm-primary-watch-arm.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ async function ensureArm(paths, sessionID, client, predecessorArmPid = "", inclu
}

export const FmPrimaryWatchArm = async ({ client, directory, worktree }) => {
if (process.env.FM_TARGET_WORKTREE) return {};
const root = worktree ? resolvePath(worktree) : await resolveRoot(directory);
const paths = effectivePaths(root);
globalThis[COORDINATOR_KEY] = {
Expand Down
Loading