fix(bin): lease ship and scout worktrees until teardown - #10
Merged
Conversation
Plain treehouse get only marks a pool slot in-use while a process holds it, so a parked task with unpushed commits could be handed to the next spawn and destroyed (kunchenguid#1441). Lease the slot with get --lease --lease-holder <task-id> (same shape as secondmate home seeding), then cd the worker into the known path and keep the landing confirmation. Teardown still releases only via a successful treehouse return; a refused teardown never reaches return.
Restore cmux/zellij/verification backend pages unchanged. Keep only the architecture worktree-lease contract lines that describe durable ship/scout leasing, refused-teardown retention, and holder-scoped abort release.
Post-create abort still needs isolation to refuse after the endpoint exists. With host-side get --lease, the fixture must hand out the armed non-worktree path so landing can match the poisoned pane cwd and validation still fails.
Focus-safe emptying close may remove the projected last pane without a pane.close audit row. Concurrent abort still serializes under the presentation lock; accept create-only sequences and keep pane-gone and focus checks as the proof.
No-op treehouse return on the synthetic abort path so real treehouse never touches the lab pool for it, and re-pin captain focus before projected shape teardown after pane-death abort cleanup.
Leased ship/scout workers have their shell cwd in the worktree. Returning the slot first kills that shell via pane-death and steals captain focus without the focus-preserving close path. Close under the presentation lock first, confirm the pane is gone, then release the lease.
Ship/scout spawns now call treehouse get --lease in-process. The crew path in fm-secondmate-harness only faked tmux, so crew-unaffected failed before meta was written. Match the shared lib stub for get --lease / return.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Lease ship/scout worktrees at spawn and release them at successful teardown only. MINIMAL CHANGE WITH A HARD SCOPE FENCE for firstmate shared tracked material.
Defect: bin/fm-spawn.sh sent plain
treehouse getinto the worker terminal. Plain get takes an AVAILABLE pool slot and does NOT lease it, so a slot still holding a parked task's worktree (with unpushed commits) counts as available and can be handed to the next spawn. That destroyed unrecoverable work on ampos-o9o.31 (kunchenguid#1441).Naive flag swap fails:
treehouse get --leaseprints the path and exits without opening a subshell, so spawn's landing wait (pane cwd change) breaks. Correct shape matches bin/fm-home-seed.sh: lease with--lease --lease-holder <task-id>, then send the worker into the leased path (cd), keeping isolation assertion and landing confirmation adapted to a known-in-advance path.IN SCOPE only: bin/fm-spawn.sh (lease then enter path), bin/fm-teardown.sh (release lease only when treehouse return succeeds), and tests. OUT OF SCOPE: home lock, retirement boundary, spawn concurrency locks, any backend adapter, install/bootstrap/CI/skills/AGENTS.md, recovery/relaunch lease semantics, pre-existing unleased worktrees.
Non-negotiable: REFUSED teardown must NOT release the lease (uncommitted/unlanded work is exactly what the lease protects). Concurrent distinct-task spawns must both succeed without serializing setup under a firstmate lock.
Acceptance: leased slot not returned by subsequent plain treehouse get; successful teardown releases; refused teardown keeps lease; concurrent distinct spawns work; existing spawn isolation and teardown tests stay green. Soft file-count fence ~5 files (landed at 7 with required test-adapter updates only).
What Changed
Risk Assessment
✅ Low: The change is narrowly scoped and the holder-guarded abort cleanup closes the prior issue without weakening refused-teardown lease retention.
Testing
The clean assigned target was checked against its base; focused lease, landing, cleanup-safety, backend, and isolation regressions passed without skips. A CLI transcript demonstrated the complete slot lifecycle, and the installed Treehouse CLI confirmed the lease-holder and guarded-return flags. The broad suite, lint, formatters, and static analysis were not run per the targeted test-phase boundary.
Evidence: Lease lifecycle CLI transcript
Spawn reserved slot-1; a later plain allocation received slot-2. Successful cleanup released slot-1, refused cleanup retained its holder without calling return, and two distinct tasks spawned concurrently with separate leases.Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 1 issue found → auto-fixed ✅
bin/fm-spawn.sh:347- Intent requires “release them at successful teardown only,” but this new EXIT path runstreehouse return --force "$WT"after any pre-metadata spawn failure, including landing timeout or isolation refusal. This releases the lease outside teardown and beforevalidate_spawn_worktreeruns at line 1370. Decide whether failed-spawn rollback is an authorized exception; otherwise remove this return and retain the lease. If it is authorized, document the exception and validate both the path and--if-lease-holder "$ID"before force-returning it.🔧 Fix: Scope failed-spawn lease cleanup to task holder
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
git status --short --branch;git rev-parse HEAD; diff stat and name-status for2ef842cb530967264ba0f4835249f247b2c2fa40..ff8d151f6a8aa8adf0eba8ff6f08fdae20e5ae71bin/fm-test-run.sh tests/fm-spawn-worktree-lease.test.sh tests/fm-spawn-worktree-settle.test.sh tests/fm-teardown.test.sh tests/fm-backend.test.sh tests/fm-tangle-guard.test.shDeterministic two-slot Treehouse evidence harness invoking the actualbin/fm-spawn.shandbin/fm-teardown.shtreehouse get --help;treehouse return --helpPost-testgit status --short --branchbin/backends/tmux.sh:82- Backend adapter comments in tmux, Herdr, Zellij, and cmux still describe plain treehouse-get subshell discovery. The hard scope fence forbids editing backend adapters; a separately authorized comment-only cleanup should describe leased-worktree landing confirmation while preserving the empirical subshell limitations.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.