Skip to content

feat: adopt existing cmux workspaces for supervision - #261

Open
ss251 wants to merge 7 commits into
kunchenguid:mainfrom
ss251:fm/adopt-existing-session
Open

feat: adopt existing cmux workspaces for supervision#261
ss251 wants to merge 7 commits into
kunchenguid:mainfrom
ss251:fm/adopt-existing-session

Conversation

@ss251

@ss251 ss251 commented Jul 5, 2026

Copy link
Copy Markdown

Intent

Add an fm-adopt command so firstmate can supervise an already-running cmux workspace (kind=adopted) without spawning a new worktree or branch; peek/send/watcher work on it and teardown un-registers it without ever closing the workspace. Implements issue #260. cmux-only, experimental, supervise-only.

What Changed

  • Added bin/fm-adopt.sh and tests for registering an existing cmux workspace as kind=adopted so firstmate can supervise it without spawning a new worktree, branch, or process.
  • Wired adopted cmux targets into session-start, crew-state, watcher, backend, and teardown paths, including duplicate-window protection and liveness checks that do not depend on readable screen output.
  • Documented the adopted-session workflow and constraints across the operator docs, script reference, architecture/configuration notes, and cmux backend guide.

Risk Assessment

✅ Low: Captain, the change is scoped to cmux adoption paths and the shared watch/peek/send/teardown integrations look consistent with the intended supervise-only behavior.

Testing

  • ⏭️ Test - skipped

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed ✅
  • ⚠️ bin/fm-adopt.sh:79 - fm-adopt only rejects an existing task id, but it never rejects an existing window=<workspace>:<surface> already registered under another id. The watcher and window_to_task resolve a window to the first matching meta file, so double-adopting a surface or adopting a firstmate-spawned cmux task can make stale handling, peek/send ownership, and teardown bookkeeping attach to the wrong task or skip stale wakes entirely. After resolving T, scan state/*.meta for the same window= and refuse it.
  • ⚠️ bin/fm-adopt.sh:98 - Adoption accepts a live cmux surface based on list-panes, but fm-crew-state.sh later treats non-tmux liveness as fm_backend_capture, which for cmux calls read-screen. The cmux adapter documents that read-screen fails on fresh never-written surfaces, so an adopted live workspace can immediately report backend target gone. Use fm_backend_target_exists for the adopted cmux liveness probe before falling through to busy/log classification.

🔧 Fix: Harden adopted cmux supervision
✅ Re-checked - no issues remain.

⏭️ **Test** - skipped

Step was skipped.

✅ **Document** - passed

✅ No issues found.

⏭️ **Lint** - skipped

Step was skipped.

✅ **Push** - passed

✅ No issues found.

@kunchenguid

Copy link
Copy Markdown
Owner

Thanks for the PR! It looks like this branch has a merge conflict with the base branch right now. When you get a chance, could you rebase onto (or merge in) the latest base branch, resolve the conflict, and push? Once GitHub shows the PR as mergeable again, it'll be picked back up for review.

Noted for firstmate#261 at b2f4d9f5.

@ss251

ss251 commented Jul 6, 2026

Copy link
Copy Markdown
Author

Thanks for the PR! It looks like this branch has a merge conflict with the base branch right now. When you get a chance, could you rebase onto (or merge in) the latest base branch, resolve the conflict, and push? Once GitHub shows the PR as mergeable again, it'll be picked back up for review.

Noted for firstmate#261 at b2f4d9f5.

sure, will do!

@ss251
ss251 force-pushed the fm/adopt-existing-session branch from b2f4d9f to 930f4f4 Compare July 7, 2026 00:24
@ss251

ss251 commented Jul 7, 2026

Copy link
Copy Markdown
Author

@kunchenguid ready for review 🫡

@kunchenguid

kunchenguid commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR! It looks like this branch has a merge conflict with the base branch right now. When you get a chance, could you rebase onto (or merge in) the latest base branch, resolve the conflict, and push? Once GitHub shows the PR as mergeable again, it'll be picked back up for review.

Noted for firstmate#261 at b0499886.

@ss251
ss251 force-pushed the fm/adopt-existing-session branch 3 times, most recently from 0ab7314 to fcab951 Compare July 9, 2026 00:14
@ss251

ss251 commented Jul 9, 2026

Copy link
Copy Markdown
Author

Rebased onto the latest main and resolved the conflicts — the PR shows mergeable again.

I also followed up on the triage note flagging that the two review bugs were reported as auto-fixed but hadn't actually landed. That was correct: both were still present in the diff. Fixed both now, each with a regression test:

  • fm-adopt.sh — it only checked $STATE/$ID.meta, so the same live cmux surface could be adopted a second time under a different task id (two tasks supervising/sending into one surface). It now scans state/*.meta for a matching window= and refuses, naming the task already on that surface.
  • fm-crew-state.sh — the kind=adopted liveness probe used read-screen, which fails on a genuinely fresh surface that has never been written to (per docs/cmux-backend.md), so a freshly-adopted, untouched workspace was misreported as backend target gone. It now uses the structural list-panes existence check (scoped to cmux; herdr/tmux paths unchanged).

Local verification: shellcheck clean; fm-adopt (11, incl. 2 new tests), fm-crew-state (39), fm-teardown (25), fm-backend (29) all green.

@kunchenguid

kunchenguid commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR! This branch currently has a merge conflict with the base branch.

When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again.

Noted for firstmate#261 at 095fb41f.

@ss251
ss251 force-pushed the fm/adopt-existing-session branch from 095fb41 to 7a2e8ed Compare July 10, 2026 21:12
@kunchenguid kunchenguid removed the wheelhouse:pending-contributor-action Managed by Wheelhouse label Jul 10, 2026
@kunchenguid

Copy link
Copy Markdown
Owner

Thanks for the PR! This branch currently has a merge conflict with the base branch.

When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again.

Noted for firstmate#261 at 7a2e8ed2.

@ss251

ss251 commented Jul 14, 2026

Copy link
Copy Markdown
Author

Rebased onto the latest main after your last note — conflicts are resolved and the PR has been mergeable with all 4 checks green since then. Ready for review whenever you get a chance.

@kunchenguid

kunchenguid commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch.

When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again.

Noted for firstmate#261 at f1db4f6a.

@ss251
ss251 force-pushed the fm/adopt-existing-session branch from f1db4f6 to f70012d Compare July 16, 2026 04:26
@kunchenguid kunchenguid removed the wheelhouse:pending-contributor-action Managed by Wheelhouse label Jul 16, 2026
@ss251

ss251 commented Jul 16, 2026

Copy link
Copy Markdown
Author

The Behavior-tests failure on this PR is inherited from main, not introduced here — main's own push CI is red with the identical failure since #593 landed (run 29468970390, not ok - old fm-teardown.sh (scout, report present) should succeed).

Root cause: #593's unresolved-decision completion gate has fm-teardown.sh's scout path invoke "$SCRIPT_DIR/fm-decision-hold.sh" verify, but tests/fm-backend.test.sh's old-bin conformance shim (OLD_BIN_UNCHANGED_SIBLINGS) was never taught about it — so in the shim the helper doesn't exist, the gate reads as failed, and the OLD run REFUSES. (fm-supervision-lib.sh is likewise missing from the list, which is why every shim run also logs fm-guard.sh: ... No such file or directory stderr noise — non-fatal only because guards are || true.)

I've pushed the one-line fix here (324f9cb): both scripts added to the shim's sibling list. With that, tests/fm-backend.test.sh passes 28/28 locally (tasks-axi 0.2.3 installed, baseline = current main), including the scout-teardown conformance test with byte-identical old-vs-new command logs. Happy to split it into its own PR instead if you'd rather fix main independently — it applies cleanly to main as-is.

This was referenced Jul 30, 2026
ss251 added 6 commits August 1, 2026 01:53
Register an already-running cmux workspace as a kind=adopted task with
no worktree and no branch. Teardown un-registers without ever closing
the workspace, the watcher exempts it from stale-pane wakes, and
peek/send target it by pure UUID so the human's title is preserved.
cmux-only and experimental; supervise-only (no delivery mode or PR).

Refs kunchenguid#260
…and restore lock recovery

The kind=adopted branch was added ahead of validate_worktree_teardown_safety
but as an elif AFTER it, which caused two defects:

1. validate_worktree_teardown_safety emits REFUSED as a side effect, so
   calling it before the adopted check printed a spurious REFUSED when tearing
   down an adopted task (whose worktree= is the human's own live, unlanded cwd).
   Fixed by checking kind=adopted first, so the safety function never runs for
   adopted tasks.

2. safety_rc=$? then captured the [ "$KIND" = adopted ] test's exit code
   instead of the safety function's (shellcheck SC2319), which silently killed
   the stale-lock recovery path (safety_rc was always 1, never LOCK_BLOCKED).
   Fixed by capturing the code with 'validate... || safety_rc=$?' - set -e-safe
   and unambiguous - restoring lock-blocked recovery.

Verified: shellcheck clean, tests/fm-teardown.test.sh (25) and
tests/fm-adopt.test.sh (9) all pass.
docs/cmux-backend.md's empirical verification transcript captured a real
personal absolute path (/Users/thescoho/Developer/reddit-hackathon), which
tests/fm-kimi-harness.test.sh's repo-wide /Users/ scan correctly flags.
@kunchenguid

kunchenguid commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch.

When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again.

Noted for firstmate#261 at eb895c55.

…s adopted tasks

upstream/main's endpoint-cleanup hardening (fbece9c) now requires every
non-tmux backend's meta to carry endpoint_task_id, matching what
fm-spawn.sh has always written. fm-adopt.sh never wrote it, so an
adopted cmux task's teardown was refused as a legacy/unbound endpoint.
Write endpoint_task_id the same way fm-spawn.sh does, and update the
test fixture and assertion to match.
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.

2 participants