Skip to content

docs(worktree): the FENCE UNAVAILABLE list names every unplaceable shape - #1246

Merged
wshallwshall merged 1 commit into
mainfrom
fencepara
Sep 17, 2026
Merged

wshallwshall merged 1 commit into
mainfrom
fencepara

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Comment only, inside scripts/worktree/prune-merged.ps1's .DESCRIPTION block. No behaviour change.

What was wrong

The FENCE UNAVAILABLE paragraph said availability requires "at least one config root with a session
registry, at least one readable record, and NO record that failed to parse". That named one of three
unplaceable shapes, and it was already short by one before #1243 -- the cwd-less record shape predates
that work. #1243 added the third.

Where the new text comes from

Get-WorktreeOccupancy in scripts/coord/occupancy.ps1, read at 1966f753d. Not from the comment it
replaces -- that comment is the thing under test, so it is not evidence.

Available is withheld on five conditions, and the paragraph now splits them by kind rather than
listing them flat:

Lines Condition Kind
253-261 $worktrees.Count -eq 0 -> RepoFound false could not look
277-285 catch around Get-ClaudeConfigRoots / Get-SessionRecords could not look
333-335 $roots.Count -eq 0 could not look
336-340 $faults.Count -gt 0 -- three shapes looked, could not place
341-343 $records.Count -eq 0 could not look

The split is the point. Four mean the fence was blind. The fifth refuses on positive evidence that a
session exists and cannot be placed, which is the only one that can refuse because it saw something.

Two things a reader would otherwise re-derive are now stated: the ladder tests faults before the
empty-record count, and RepoFound false reaches the Available gate on the second read (the
re-check at 1101 reads $occ2.Available with no RepoFound guard; RepoFound appears once in this
script, at 227).

Verification

Flattened differential against origin/main, because the old phrase wraps across lines 84-85 and a
naive literal search returns False for patched and unpatched alike -- a check that cannot fail:

Check patched main
old one-shape wording False True
new three-shape list True False
two-family split True False
deregistered-checkout shape True False
ladder-order note True False

Every row inverts. Gates, each zero beside a control that fired: 0 cp1252-unencodable (control U+2500
fires; the CI gate is encodability, not ASCII), 0 non-ASCII, .DESCRIPTION max width still 104 with
nothing over it and added lines topping out at 103, 0 tabs, 0 trailing-whitespace lines. PowerShell
parser 0 errors, against a control reporting 2 on deliberately broken script.

No test reads this paragraph: git grep 'FENCE UNAVAILABLE' origin/main returns two hits, both prose in
the scripts themselves, against a control of prune-merged appearing in 20 files. So nothing gated this
and nothing would have caught the drift.

Not fixed here

scripts/coord/presence.ps1:180 prints "Nothing was examined, so nothing can be concluded" on an
unavailable roster. That is false on the fault path -- every record was examined and one could not be
placed, and RecordsExamined can be large. Wrong before this work, unaffected by it, and it changes
operator-visible output rather than a comment. It wants its own row.

prune-merged.ps1:856-857 does not share that defect: it interpolates $occ.Detail and adds no
claim of its own.

prune-merged.ps1's header said the fence is available given "at least one
config root with a session registry, at least one readable record, and NO
record that failed to parse". That named one of three unplaceable shapes.

READ FROM Get-WorktreeOccupancy IN scripts/coord/occupancy.ps1, not from the
comment it replaces. The prior text is the thing under test, so it is not
evidence of anything. Line numbers below are that function at 05a37c1.

Available is withheld on FIVE conditions, not three:

  253-261  $worktrees.Count -eq 0            RepoFound false
  277-285  catch around Get-ClaudeConfigRoots / Get-SessionRecords
  333-335  $roots.Count -eq 0
  336-340  $faults.Count -gt 0
  341-343  $records.Count -eq 0

THE SHAPE THAT MATTERS IS NOT THE COUNT, IT IS THE SPLIT. Four of the five mean
the fence could not look: nothing was examined, so nothing is cleared. The
fifth means it looked and found a session it cannot place. That is the only
refusal resting on positive evidence -- a session demonstrably exists, the
fence cannot say which tree it is in, and the tree could be the one the run is
about to delete. A flat list of five loses that, so the paragraph is now two
bullets and not an enumeration.

The unplaceable family has three shapes, built at 291-292 (a file that will not
parse), 301-305 (parses, carries no cwd) and 327-328 via
Get-UnplaceableCwdReason (a cwd that is a checkout of this repo which
`git worktree list` no longer carries). The third is the state this script's own
incident produces: deregister a worktree out from under its occupant and that
session's recorded cwd names a checkout git has stopped listing. The header
already tells that incident eleven lines above and did not connect it.

TWO THINGS A READER WOULD OTHERWISE RE-DERIVE, both now stated:

The ladder tests faults BEFORE the empty-record count, so a registry holding
nothing but unreadable files reports the unplaceable record rather than "not one
readable record".

RepoFound false reaches the Available gate on the SECOND read. RepoFound appears
exactly once in this script (line 227, which exits at 230), but the re-check
before each removal at 1101 reads $occ2.Available alone, and 1107-1110 prints
that Detail and skips. An earlier draft of this paragraph said the condition
never surfaces here. It was wrong and is recorded rather than quietly dropped,
because the reason it was wrong -- one guarded call site read as the only call
site -- is the error a later reader would repeat.

NO BEHAVIOUR CHANGE. Comment text only, inside the .DESCRIPTION help block.

Measured on the patched file, each zero beside a control that fired:
cp1252-unencodable characters 0, against a control where U+2500 fires and U+2014
deliberately does not, since tests/test_cp1252_console_safety.py gates on
encodability rather than on ASCII; non-ASCII 0, control ord(U+2014) > 127 true;
tabs 0 and trailing-whitespace lines 0, both detectors fired on planted text;
.DESCRIPTION block max width 104 with nothing over it, unchanged from before
this change, and the added lines top out at 103. The PowerShell parser reports 0
errors over the whole file. The patch applies to origin/main with `git apply
--check`, and the same patch is refused against a subject with line 84 mutated,
so the clean apply is attributable.

Get-Help was ATTEMPTED AND DISCARDED as a check: run against a bare path it
returns 0 description characters and the generic "SHORT DESCRIPTION" synopsis
for the unpatched file too, so it measured nothing either way.

WHAT I DID NOT VARY. scripts/coord/occupancy.ps1 was read at 05a37c1 and is
not touched here. Two sibling drifts of the same family are NOT fixed in this
commit and are not mine to widen into: docs/WORKTREES.md:225-232 restates the
shapes by count and still says "Two shapes qualify", and
scripts/coord/presence.ps1:180 prints "Nothing was examined" on an unavailable
roster, which is false on the fault path and was already false before this work.
prune-merged.ps1:856-857 does not have the second defect: it interpolates
$occ.Detail and adds no claim of its own.
@wshallwshall
wshallwshall added this pull request to the merge queue Sep 17, 2026
Merged via the queue into main with commit 8f5bd54 Sep 17, 2026
41 checks passed
@wshallwshall
wshallwshall deleted the fencepara branch September 17, 2026 23:00
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