Skip to content

feat(bin): launch cmux-backed secondmates in dedicated home-cwd workspaces - #3492

Open
Nitsur10 wants to merge 8 commits into
kunchenguid:mainfrom
Nitsur10:fm/cmux-secondmate
Open

feat(bin): launch cmux-backed secondmates in dedicated home-cwd workspaces#3492
Nitsur10 wants to merge 8 commits into
kunchenguid:mainfrom
Nitsur10:fm/cmux-secondmate

Conversation

@Nitsur10

@Nitsur10 Nitsur10 commented Sep 2, 2026

Copy link
Copy Markdown

Enable bin/fm-spawn.sh <id> --secondmate --backend cmux so a persistent second mate launches in its own dedicated cmux workspace, mirroring the per-home workspace Herdr already provides.

What changed

  • bin/fm-spawn.sh: remove the cmux --secondmate refusal; a secondmate spawn creates one dedicated workspace whose cwd is the secondmate's home (never a project worktree). The Orca refusal stays.
  • Title scoping: the secondmate workspace deliberately carries the launching primary's home label (fm-<primary-hometag>-<id>), because the primary owns the task record and performs every send/peek/state/teardown/recovery op with its own FM_HOME, and fm_backend_cmux_target_ready re-derives the expected title from the caller's home on every op. The 2ndmate-<id> label namespace remains what the secondmate's own crewmate workspaces carry. Contract documented in bin/backends/cmux.sh and the spawn header (one-owner rule).
  • Honest liveness limit: cmux has no recovery-grade agent-state classifier (fm_backend_agent_state returns unverified), so a dead cmux secondmate is preserved and reported by the startup liveness sweep, never auto-relaunched; --relaunch remains refused. Documented in docs/cmux-backend.md instead of claiming recovery works.
  • Remote second mates remain Herdr-only (bin/fm-remote-secondmate-control.sh enforces this independently).

Tests

  • tests/fm-backend-cmux.test.sh: new full-spawn secondmate regression on a subcommand-aware fake cmux CLI, asserting the primary-scoped title, home cwd, and full metadata (backend=cmux, workspace/surface UUIDs, window=, worktree=/home= = the secondmate home).
  • tests/fm-backend-cmux-smoke.test.sh: guarded live secondmate spawn against the real app using an fm-test- id, a throwaway seeded home, and the raw-launch-command escape hatch; cleanup only through tests/cmux-test-safety.sh.
  • Verified live on cmux 0.64.20 build 100, macOS aarch64, 2026-09-01 (recorded in docs/verification/runtime-backends.md). Orca secondmate-refuse regression still green; bin/fm-lint.sh clean.

Docs

docs/cmux-backend.md (new Secondmate launch section, updated active limits), docs/configuration.md, docs/verification/runtime-backends.md, plus stale refusal mentions in docs/architecture.md, docs/remote-secondmates.md, and docs/trace-context.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SEApWYsEQrv9oTAr2RwUQq

…paces

Remove fm-spawn.sh's cmux --secondmate refusal: a secondmate spawn now
creates one dedicated cmux workspace whose cwd is the secondmate's home,
titled with the launching primary's home label so every primary-side op,
recovery, and cleanup verifies unchanged. Orca still refuses. cmux has no
recovery-grade agent-state classifier, so a dead cmux secondmate is
preserved and reported, never auto-relaunched; documented as an active
limit. Adds a full-spawn fake-CLI regression and a guarded fm-test- live
smoke case, plus dated live evidence (cmux 0.64.20, 2026-09-01).
@greptile-apps

greptile-apps Bot commented Sep 2, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Reviews (4): Last reviewed commit: "no-mistakes(review): reclaim per-run tas..." | Re-trigger Greptile

Comment thread tests/fm-backend-cmux-smoke.test.sh Outdated
Comment thread tests/fm-backend-cmux-smoke.test.sh
…ed temp in smoke cleanup

Address PR review: resolve an unrecorded fm-test- secondmate workspace by
its scoped title before the guarded close so a partial spawn cannot leak
it, and remove /tmp/fm-<id> only when this run observed it absent first.
Comment thread tests/fm-backend-cmux-smoke.test.sh Outdated
Comment thread tests/fm-backend-cmux-smoke.test.sh Outdated
The title-based workspace fallback now adopts only an id absent from a
pre-spawn snapshot, so a leftover workspace this run did not create is
never closed on a reusable title match alone. The /tmp/fm-<id> temp root
is deliberately left in place because no ownership check on a shared /tmp
path is free of check-to-delete races.
Comment thread tests/fm-backend-cmux-smoke.test.sh Outdated
…rship holds

A reusable scoped title left every fallback-close ownership proof exposed
to some race: a pre-existing leftover, a transiently failed snapshot read,
or a concurrent invocation creating the same title after the snapshot.
A per-run unique id removes the shared title entirely, so a live workspace
carrying it can only be this run's own spawn, and the snapshot machinery
is no longer needed. A crashed run's leftover keeps its own old title and
is left open for recoverable by-hand cleanup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant