fix(teardown): refuse to release a worktree another task still records - #8
Merged
Merged
Conversation
A stale cleanup returned a shared slot and reset the live checkout. Leave that slot in place when another task still records it, and still remove the stale task's own record.
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.
Why
On 1 Oct 2026, tearing down a stale task (
pubmax-map-ui-sweep, whose work had moved elsewhere) returned treehouse slotpubmaxx-bde241/19to the pool while another live task,pubmax-out-honesty-guard, was working in it. That reset the live worker's copy to detached main. Its commits survived, but nothing stopped the release.Change
bin/fm-teardown.sh: before releasing a worktree, look for any otherstate/<id>.metathat records the same worktree path. If that task's endpoint is alive, or it records a different branch, teardown refuses to return, reset, or clean the slot and names the conflicting task. The rest of the stale task's cleanup (its own records, endpoint, hooks it owns) still completes. A dead record on the same branch does not block release, and it never weakens the existing unlanded-work refusal.bin/fm-backend.sh: small helper changes the guard uses to read neighbor endpoint liveness.tests/fm-teardown.test.sh: regression cases for the shared-slot guard.Tests
Reproduced first: with two metas pointing at the same worktree, tearing down the stale one returned the slot and cleaned the neighbor's hook files. After the fix:
bash tests/fm-teardown.test.sh: exit 0, 65 ok, 0 not ok. New cases:bin/fm-lint.sh: exit 0 (ShellCheck 0.11.0, actionlint 1.7.12, pinned).Validation path
This PR skips the no-mistakes pipeline by the captain's decision on 2 Oct 2026, because no-mistakes refuses every available gate agent on the firstmate repo. It ships as a direct PR; GitHub CI is the gate.
🤖 Generated with Claude Code