fix(bin): isolate Treehouse worker pools per home to prevent slot collisions - #2
Merged
gk-io-dev merged 7 commits intoSep 17, 2026
Conversation
Treehouse names a pool after the repository it serves, so the primary home and a persistent secondmate holding clones of one remote resolved to a single shared pool and could be handed each other's live slots. Only Claude's workspace-trust check caught the observed cross-owner allocation; no runtime-independent guard existed. Every ship and scout spawn now acquires its slot with `treehouse get --root <base>/fm-home-<hash>`, a deterministic root per canonical FM_HOME owned by fm_treehouse_home_root in bin/fm-wake-lib.sh, and records it as treehouse_root= in the task meta. Teardown reconciles that record against the slot's actual root through fm_treehouse_task_root and returns the slot with the same --root; a record whose root does not contain its worktree refuses before any mutation, for the task itself and for a secondmate's child tasks alike. A record without the field predates it and returns through the pool that allocated it, so existing slots drain with no migration, move, or reinterpretation. Secondmate homes stay the primary's own lease under Treehouse's default root. Spawn also refuses a slot whose owner claim names a task that still has a task record in its home, on every harness and backend, and replaces only a claim whose task record is gone. tests/fm-treehouse-pool-isolation.test.sh pins the contract: two homes with clones of one repo allocate to distinct roots, a task returns through its recorded root, a legacy record returns through its original root, a mismatched root refuses without mutation at spawn and teardown, and a live foreign claim refuses while a stale one is replaced.
…eserving pool isolation
…reign-home ownership guards
…lity documentation
…change; no stale facts found
…(the "wait for 3 fixed test files" watch) — its target logs were already checked manually and the relevant background tasks were stopped after confirming results. Fix remains: tests/fm-secondmate-sync.test.sh, tests/fm-startup-memory-budget.test.sh, tests/fm-session-start.test.sh each had their fake treehouse's `--help` output updated to advertise `--root` alongside `--lease`, resolving the false "MISSING: treehouse" diagnostics that broke Behavior portable serial 1, 2, and 5. No further action needed
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
Restore reliable worker allocation after evidence showed the primary Firstmate home and its persistent secondmate clone can resolve the same project clone to one shared reusable worktree pool.
What Changed
bin/fm-spawn.shresolves each home's own Treehouse root via a newfm_treehouse_home_roothelper, passes it astreehouse get --root <root>for fresh ship/scout allocations, records the absolute root astreehouse_root=in the task'sstate/<id>.meta, and refuses (fresh spawn and relaunch) to launch into a slot whose owner claim names a different canonical home with an extant task record.bin/fm-teardown.shreconciles each task's recordedtreehouse_root(or derives it from the slot's own path for records that predate the field) before everytreehouse return, passing it as--root, and refuses the return outright when the worktree isn't under that reconciled root — including in the descendant/child-worktree cleanup and forced-teardown preflight paths. Secondmate home leases continue to return without--root, unchanged.bin/fm-wake-lib.shadds the shared helpers backing this (fm_treehouse_home_root,fm_treehouse_task_root,fm_treehouse_slot_owner_state) used by both spawn and teardown.bin/fm-bootstrap.shnow probes for both--leaseand--rootsupport (treehouse_supports_required_flags, replacingtreehouse_supports_lease) and emits an upgrade diagnostic if either is missing;bin/fm-install-treehouse.shbumps the pinned Treehouse release to v2.3.0 with updated per-platform checksums.docs/architecture.md,docs/configuration.md, the two.agents/skillsfiles) and existing tests are updated to describe per-home pool isolation and the newTREEHOUSE_ROOTvariable; addstests/fm-treehouse-pool-isolation.test.shcovering allocation, recovery, and return under the new root reconciliation.Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Risk Assessment
✅ Low: Per-home Treehouse root derivation, task-root reconciliation, foreign/same-home claim logic, relative-root resolution, and teardown-return root plumbing are all internally consistent, correctly gated (ship/scout only, never orca/secondmate), fail-closed on ambiguity, and covered by behavioral tests that exercise real spawn/teardown scripts against fake and (gated) real Treehouse binaries rather than asserting on source text; docs match the implemented contract.
Testing
Ran the new dedicated suite (fm-treehouse-pool-isolation.test.sh) plus every other test file the diff touched, all end-to-end against the real shell scripts in isolated tmp homes, with one case driving an actual Treehouse v2.3.0 binary for lease/return. Every scenario passed with no failures; worktree left clean, no stray artifacts.
.) resolves against the spawning repository instead of aborting spawn (R4 fix).treehouse/fixture layout)treehouse get --root <root>to the stable window id, and a slot-claim failure surfaces the correct refusal messagetreehouse get --rootsend-keys text and the 'unreadable…Evidence: fm-treehouse-pool-isolation.test.sh run
Evidence: remaining touched suites (bootstrap, secondmate-safety, spawn-pool-base-freshen, tangle-guard, teardown-endpoint-safety)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
.) resolves against the spawning repository instead of aborting spawn (R4 fix).treehouse/fixture layout)treehouse get --root <root>to the stable window id, and a slot-claim failure surfaces the correct refusal messagetreehouse get --rootsend-keys text and the 'unreadable…bash tests/fm-treehouse-pool-isolation.test.sh (10/10 passed, includes a real Treehouse v2.3.0 binary allocate/recover/return case)bash tests/fm-bootstrap.test.sh (passed, exit=0)bash tests/fm-secondmate-safety.test.sh (passed, exit=0)bash tests/fm-spawn-pool-base-freshen.test.sh (passed, exit=0)bash tests/fm-tangle-guard.test.sh (passed, exit=0)bash tests/fm-teardown-endpoint-safety.test.sh (passed, exit=0)✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.