Skip to content

fix(coord): unbrick the backlog allocator — the partition guard measured the wrong maximum - #166

Merged
wshallwshall merged 2 commits into
mainfrom
claude/fix-alloc-floor-partition
Aug 4, 2026
Merged

fix(coord): unbrick the backlog allocator — the partition guard measured the wrong maximum#166
wshallwshall merged 2 commits into
mainfrom
claude/fix-alloc-floor-partition

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

alloc.ps1 -Kind backlog refused every allocation, repo-wide, blocking at least two sessions from filing items and blocking PR #105 from renumbering an illegal pre-partition number.

What broke

One number served two incompatible purposes. Get-Floor returns the maximum over every ## N. heading across both backlog files on every ref, and the script used that single value for:

  • the emit startmax($observed, floor - 1) + 1. Wants the union max, so a number is never re-issued. Correct as written.
  • the residual detectorif ($observed -ge $PublicBacklogFloor) { throw }. Wants the maintainer-internal sequence's high-water, to catch the internal ledger creeping up on the partition. It read the union instead.

Public items are supposed to sit at or above the floor — that is the whole of the #107 partition design — so the detector fired on the system working exactly as intended. BACKLOG #1000 was simply the first legitimate public number to get there, and from that moment 1000 >= 1000 held forever.

Raising PUBLIC_BACKLOG_FLOOR, which the error message itself recommended, would have re-bricked at the new floor the moment a public item reached it. It is a workaround, not a fix.

What changed

Two measurements where there was one: Floor (max over everything swept — what must I not re-issue?, includes public numbers) and SubFloorMax (max below the partition — how much runway does the internal sequence have?).

The refusal is removed rather than made unreachable. Once an internal item is allocated at or above the boundary it is indistinguishable, in the published files, from a legitimate public item at the same number — both are ## N. with N ≥ floor. There is no attribute that separates them, so the arrival case cannot be detected from this data. A refusal branch that cannot fire reads as protection and is worse than none, so the detector now only warns, and the comment states that the limit is the data rather than the implementation.

-ShowFloor was a lying instrument and is fixed in the same commit. It returned before the guard, so it printed a confident next : 1001 while a real allocation threw. Anyone diagnosing this with the inspector concluded the allocator was fine. $residualWarning is now computed above the -ShowFloor block, so the preview and the real run read one shared expression.

Verified by the reviewer, not just reported

  • Fail-on-purpose has teeth. Re-planting $observed -ge $PublicBacklogFloor turns test_the_residual_detector_does_not_read_the_whole_set_maximum red; removing it turns it green. Reproduced independently.
  • -ShowFloor now reports floor 1001 / sub-floor 353 / next 1002, no refusal, guard quiet (353 is far below the 900 warn tier). ADR allocation unaffected.
  • 29 tests pass; ruff clean.

One measurement worth recording, because both the author and the reviewer initially got it backwards

The old comment claimed "Get-Floor already swept every ref, internal ones included." That claim is TRUE — measured: 490 vault-ish remote-tracking refs present, 489 carrying docs/BACKLOG.md, and 67 item numbers living only there, including #240#247, precisely the numbers the Ledger erratum records as re-issued over cited work. The sweep is why the floor is trustworthy.

What was false was the inference built on top of it: seeing internal numbers is not the same as being able to attribute one. The replacement comment separates the true claim from the false inference instead of deleting both.

BACKLOG #1001 is a permanent hole

A regression probe spent it as a real allocation before the test seam was in view. Precedent is #315/#317, probe allocations made verifying the previous floor fix, so it is left as a documented hole rather than hand-releasing a claim — which would establish a "release the verb by hand" habit the registry design deliberately refuses. The next backlog number is #1002.

Ledger

No BACKLOG number (the allocator was the broken thing) and no ADR: this restores intended behaviour rather than deciding anything, and ADR 0115 is not the partition ADR — 8e6e7fa3 touches three files, none under docs/adr/. Repo precedent for gate fixes of this class is a plain commit carrying the reasoning.

…wrong maximum

Filing BACKLOG #1000, the first legitimate item in the post-partition public
sequence, made EVERY backlog allocation in the repository throw:

    REFUSING TO ALLOCATE. The all-refs backlog maximum (1000) has reached the
    public floor (1000).

I filed #1000 and I caused this. It is not a latent bug that #1000 revealed -- the
guard's premise held right up until a public number legitimately reached the floor,
and mine was the first.

ONE MEASUREMENT WAS SERVING TWO INCOMPATIBLE PURPOSES. Get-Floor returned a single
maximum, used for:

  - the emit start, which wants the max over EVERYTHING so a number is never
    re-issued. Correct as written.
  - the residual detector, which wants the maintainer-internal sequence's high-water
    to see it running out of room below the partition. It read the union instead.

Public items are SUPPOSED to be >= 1000 -- that is the whole design -- so the
detector fired on the partition being used correctly. Get-Floor now returns both
`Floor` and `SubFloorMax`; the emit start keeps the union, the detector reads only
the sub-floor band (353 on this tree, so it is quiet).

THE REFUSAL IS REMOVED, NOT REWRITTEN TO BE UNREACHABLE. Once an internal item is
allocated at or above the boundary it is indistinguishable, in the published files,
from a legitimate public item at the same number -- both are `## N.` with N >= floor.
A refusal arm would have to fire on correct input or never fire at all, and a branch
that cannot fire reads as protection while providing none. Detecting a real breach
needs an internal-side input this repository does not have. What remains is an honest
warning at 90% of the boundary.

THE COMMENT'S LOAD-BEARING CLAIM WAS CHALLENGED AND SURVIVED. It justified the guard
with "Get-Floor already swept every ref, internal ones included", and that was
suspected of being false. Measured instead of repeated: 490 vault-ish
remote-tracking refs exist, 489 carry docs/BACKLOG.md, and 67 item numbers live ONLY
there -- including #240-#247, the numbers the Ledger erratum records as re-issued
over cited work. The claim is TRUE and the sweep is why the floor is trustworthy.
What is false is the inference that seeing internal numbers means being able to
detect the breach. The comment now says which is which.

SECOND DEFECT, ALSO MINE: -ShowFloor lied. I added it earlier today and it returned
19 lines BEFORE the guard, so it printed `next: 1001` while every real allocation
threw. A peer session listed it among six verifications, got a green answer, and
recorded it as fact. The residual warning is now computed ONCE, above the -ShowFloor
block, and both paths read that one expression -- they cannot drift apart. -ShowFloor
also prints the sub-floor maximum, because a bare floor cannot answer the question
the partition raises.

Negative controls, in the existing source-text seam (tests/test_ledger_check.py) --
executing the allocator to test it would either spend a real number or write to
.git/mefor-coord/alloc/**, and a test that mutates the ledger registry to check the
ledger registry is its own hazard:

  - the sub-floor measurement must exist, and Floor must survive for the emit start
  - `$observed -ge $PublicBacklogFloor` must never reappear (the regression verbatim)
  - $residualWarning must be computed before the -ShowFloor block and read by both

PROVEN TO FAIL: re-planting the exact regression makes the second test red; removing
the plant makes it green. 29 tests pass.

DISCLOSURE -- I spent a real number proving this. The regression probe allocated
BACKLOG #1001, which is now a permanent hole; claims are never released, and the
precedent for exactly this is #315/#317, the probe allocations made verifying the
previous floor fix. Next backlog number is #1002. Verified after the fix: a real
allocation succeeds, the ADR path still works (next 0160), -List works, and
-ShowFloor leaves the high-water ratchet untouched.

No BACKLOG number is filed for this work: the allocator is the thing that was broken.

"A control nobody has watched fail is an assumption wearing a green tick" -- this one
had never been watched fail on LEGITIMATE input, which is the harder half. That is
BACKLOG #1000's own thesis, and #1000 is the item that broke it.

ruff clean; docs/LEDGER-GATE.md documents both maximums and why the refusal is gone.
@wshallwshall
wshallwshall enabled auto-merge (squash) August 4, 2026 02:23
…allocator in tests

Revision after an independent design pass. The mechanism from the previous commit
holds; four things about the patch did not.

1. THE REFUSAL NOW HAS A REAL TRIGGER instead of being removed. Refusing nothing was
   the safe correction, not the right one. PUBLIC_BACKLOG_FLOOR is a constant in a
   source file, so it can be LOWERED -- a bad revert, a merge resolved wrongly, a
   tidy-up -- and NEITHER the pre-commit gate NOR CI can catch that: both read only
   the current value and have no memory of the previous one. Drop it to 900 and a new
   public #900 lands on top of an internal #900, green all the way. A ratchet outside
   the constant is the only instrument that can see it, so alloc.ps1 now keeps
   .boundary-highwater beside its registry and refuses when the constant falls beneath
   a value this clone already allocated against. Locally observable, genuinely
   reachable.

   Three quantities, three purposes, never crossed:
     $observed     (union max)       -> the next number, ONLY
     $subFloorMax  (below boundary)  -> the warning, ONLY
     $boundarySeen (highest floor)   -> the refusal, ONLY

2. "THIS CLONE CANNOT SEE THE INTERNAL LEDGER" IS FALSE AND IS NOT THE ARGUMENT.
   Measured: 490 vault-ish remote-tracking refs, 489 carrying docs/BACKLOG.md, 67
   numbers living only there including the #242-#246 band ADR 0115 cites. The premise
   fails for four other reasons, any one fatal, and they are now written down: an
   integer has NO PROVENANCE (a legitimate public item at the boundary and an internal
   breach are the same observation -- which is exactly how #1000 read as a breach);
   the refs are a FOSSIL (newest 2026-07-26, no refspec advances them, and they say
   314 while the real vault is at 315); they are CLONE-LOCAL (a fresh clone has none);
   and they are MASKED (internal 314 < public 353).

3. $observed STAYS THE UNION MAXIMUM, with the trap recorded. Repointing it at the
   sub-boundary max -- the tempting one-line fix -- makes $start = max(353, 999) + 1 =
   1000, a number already merged, and in a fresh clone with an empty registry the
   atomic CreateNew has no claim to collide with and would NOT catch the re-issue.

4. NAMING: $subFloorMax is "the highest number below the boundary", never "the
   internal maximum". It includes public pre-partition numbers, so it deliberately
   OVER-states the internal high-water and warns early rather than late. Relatedly,
   ledger_check.py's high-water 314 is NOT refreshed to 353: 314 is the vault-refs
   maximum, 353 is a public number on origin/main, and relabelling one as the other
   would plant a fresh false premise inside the comment being fixed.

ledger_check.py's own claim -- that alloc.ps1 "warns if the all-refs maximum reaches
this boundary" -- was the defect written down: wrong instrument, and it asserted a
liveness the fossil ref store does not have. Replaced, not softened.

THE TESTS NOW RUN THE ALLOCATOR. Nothing in tests/ ever had: the two existing
references are read_text() assertions and stayed green through the entire brick. The
seam is the process working directory -- alloc.ps1 has no -Repo switch and reads no
env var, so a throwaway repo gets its own registry AND supplies its own
ledger_check.py, making the boundary injectable. FLOOR=100, not 10: at 10 the warn
tier and the highest sub-boundary number collide and every tier test passes for the
wrong reason. The isolation check runs FIRST, because every later test spends real
numbers if it is false.

PROVEN TO FAIL: the same rig against the PRE-FIX alloc.ps1, with an item at the
boundary, returns rc=1 and "REFUSING TO ALLOCATE ... has reached the public floor
(100)" -- the production brick reproduced at 1/10 scale. Against the fix it allocates
#101. Real registry confirmed untouched by the suite: 62 claims before and after,
.floor-highwater still 1000.

34 tests pass; ruff clean.
@wshallwshall
wshallwshall merged commit 98b7e2b into main Aug 4, 2026
32 checks passed
@wshallwshall
wshallwshall deleted the claude/fix-alloc-floor-partition branch August 4, 2026 02:54
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