fix(coord): -Take and -Release recommended -Force on a holder nobody had looked at (BACKLOG #345 Half B) - #151
Merged
Merged
Conversation
…had looked at (BACKLOG #345 Half B) #106 taught `-List` to probe whether a claim's holder still exists on disk. That was the wrong half to fix alone: `-List` is where you BROWSE, and `-Take`/`-Release` are where a session is STOPPED and has to choose between waiting, picking other work, and taking the key. Both blocking paths printed the same "held by another worktree" block whether the holder had been deleted, had died, or was committing that minute -- and `-Release` went further, printing "If that session is gone, re-run with -Force" unconditionally, about a holder it had never probed. That is an instruction to guess, issued at the exact moment the guess is expensive: the cheapest way past the gate was also the one that frees a live session's key. This file's own header records what that costs -- three sessions fixed the same npm advisory on 2026-07-24, two PRs closed as duplicates, and the survivor had not tested what the others found. All three surfaces now share ONE helper, because they had been disagreeing: -List probed, the other two did not probe at all. `-Take` blocked by a vanished holder names the exact take-over commands; blocked by a living one it withholds the -Force recipe entirely and says quiet is not dead. THE ASYMMETRY IS THE DESIGN. A vanished worktree is a fact and the one state safe to act on unasked. Present, undatable and unprobeable all read as "coordinate first", never "probably fine" -- a session can be alive and simply not committing, so silence is not evidence of death. A probe hardwired to 'gone' would pass every positive assertion, so each is paired with the negative case that catches it. The catch returns 'failed', never 'gone': an unreadable path must not become a licence to release someone's live claim. -Force is deliberately untouched. This reports; it does not enforce. Refusing to override a live claim would strand every key whose holder is merely unreachable -- the same orphan, one level up. Verified: 4 of the 9 new tests FAIL against main's claim.ps1 and the other 5 are regression guards that must pass on both sides. One assertion was rewritten mid-build after it failed on the PATCHED code -- it searched for the token `-Force`, which the live-holder text contains inside "do NOT -Force it"; the property wanted is "no runnable recipe", so it now asserts the absence of the command line. Re-checked against unpatched afterwards to prove the rewrite had not made it vacuous. 41 coordination tests green.
wshallwshall
enabled auto-merge (squash)
August 2, 2026 16:33
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.
Completes BACKLOG #345. Half A landed in #141; this is the other half.
What
#106 taught
-Listto probe whether a claim's holder still exists on disk. That was the wrong half to fix alone:-Listis where you browse,-Takeand-Releaseare where a session is stopped and has to choose between waiting, picking other work, and taking the key.Both blocking paths printed the same "held by another worktree" block whether the holder had been deleted, had died, or was committing that minute.
-Releasewent further and printed:— unconditionally, about a holder it had never probed. That's an instruction to guess, issued at the exact moment the guess is expensive: the cheapest way past the gate was also the one that frees a live session's key.
claim.ps1's own header records the cost — three sessions fixed the same npm advisory on 2026-07-24, two PRs closed as duplicates, and the survivor hadn't tested what the others found.The change
All three surfaces now share one liveness helper, because they had been disagreeing —
-Listprobed, the other two didn't probe at all.-Takeblocked-Releaserefused-Force-Forcerecipe, says quiet is not dead-ForceThe asymmetry is the design
A vanished worktree is a fact and the one state safe to act on unasked. Present, undatable and unprobeable all read as "coordinate first", never "probably fine" — a session can be alive and simply not committing, so silence is not evidence of death. The catch returns
failed, nevergone: an unreadable path must not become a licence to release someone's live claim.A probe hardwired to
gonewould pass every positive assertion, so each positive case is paired with the negative one that catches it.-Forceitself is deliberately untouched. This reports; it does not enforce. Refusing to override a live claim would strand every key whose holder is merely unreachable — the same orphan, one level up.Verification
claim.ps1; the other 5 are regression guards that must pass on both sides (including two pinning fix(coord): claim -List measured age and called it staleness #106's-Listbehaviour through the refactor).-Force, which the live-holder text legitimately contains inside "do NOT-Forceit". The property wanted is "no runnable recipe", so it now asserts absence of the command line. Re-checked against unpatched afterwards to prove the rewrite hadn't made it vacuous.ruffclean; no non-ASCII introduced into a BOM-less script.Sequencing note
Deferred once on purpose:
claim.ps1had three sessions in it at once (#106, #140, this). Built once both merged — one round-trip, no rework, no three-way merge.🤖 Generated with Claude Code