feat: lease secondmate homes with treehouse - #43
Merged
Conversation
Replace the SHELL-runner path-capture hack in acquire_treehouse_home with treehouse get --lease --lease-holder <id> (v1.8.0), which durably leases the worktree so the home survives with no live process and is never recycled by a later get/prune until released. Thread the secondmate id through ensure_home into the lease holder. Teardown and seed rollback already release via treehouse return, which clears the lease in v1.8.0; document that intent. Existing process-held homes (e.g. homemux-h7) keep their old hold until reprovisioned; only new provisioning leases. Update the secondmate treehouse mock to support get --lease/--lease-holder and return <path>, and assert the lease holder is set on acquire and released on retirement.
leo1oel
referenced
this pull request
in leo1oel/nemo
Jun 23, 2026
Bring the upstream secondmate feature (PRs #37/#42/#43/#31/kunchenguid#45) to herdr-backend, rewriting every treehouse/tmux mechanism into the herdr equivalents this branch already uses. A secondmate is a crewmate whose workspace is an isolated firstmate home (its own FM_HOME) and whose brief is a charter; it runs the same spawn/brief/status/watch/teardown/recovery lifecycle and is idle by default. treehouse -> herdr mapping: - Home leasing -> a herdr worktree of the firstmate repo. fm-home-seed.sh `-` runs `herdr worktree create --cwd $FM_ROOT --branch secondmate-<id>` and records the worktree path + open_workspace_id; herdr never recycles a worktree, so persistence is automatic and all lease/return bookkeeping is dropped. The workspace id is stored beside the home marker (.fm-secondmate-home.workspace) so retirement can find it. - Retirement / seed rollback -> `herdr worktree remove --workspace <ws> --force`. An explicit <home> path stays a plain directory home (a git clone, no herdr worktree); spawn opens a workspace for it on the fly via `herdr workspace create` and teardown closes it with `herdr workspace close` then deletes the dir. - firstmate_home_has_treehouse_slot -> "does the home record a workspace marker"; if yes remove via herdr, else plain rm. New: bin/fm-home-seed.sh (charter fill, project cloning, no-mistakes init, registry edits, transactional rollback, validate subcommand all ported as-is), bin/fm-backlog-handoff.sh (no treehouse/tmux; near-verbatim). Edits (re-implemented on the diverged herdr-backend files, not applied as upstream hunks): fm-spawn.sh (--secondmate path, FM_HOME indirection, registry/home resolution, launch in home, meta records home=/home_workspace=/projects=), fm-teardown.sh (kind=secondmate retirement via herdr, child-work refusal + --force discard, plus #31: allow teardown when work is on any remote incl. a fork), fm-brief.sh (--secondmate charter scaffold), fm-watch.sh (skip stale-pane wakes for kind=secondmate), fm-project-mode.sh (honor FM_HOME/FM_DATA_OVERRIDE so a secondmate resolves its own projects.md). kunchenguid#45: dropped the ':' from the afk skill description. Skipped fm-bootstrap.sh / fm-harness.sh (removed on this branch). Docs: AGENTS.md + README.md gain herdr-flavored secondmate sections (concept, secondmates.md routing table, fm-home-seed usage, idle-by-default contract, backlog handoff, kind=secondmate recovery, watch idle) with no treehouse/tmux wording. Tests: new herdr-stubbed tests/fm-secondmate.test.sh drives the real scripts against a stub `herdr` over the full lifecycle (seed `-`, register, validate dup ids/homes/overlap, spawn, backlog handoff, retire); tests/fm-teardown.test.sh ports the #31 any-remote/fork matrix to herdr. shellcheck bin/*.sh tests/*.sh clean; 5/5 test scripts pass.
vipentti
pushed a commit
to vipentti/firstmate
that referenced
this pull request
Aug 5, 2026
* feat(secondmate): adopt treehouse durable lease for secondmate homes Replace the SHELL-runner path-capture hack in acquire_treehouse_home with treehouse get --lease --lease-holder <id> (v1.8.0), which durably leases the worktree so the home survives with no live process and is never recycled by a later get/prune until released. Thread the secondmate id through ensure_home into the lease holder. Teardown and seed rollback already release via treehouse return, which clears the lease in v1.8.0; document that intent. Existing process-held homes (e.g. homemux-h7) keep their old hold until reprovisioned; only new provisioning leases. Update the secondmate treehouse mock to support get --lease/--lease-holder and return <path>, and assert the lease holder is set on acquire and released on retirement. * no-mistakes(review): Captain, harden treehouse lease lifecycle * no-mistakes(document): Document lease lifecycle
This was referenced Aug 7, 2026
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
Adopt treehouse v1.8.0's durable worktree lease in firstmate's secondmate-home lifecycle, replacing the fragile process-based hold plus path-capture hack.
Background: a secondmate's home is a treehouse worktree of the firstmate repo acquired at seeding. The old acquire_treehouse_home() ran 'treehouse get' with a throwaway custom SHELL runner ONLY to capture the worktree path from the subshell's PWD, then let the subshell exit - which returned the worktree to the pool, so the home only persisted because a live process happened to keep it in use. treehouse v1.8.0 adds a real durable lease.
Changes made:
Deliberate scope choice: existing process-held homes (e.g. live secondmate homemux-h7, acquired before v1.8.0) are intentionally NOT retroactively leased - only new provisioning uses the lease; they keep the old hold until reprovisioned. This is noted for the PR.
Validation done locally: all 5 test scripts pass (110 assertions) and shellcheck bin/.sh tests/.sh is clean, matching CI.
What Changed
treehouse get --lease --lease-holderprovisioning for secondmate homes, with retirement and rollback paths releasing leased slots throughtreehouse return --force.Risk Assessment
✅ Low: Captain, the changes are narrowly scoped to the secondmate lease lifecycle, add bootstrap coverage for the required treehouse feature, and preserve failure paths without introducing a material merge risk.
Testing
Inspected the lease-related diff and docs, ran all six shell behavior test scripts, then captured a focused end-to-end CLI transcript proving seed acquires a durable secondmate lease and teardown releases it. All checks passed, the worktree stayed clean, and I did not run linters or static analysis per the prompt.
Evidence: Focused CLI lease seed and teardown transcript
Evidence: Secondmate lifecycle behavior test log
Evidence: Bootstrap feature-probe behavior test log
Evidence: Teardown regression behavior test log
/var/folders/5x/4nqprlbx0518k3ybcb1sz6gr0000gn/T/no-mistakes-evidence/01KVRW18PP6HKJ5779PP3318PE)Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 3 issues found → auto-fixed ✅
bin/fm-home-seed.sh:468-acquire_treehouse_homenow requires the v1.8.0treehouse get --leaseflag, but bootstrap still only checks that sometreehousebinary exists. A pre-1.8 install will pass startup and fail later during secondmate seeding, so add a bootstrap feature/version probe forget --leaseand surface the normal install/upgrade instruction there.bin/fm-teardown.sh:281- On secondmate retirement, falling back tosafe_rm_rfaftertreehouse returnfails can remove a leased worktree directory while leaving the durable lease recorded in treehouse state, then the script clears meta and registry as if release succeeded. For homes registered as firstmate treehouse worktrees, teardown should fail unlesstreehouse return --forcesucceeds; reserve raw removal for plain-clone homes with no treehouse pool slot.bin/fm-home-seed.sh:638- Rollback suppressestreehouse returnfailures for newly leased homes, so a failed seed can leave the durable lease held with no visible cleanup warning. Since the registry is never written in that path, make release failure visible at least, and preferably preserve enough evidence for manual cleanup instead of silently swallowing it.🔧 Fix: Captain, harden treehouse lease lifecycle
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
git status --short --branchgit diff --stat ef1107d41c7ef710bdb2e27aa64bebdf94f2e027..bf195ee8ab8dbd8fe3e7e8e553c0776ab50e7062git diff --unified=80 ef1107d41c7ef710bdb2e27aa64bebdf94f2e027..bf195ee8ab8dbd8fe3e7e8e553c0776ab50e7062 -- bin/fm-home-seed.shgit diff --unified=80 ef1107d41c7ef710bdb2e27aa64bebdf94f2e027..bf195ee8ab8dbd8fe3e7e8e553c0776ab50e7062 -- bin/fm-teardown.shgit diff --unified=60 ef1107d41c7ef710bdb2e27aa64bebdf94f2e027..bf195ee8ab8dbd8fe3e7e8e553c0776ab50e7062 -- tests/fm-secondmate.test.shgit diff --unified=60 ef1107d41c7ef710bdb2e27aa64bebdf94f2e027..bf195ee8ab8dbd8fe3e7e8e553c0776ab50e7062 -- tests/fm-bootstrap.test.sh README.md AGENTS.mdtests/fm-bootstrap.test.sh > /var/folders/5x/4nqprlbx0518k3ybcb1sz6gr0000gn/T/no-mistakes-evidence/01KVRW18PP6HKJ5779PP3318PE/fm-bootstrap.test.log 2>&1tests/fm-secondmate.test.sh > /var/folders/5x/4nqprlbx0518k3ybcb1sz6gr0000gn/T/no-mistakes-evidence/01KVRW18PP6HKJ5779PP3318PE/fm-secondmate.test.log 2>&1tests/fm-teardown.test.sh > /var/folders/5x/4nqprlbx0518k3ybcb1sz6gr0000gn/T/no-mistakes-evidence/01KVRW18PP6HKJ5779PP3318PE/fm-teardown.test.log 2>&1tests/fm-spawn-batch.test.sh > /var/folders/5x/4nqprlbx0518k3ybcb1sz6gr0000gn/T/no-mistakes-evidence/01KVRW18PP6HKJ5779PP3318PE/fm-spawn-batch.test.log 2>&1tests/fm-wake-queue.test.sh > /var/folders/5x/4nqprlbx0518k3ybcb1sz6gr0000gn/T/no-mistakes-evidence/01KVRW18PP6HKJ5779PP3318PE/fm-wake-queue.test.log 2>&1tests/fm-afk-inject-e2e.test.sh > /var/folders/5x/4nqprlbx0518k3ybcb1sz6gr0000gn/T/no-mistakes-evidence/01KVRW18PP6HKJ5779PP3318PE/fm-afk-inject-e2e.test.log 2>&1Focused manual CLI check captured inlease-e2e.transcript: seeded a secondmate withhome=-, verified the lease holder, marker, project clone, and registry route, then retired it and verifiedtreehouse return --force, lease removal, home removal, registry cleanup, and meta cleanup.git status --short✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.