Skip to content

fix(tooling): qualify the cutover ratchet's ordinary-English alternative - #461

Merged
wshallwshall merged 2 commits into
mainfrom
lander/1261-cutover-ratchet
Aug 20, 2026
Merged

fix(tooling): qualify the cutover ratchet's ordinary-English alternative#461
wshallwshall merged 2 commits into
mainfrom
lander/1261-cutover-ratchet

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Routed by the lander from claude/builder-2bee12, whose authoring session has been archived. Authorship preserved on the commit.

Why this one, alone

main currently carries the bare pattern at zero slack on the topology ratchet, so this is the commit that stops an innocent documentation edit from redding main.

It splits the bare form out from the four unambiguous topology phrases, gates it on a topology qualifier, rewires both ratchet assertions, adds the both-directions test the item demands, and re-baselines the ceiling in the same change. Two mutants each red the new test, so it is not one-polarity.

The four exclusions, and why each

The dispatcher seat holds the owner's delegation on this branch's shape. I verified the two that are mechanically checkable rather than accepting the list:

commit disposition
f34eb881 ALREADY LANDING as PR #457's single commit. f34eb881 (commit) patch-id=778090c3ab9f5d34 and f94eb73f (commit) patch-id=778090c3ab9f5d34 -- the same change. Taking it here double-lands it. Verified by patch-id, not by diffstat: two different diffs can share a stat.
ff426e58 its own archived author left a DO NOT LAND with a substantive reason -- the counter it adds would read 0 forever on a default deployment, because the built route is unreachable under require_rcsi_for_pooled, which defaults True. Excluded on my own judgement: a control resting on a false premise reads as coverage and is worse than no control.
d37589b4 the item's own stated precondition is unmet -- it requires route sizing that the accompanying ADR does not do.
67347480 pending an unanswered owner design question that decides whether 48 files need editing or zero do. It was the most at-risk ref on the board -- local-only, zero origin refs. It is now backed at snapshot/builder-2bee12-20260820, so settling that question is no longer a race against a prune.

Ledger banner is OWED, and is explicitly NOT mine to write

The item number is written bare on purpose. The dispatcher seat has asked to author this banner once the merge lands, and has a specific reason: the entry must not be closed before the merge is on main, because until then main still carries the bare pattern at zero slack and a premature close leaves it one doc edit from red.

I will tell them when this is on main.

…ive (BACKLOG #1261)

The pattern's bare definite-article alternative is an ordinary English noun phrase. It matched
any sentence containing it, with no regard for whether the sentence concerned repository
topology at all -- and nothing in the regex looks at the surrounding words.

IT HAS FIRED ON INNOCENT PROSE AT LEAST THREE TIMES AND WAS FIXED BY EDITING THE PROSE EVERY
TIME. The most recent, e6d25d1, reworded two sentences to "counterpart" and left the pattern
untouched; `git diff e6d25d1 origin/main` over this file is empty, so the next author writing
the same ordinary sentence reproduced the same red on a documentation-only branch. Two earlier
firings are recorded in this file's own comments and were answered the same way. A defect fixed
three times at the instance level is a class nobody had priced.

WHAT CHANGED: the four unambiguous topology phrases still count bare, because they cannot mean
anything else. The bare form now counts only when a topology qualifier shares its line.

MEASURED BEFORE CHANGING, 52 hits over 1619 tracked files, of which 20 matched ONLY via the bare
form. Reading all 20 splits them three ways: 5 are figurative English with no repository in view,
9 carry an unambiguous topology term and still count, and 6 are historical narration the
retrospective filter never covered. The last group drops, and dropping it is correct -- this
gate's subject is a PRESENT-TENSE claim that this repo is a copy, which "what it did on the
mirror" does not make.

THE QUALIFIER LIST IS SHORT ON PURPOSE. `remote` and `branch` are deliberately absent: with
either of them in, two of the five false positives survive -- a line about a remote-tracking ref
and one about a case that broke every open branch. Every term in the set means repository
topology and nothing else. A longer list makes the false-positive rate worse, which is the trap
the previous three fixes fell into.

Ratchet re-baselined 52 -> 41 in the same change, with its measurement, per this file's own rule
that the number may fall and never rise. The slack was ZERO before this, which is what turned a
nuisance into a tripwire: the next innocent sentence red `main` immediately, and the sanctioned
remedies were to reword it or delete an unrelated genuine hit to buy room.

BOTH DIRECTIONS ARE PINNED, and each was made to fail on purpose:
  - revert the classifier to the bare pattern -> the ordinary-English arm reds
  - delete the bare form instead of qualifying it -> the real-claim arm reds, naming the line
Restored after each; the file hashed byte-identical both times. A one-directional test would
have passed against retiring the check entirely.

The fixtures are the real lines quoted from the tree, not invented to fit the regex. This module
is excluded from its own scan, which is the only reason the gate can be documented in the
repository it polices -- an early draft of the ledger item raised the counted population by three
just by describing it.

Verification, with its scope: pytest tests/test_cutover_slug_rot.py, 5 passed; ruff check and
ruff format --check on the changed file, clean. This lane's own .venv (ruff 0.15.22, the pin).
Not run here: the full suite, which is a separate pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>


Cherry-picked by the lander from claude/builder-2bee12, whose authoring session is archived.
Authorship preserved.

TAKEN ALONE, and the exclusions are deliberate. The dispatcher seat holds the owner's delegation
on that branch's shape and excluded the other four; I verified the two that are checkable:

  f34eb88  ALREADY LANDING as PR #457's single commit -- patch-id 778090c3ab9f5d34 on BOTH,
            so taking it here would DOUBLE-LAND it. Verified by patch-id, not diffstat.
  ff426e5  its own archived author left a DO NOT LAND with a substantive reason: the counter it
            adds would read 0 forever on a default deployment. Excluded on my own judgement --
            a control resting on a false premise reads as coverage and is worse than none.
  d37589b  the item's own stated precondition is unmet.
  6734748  pending an unanswered owner design question. Now backed on origin at
            snapshot/builder-2bee12-20260820 so it cannot be lost while that is settled.

main currently carries the bare pattern at ZERO slack on the topology ratchet, so this is also
the commit that stops an innocent doc edit redding main.
@wshallwshall
wshallwshall enabled auto-merge (squash) August 20, 2026 13:58
@wshallwshall
wshallwshall merged commit 1df0c07 into main Aug 20, 2026
38 of 39 checks passed
@wshallwshall
wshallwshall deleted the lander/1261-cutover-ratchet branch August 20, 2026 14:41
wshallwshall added a commit that referenced this pull request Aug 20, 2026
…rning runs an index test) (#465)

* backlog: close #1261 -- the cutover ratchet fix is on main by content

parse_items 313 items / 231 open / 82 closed, from 232/81. Expected closure
delta: 0 items, -1 open, +1 closed. backlog_status_check reports 549 across both
files, each declaring exactly one status.

Closed on the release condition this project uses -- the fix TEXT on main -- and
verified that way rather than on a merged badge. The
tests/test_cutover_slug_rot.py blob is 13a711b on origin/main, on PR #461's head
and on 9d781ed: all three identical.

Recorded in the banner because it will be reached for again: the cumulative
patch-id test does NOT match here, branch 43f5a21a against squash 148226e6, and
that proves nothing. A cherry-pick onto a different base plus an update-branch
breaks the equality without the work being absent. On a squash-merging repo a
patch-id MATCH proves landed and a NO-MATCH proves nothing. Blob identity settled
it in one command.

The banner's closed-alphabet character was LIFTED PROGRAMMATICALLY from an
already-closed item rather than typed, and asserted a member of _CLOSED before
use. Typing a status glyph by hand is how a wrong one enters the file, and the
alphabet is machine-parsed.

Held until the fix landed rather than closing on the PR, because main carried the
bare pattern at zero slack until then and a premature close leaves main one
innocent documentation edit from red.

* backlog: file #1298 -- the archive dialog's discard warning is an index test, not a loss test

The session-archive dialog lists the worktree's dirty set and says the files
"will be permanently discarded". For a ?? entry that is a statement about THIS
worktree's index, not about the content: a worktree whose HEAD predates a commit
sees every file that landed since as untracked, because they are absent from its
index while being tracked on main.

Measured on a live instance. It warned that tests/test_notifiable_admin.py and
docs/adr/0167-*.md would be permanently discarded. Both are tracked on
origin/main -- the test was added at 4c28bad (PR #428), which merged that same
session -- and every local copy was byte-identical to main's blob in all six
worktrees holding them. Archiving would have discarded nothing.

Reproduced on this seat's own tree, which is what establishes the mechanism
rather than the coincidence: at dd655da, two behind origin/main, git status
showed the identical ?? pair; fast-forwarding to 1df0c07 converted both to
tracked with no edit and no conflict. The files never changed, the base did.

The failure is systematic and its timing is adversarial -- the warning is
loudest exactly when the fleet lands fastest, and wrong in those cases. Both
responses are damaging: believing it refuses a safe archive, and learning to
dismiss it trains the response that defeats a real one.

Scope is stated in the item so it is not mis-built: the dialog is the Claude Code
harness and is not this repository's code. In scope here is a WORKTREES.md
subsection plus a scripts/coord/ helper that answers the recoverability question
for a whole dirty set and prints what it examined, refusing to call anything it
cannot read safe.

Also records #1297 as a permanent hole in the erratum. It was allocated from the
PRIMARY checkout because the allocating shell's cwd was the primary, so the
ledger gate correctly refused that commit and the item was re-filed at #1298.
alloc.ps1 records the claim against whatever tree it runs in.

Verified with the repo's own gate: each item declares exactly one status.
wshallwshall added a commit that referenced this pull request Aug 20, 2026
… own banner named (#466)

* backlog: retire #1259's inverted do-not-build banner, and record #1292's fifth sighting against its own argument

Two body amendments to landed items. No item filed, no item closed, no banner
status changed: parse_items reads 313 items / 232 open / 81 closed before and
after, the expected 0/0/0 delta for an amendment.

#1259 -- the 2026-08-15 banner had INVERTED. It read "DO NOT BUILD -- ALREADY
BUILT AND UNLANDED ON PR #394" and named #394 landing as its own expiry
condition. #394 landed, so the banner then said do-not-build over work that was
only half done. That is the dangerous direction: it removes an item from the
queue so nobody looks again.

The first scope option shipped -- parse_items refuses a source carrying conflict
markers, defined :94, called :132, reached before any parsing. The second did
not, and the item's own failure sentence stayed true: no pre-commit hook called
parse_items, so a conflicted ledger could still be committed with every gate
passing.

Also folded in a measurement the item did not carry, and it is the difference
between a defect and a non-defect here: the SHAPE of the conflict decides
whether anything catches it. A conflict that ADDS HEADINGS is caught
incidentally, by the ownership guard, because both sides' numbers read as
unallocated -- which renders as "already covered". A real ledger conflict is two
sides editing PROSE, adds no heading, and the ownership guard has nothing to
fire on. Measured with a prose-only conflict at dd655da, file restored
byte-identical: every gate passes, overall rc 0, the conflicted ledger commits,
while backlog_status_check.py on the same file exits 1.

#1292 -- a fifth sighting on main's own tip, recorded because it WEAKENS the
argument the fourth entry made rather than confirming it. The ack series is now
13, 14, 24 against a fixed sent=36. The fourth entry's case was that the
shortfall reproduces to within one ack, which is what made "systematic"
persuasive; 24 is a spread, not a reproduction. The verdict is NOT flipped to
starvation -- two clustered points and one outlier is not a distribution. What
changed is that neither reading now has an argument from reproducibility, so the
store-side discriminator is the only thing that settles it.

The same entry records that this sighting is NOT what was redding main. That
run's failing assertion is tests/test_connscale_smoke.py:128, the FD probe.
no_loss passed, and it is computed as agg_sent minus engine_read so acked is not
in it at all. The sent/acked figures are real and incidental -- pytest prints the
record's full repr on any assertion failure, and three sessions attributed the
red to this item because the numbers pattern-matched it. When a sighting names
an item, quote the line with the caret, never the values in the dump.

Amendments to items already on origin/main add no heading, so the ledger gate's
ownership check is never consulted; docs-only, so the claim gate's code-touching
scope does not apply. Every added line verified cp1252-encodable.

* backlog: write four provenance lines generically, so the widened slug guard can land

MUST LAND WITH BACKLOG #1083's WIDENED GUARD, NOT BEFORE OR AFTER IT.

With that guard on main and these four lines as they stood, the forbidden-content
pre-commit hook refuses ANY commit touching docs/BACKLOG.md or
docs/archive/backlog/BACKLOG-CLOSED.md -- the two most-edited files in the repo.
Measured by the builder that widened it: the fixed scanner exits 1 on them.
Allowlisting is not an alternative; the guard's own failure text forbids it.

Four lines, five tokens (one line carries two). Line set taken from the guard's
OWN output rather than from a pattern of mine: a shape regex I wrote reported
five and the guard reports four, and reconciling that showed the two counts
agreed on the population and differed on the counting rule -- the guard reports
one hit per LINE, my regex counted TOKENS. Identical line sets. Redacting off my
own pattern would have been a second, silently different definition of the
predicate the guard defines.

Each line is a Source or provenance note naming which session found something.
The slug carried no meaning the sentence needed, so each is now generic and the
distinction that mattered is preserved -- the two-session line still reads as one
session and a second session, in their original roles. The alloc-record line
keeps its point (the record captured the wrong worktree) with a placeholder.

Written generically rather than allowlisted, per the standing rule: when the gate
refuses a branch or worktree slug in a committed file, that is correct behaviour.

Ordering was checked before writing, not assumed. A redaction commit republishes
the token in its own diff, so this is only safe because the tokens were already
public on origin/main -- verified present there first. The shape was classified
WITHOUT echoing it: three-part hyphenated, 18-21 characters, an auto-generated
session slug rather than a customer or site token. Had it classified as customer
or site, the correct move was to hold the disclosure rather than commit.

Verification. parse_items 313 items / 232 open / 81 closed before and after, the
expected 0/0/0 delta for a prose amendment; backlog_status_check.py reports 549
across both files, 313 and 236. Residual slug-shapes in both ledger files: ZERO
-- and that zero is stated only because the positive control FIRES. The first
control I ran returned zero itself, which would have made the result
indistinguishable from a broken pattern; re-run against a file known to carry
slugs it returns 16.

No item filed, no item closed, no banner changed.

* backlog: record #1083 as built-and-awaiting-merge, in a form that cannot invert

Body amendment to a landed item. parse_items 313 items / 232 open / 81 closed
before and after; #1083 stays OPEN, which is correct -- the fix is on PR #462 and
not on main.

WHY THIS IS WORDED AT THE CODE AND NOT AT THE PR. A banner that says "do not
build, it is on PR #N" INVERTS the moment #N lands: it then reads do-not-build
over finished or half-finished work, and nothing in the document can tell. That
is not hypothetical. #1259 carried exactly that banner, its named PR landed, and
the banner then steered lanes away from an item whose second half was genuinely
undone -- I retired that banner earlier today in 4656694.

So this one names the check instead: read _WORKTREE_SLUG in
scripts/security/scan_forbidden.py on origin/main and see whether the prefix is
still mandatory. A pointer to a symbol re-answers itself on every read; a pointer
to a merge state answers correctly once and then lies.

Also recorded, because whoever works this item inherits both:

The ordering constraint. With the widened guard on main and the four
pre-existing ledger instances unredacted, the forbidden-content hook refuses any
commit touching docs/BACKLOG.md or BACKLOG-CLOSED.md. Established on the combined
tree by the guard itself, in a 2x2 with an asymmetric control -- widened guard
exits 1 on the unredacted ledger and 0 on the redacted one, current guard exits 0
on both. The exit 1 is the load-bearing cell: without it the green would be
indistinguishable from a guard that cannot see the class.

The second-order effect. Once the widened guard exists in a working tree, any
agent that RUNS it sees live ledger hits and helpfully edits the ledger, which a
builder may not author. Three occurrences on 2026-08-20, three different agents,
the last two under an explicit prohibition naming both files. The prohibition is
nought for three; checking git status --porcelain for what is actually staged is
three for three.

Residual slug-shapes in the ledger after this edit: zero, from a pattern whose
positive control fires at 20.

* backlog: close #1261 -- the cutover ratchet fix is on main by content

parse_items 313 items / 231 open / 82 closed, from 232/81. Expected closure
delta: 0 items, -1 open, +1 closed. backlog_status_check reports 549 across both
files, each declaring exactly one status.

Closed on the release condition this project uses -- the fix TEXT on main -- and
verified that way rather than on a merged badge. The
tests/test_cutover_slug_rot.py blob is 13a711b on origin/main, on PR #461's head
and on 9d781ed: all three identical.

Recorded in the banner because it will be reached for again: the cumulative
patch-id test does NOT match here, branch 43f5a21a against squash 148226e6, and
that proves nothing. A cherry-pick onto a different base plus an update-branch
breaks the equality without the work being absent. On a squash-merging repo a
patch-id MATCH proves landed and a NO-MATCH proves nothing. Blob identity settled
it in one command.

The banner's closed-alphabet character was LIFTED PROGRAMMATICALLY from an
already-closed item rather than typed, and asserted a member of _CLOSED before
use. Typing a status glyph by hand is how a wrong one enters the file, and the
alphabet is machine-parsed.

Held until the fix landed rather than closing on the PR, because main carried the
bare pattern at zero slack until then and a premature close leaves main one
innocent documentation edit from red.

* backlog: #1003's trigger will not fire -- record the no-lab ruling and stop four items reading as imminent

Owner ruled 2026-08-20, asked directly: there is no multi-VM lab.

parse_items 314 items / 231 open / 83 closed before and after -- the expected
0/0/0 amendment delta. #1003 stays open, correctly: the ruling closed a question,
it did not discharge the item.

THE DEFECT THIS FIXES IS A SENTENCE, NOT A STATUS. #1003's body says the four
residuals are "parked on a blocker that is about to stop existing". That blocker
is not about to stop existing. It is indefinite. Every planning pass that read
that line priced #99, #98, #320 and #351 as nearly-available capacity, and they
are blocked on HARDWARE rather than on a decision -- which no amount of triage,
scoring or re-reading can move.

#98 is a partial exception in exactly one limb, and the amendment says so rather
than flattening it: its trigger reads "a deployment that wants EPA, OR the first
domain-joined lab box". The first disjunct survives the ruling. The lab half is
dead; the deployment half is not.

Also carried into the item, because it will be reached for when a rig eventually
exists and not before: a green rig result must NOT be recorded as retiring the
db_lookup workaround. AOAG-DEPLOYMENT.md section 4.5's planned-outage mandate
stands until the RECONNECT ITSELF is proven. "The setting exists" is not the same
claim as "the reconnect works", and a rig standing up demonstrates only the first.

Amendment to an item already on origin/main, so it adds no heading and the ledger
gate's ownership check is never consulted. Docs-only, so the claim gate's
code-touching scope does not apply. Every added line verified cp1252-encodable.

* backlog: close #1233 -- delete_user purges search_presets on all three backends, verified per limb

parse_items 314 items / 230 open / 84 closed, from 231/83. Expected closure
delta: 0 items, -1 open, +1 closed. backlog_status_check OK, 550 across both
files.

VERIFIED PER LIMB RATHER THAN ON ONE, deliberately. Twice today I called a
multi-limb item done after checking a single limb and was wrong both times, so
this one was checked as: code on each of the three backends, then coverage for
each of the three, then whether that coverage actually asserts the purge.

  store/store.py, store/postgres.py, store/sqlserver.py -- one keyed
  search_presets purge each, alongside five DELETEs each.

  tests/test_postgres_store.py and tests/test_sqlserver_store.py cover two
  backends directly. The SQLite/default path is covered through
  tests/test_search_presets_api.py, which a filename-shaped search would have
  missed -- the same wrong-mechanism null that produced a false zero elsewhere
  today.

THE TEST WAS READ, NOT COUNTED, and it is non-vacuous by construction: it asserts
a PRECONDITION that the preset exists before deletion, then asserts the purge on
both the id and the freed username. It further carries two independent controls,
re-inserting the captured row afterwards, because with the row purged #1225's key
assertions would pass TRIVIALLY and stop being evidence about the key at all.
That is the anti-vacuity property this project keeps having to rediscover, and it
was already there.

It also retracts in place: the assertion it replaced said delete_user does NOT
purge preset rows, which was true when written and is the defect this item fixes.
The old line is recorded rather than quietly deleted.

Closed on the release condition this project uses -- the fix TEXT on main -- not
on a merged badge. The holder's claim can be released; that condition is met.

The closed-alphabet character was lifted programmatically from an already-closed
item and asserted a member of _CLOSED before use, never typed.

* backlog: close #1083 -- the bare-slug arm, its tests and the ledger redaction all landed together

parse_items 314 items / 229 open / 85 closed, from 230/84. Expected closure delta:
0 items, -1 open, +1 closed. backlog_status_check OK, 550 across both files.

VERIFIED ON ALL THREE LIMBS AT origin/main 7f68ea4, not on the merged badge and
not on one limb:

  1. THE FIX -- scan_forbidden.py carries two arms now, _WORKTREE_SLUG_PATH for
     the prefixed form and _WORKTREE_SLUG_BARE for the bare one. The claude/ or
     worktrees/ prefix is no longer mandatory.
  2. THE TESTS -- tests/test_scan_tokens_source.py, 54 tests, referencing the
     bare arm.
  3. THE LEDGER REDACTION -- zero slug-shapes remain in docs/BACKLOG.md or
     docs/archive/backlog/BACKLOG-CLOSED.md, against a control that fires at 22
     on a file known to carry them.

LIMB 3 IS NOT INCIDENTAL AND THE ITEM COULD NOT HAVE LANDED WITHOUT IT. With the
widened guard on main and those lines unredacted, the forbidden-content hook
refuses EVERY commit touching either ledger file -- the two most-edited files in
the repo. The three landed as one change, and merge safety was established on the
combined tree by the guard itself in a 2x2 with an asymmetric control: widened
guard exits 1 on the unredacted ledger and 0 on the redacted one, current guard
exits 0 on both. The exit-1 cell is what made the green mean anything; without it
the answer would have been indistinguishable from a guard that cannot see the
class.

THE PRIOR BANNER DID THE JOB IT WAS BUILT FOR, and that is worth recording
because the alternative was tried on another item today and failed. It named a
CHECK -- read _WORKTREE_SLUG on origin/main and see whether the prefix is still
mandatory -- rather than a PR state. When #462 merged, that check returned FIXED,
so the paragraph read as SPENT. A banner saying "do not build, it is on PR #N"
INVERTS the moment #N lands; #1259 carried exactly that and had to be retired
this morning. A pointer to a symbol re-answers itself on every read.

Closed on the release condition this project uses -- the fix TEXT on main. The
closed-alphabet character was lifted programmatically from an already-closed item
and asserted a member of _CLOSED before use, never typed.
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