Skip to content

fix(coord): -Take and -Release recommended -Force on a holder nobody had looked at (BACKLOG #345 Half B) - #151

Merged
wshallwshall merged 2 commits into
mainfrom
claude/backlog-345-half-b
Aug 2, 2026
Merged

fix(coord): -Take and -Release recommended -Force on a holder nobody had looked at (BACKLOG #345 Half B)#151
wshallwshall merged 2 commits into
mainfrom
claude/backlog-345-half-b

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Completes BACKLOG #345. Half A landed in #141; this is the other half.

What

#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, -Take and -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. -Release went further and printed:

If that session is gone, re-run with -Force.

— 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 — -List probed, the other two didn't probe at all.

Holder state -Take blocked -Release refused
gone names the exact take-over commands recommends -Force
present withholds the -Force recipe, says quiet is not dead says ask that session first
unknown / probe failed treat as live, coordinate confirm before -Force

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. The catch returns failed, never gone: an unreadable path must not become a licence to release someone's live claim.

A probe hardwired to gone would pass every positive assertion, so each positive case is paired with the negative one that catches it.

-Force itself 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

  • 4 of 9 new tests fail against main's 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 -List behaviour through the refactor).
  • One assertion was rewritten mid-build after it failed on the patched code — it searched for the token -Force, which the live-holder text legitimately contains inside "do NOT -Force it". 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.
  • 41 coordination tests green; ruff clean; no non-ASCII introduced into a BOM-less script.

Sequencing note

Deferred once on purpose: claim.ps1 had 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

…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
wshallwshall enabled auto-merge (squash) August 2, 2026 16:33
@wshallwshall
wshallwshall merged commit 5f24c75 into main Aug 2, 2026
32 checks passed
@wshallwshall
wshallwshall deleted the claude/backlog-345-half-b branch August 2, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant