Skip to content

builder3: #1100 master test plan audit, 74 commits including P0s withdrawn as false (stranded branch) - #433

Open
wshallwshall wants to merge 75 commits into
mainfrom
claude/hopeful-chaplygin-3158c6
Open

builder3: #1100 master test plan audit, 74 commits including P0s withdrawn as false (stranded branch)#433
wshallwshall wants to merge 75 commits into
mainfrom
claude/hopeful-chaplygin-3158c6

Conversation

@wshallwshall

@wshallwshall wshallwshall commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Opened by a different session to make stranded work visible. Not reviewed by me, not armed for auto-merge.

Existed only in a local checkout — never on origin, no PR — while 9 ledger claims pointed at a worktree directory that no longer exists. Backed as origin/snapshot/b3-hopeful-chaplygin-20260815h-1810Z.

The 9 claims are not 9 pieces of work, and that matters for triage

All 74 commits belong to #1100 alone. The other eight keys are bookkeeping attached to the same dead worktree, and two of them say outright that they are not work:

So merging this satisfies #1100 and resolves none of the other eight. Releasing them is a separate, per-claim judgement, and for #1010 the note is the only copy of a fact worth keeping before the key goes.

What is here

74 commits, 52 files, +2358/−177 — an audit of the master test plan under #1100, chapter by chapter. It is unusually self-correcting, and the commit subjects are the record:

  • "my ch17 r112 WITHDRAWAL REASON was itself unverified"
  • "audit my OWN corrections — two welded claims I carried forward unchecked"
  • "finish the self-audit — two withdrawn rows were contradicting themselves"
  • "WITHDRAW the ch17 'engine sharding has zero CI execution' P0 — it is false"
  • "ch12 — the auth gate is TESTED, its CALL SITE is not"
  • "ch15 G1 — no live drift, and a naive-guard trap I walked into first"

Several P0s are withdrawn as false rather than confirmed, and the author repeatedly audits their own prior corrections. That is the same discipline this repository keeps rediscovering: a finding is not real until something independent of the finder checks it.

Expected failure and sequencing

BACKLOG.md is untouched while every commit cites BACKLOG #1100, so a PR that implements BACKLOG #N must update BACKLOG.md will fail. That gate is correct. I have not written the entry, because it would assert on another session's behalf that this audit is complete.

7 files overlap with #430 and 7 with #432; those three are the large branches and they collide with each other. Last commit 2026-08-15, so main has moved ~60 commits since.

🤖 Generated with Claude Code


Correction (author, later the same day)

The prediction above is right about the outcome and wrong about the mechanism, and the difference matters — because the mechanism is me.

I wrote that the gate will fail "because every commit cites BACKLOG #1100 while BACKLOG.md is untouched." Commit messages are not what it reads. Per .github/workflows/backlog-hygiene.yml, it fires only when an explicit BACKLOG #<digits> token appears in the pull request title or body — a bare #123 deliberately does not count, because in this repo that is usually a PR number — and the PR changes engine or IDE code, and then no docs/BACKLOG.md or docs/archive/backlog/ file is touched.

On every sibling PR I wrote the item numbers bare, so their gates exit 0 without enforcing anything. On this one I wrote the literal string BACKLOG #1100 in the body. That is a claim token, and it is the only reason this gate has something to enforce here.

The gate has not yet run — the PR is conflict-dirty, so GitHub cannot build a merge commit and 12 of the 13 required contexts have never executed. When the conflicts are resolved it will run, and it will fail: this branch changes 10 files under messagefoundry/ and touches no backlog file.

I am leaving the token in place rather than deleting it to make the gate quiet. The claim is true — these 74 commits are the #1100 audit — so the banner update is genuinely owed, and removing the token would be routing around a control rather than satisfying it. What I got wrong is that the same obligation exists on the sibling PRs and their gates will never ask, because of how I happened to write the numbers.

Everything else above stands, including that the other eight claims on this branch are bookkeeping rather than work.

…tent below INFO (BACKLOG #343)

Records the design decision for #343 before the engine change lands, because the diff shows what
and never why, and the why here is a rejection that is easy to re-litigate.

THE REJECTED ALTERNATIVE IS THE LOAD-BEARING PART. Relaying child stderr at INFO with a per-line
byte cap is the obvious compromise and it fails on the shape of this payload specifically:
truncating an HL7 v2 message to its first N bytes keeps MSH and PID -- the header and the patient
identifying segment -- and discards the clinically bulky remainder. A byte cap therefore preserves
precisely the most identifying part of the record. It is the worst available redaction for this
format, not merely a weak one, and it would place a CLAUDE.md section 9 violation inside the fix
for the defect that violation is about.

So content relays at DEBUG only, and INFO and above get an attributed rate-limited notice carrying
identity and a count and no content. That satisfies section 9 BY CONSTRUCTION rather than by
operator discipline: no call site above DEBUG carries content.

States the hazard the decision CREATES rather than softening it: stderr=PIPE with no drainer blocks
a flooding child, and the window that matters is bootstrap, where load_config() runs untrusted
admin code before the boot reply is read. The stderr reader must start in the same window the
stdout reader does.

Findings are written conditionally per CLAUDE.md section 0 -- zero deployments, so a deploying site
WOULD inherit this on first deployment; nothing is exposed today.

Index row added in the same commit, as the ledger gate requires. ADR number allocated by this
worktree via alloc.ps1 -- ownership is keyed on the committing worktree and is non-transferable.
…use a silent overwrite (BACKLOG #1247)

The installed gate's content changed on this box while three sessions ran against it, and afterwards
nobody could say who wrote it. The change was benign -- it moved the gate forward -- which is not the
point: an unattributable write to a shared safety control is the same class of event whichever
direction it moves the file.

FOUR MECHANISMS COULD HAVE RECORDED IT AND NONE WAS PRESENT: no backup, no receipt, no log line, and
no usable timestamp. The install site was a bare Copy-Item.

THE MTIME WAS THE TRAP, NOT THE GAP, and this does not repair it. Copy-Item carries the SOURCE's
LastWriteTime, so the installed copy inherits an mtime from whichever checkout installed it. A correct
stale-gate report was RETRACTED on the strength of one, and the retraction reached three sessions and
the owner before a baseline hash reproved the original finding. An absent record makes a reader say
"unknown"; a WRONG record makes them say something false with confidence. A corrected timestamp would
still be one mutable field asserting a fact nothing corroborates, so the record is the receipt.

PROVENANCE IS THREE-WAY AND COLLAPSING IT TO A BOOLEAN LOSES THE POINT. UNRECORDED (a gate installed
before this change) is the normal first-run state and must NOT be fatal -- refusing there would block
the very re-install that adopts the mechanism. Only MODIFIED stops the install, because an overwrite
destroys the only evidence that anything happened. -OverwriteUnverifiedGate proceeds deliberately.

THE HELPER IS A SEPARATE FILE FOR A TESTABILITY REASON, not a stylistic one: install-gate.ps1 cannot
be dot-sourced to reach its functions, because loading it performs a machine-global install into
~/.claude. A suite that had to install the gate to test the receipt would be a suite that installs the
gate, and that is the owner's action by design.

IT REUSES Get-GateHash RATHER THAN HASHING AFRESH. That digest folds CRLF, because git stores LF and
a Windows checkout carries CRLF; a second basis would let the receipt and
tests/test_gate_installed_parity.py disagree about one file.

A DEFECT FOUND WHILE BUILDING THIS, RECORDED IN THE CODE BECAUSE IT IS THE SAME CLASS THE ITEM IS
ABOUT: try is not an expression in PowerShell. Written as a parenthesised try/catch in a hashtable
value, the parser reads try as a command name, ParseFile reports the file CLEAN, and at run time it
discards the whole hashtable, writes a receipt containing the literal null, and still returns a path
and exits 0. The round-trip guard did not catch it either, because null is valid JSON -- a check its
own failure mode satisfies is not a check. Both are now fixed and commented.

Tests split deliberately: behaviour against a temp directory (never the real gate), plus static
assertions that the installer is WIRED to call it. Each half is blind to the other's failure -- the
behavioural tests pass if nothing calls the functions, the static ones pass if every function is
wrong.
…te (BACKLOG #321, Proposed 3)

A required merge context exited 0 on content carrying a real site code. scan_forbidden.py:10-12 is
explicit that gitleaks finds SECRETS, not this class, and the file WAS scanned -- the detectors simply
did not match. Every existing site-code detector is PREFIX-DRIVEN, so with no token file loaded it
degrades to the always-failing _NEVER sentinel: blind until the owner supplies data. This adds a
STRUCTURAL detector that works with nothing loaded, which is what makes it a backstop rather than a
second thing waiting on the owner.

THE SHAPE HAD TO EARN ITS PRECISION, because a leak gate that cries wolf gets disabled and that is
strictly worse than the hole it closes. Measured over the tracked tree (1,953 files): a bare delimited
six-digit run matches 637 lines in 146 files. Requiring the run to JOIN a letter-bearing identifier
segment across an underscore takes that to 5 -- every one of them this gate's own illustrations of the
shape, now rewritten with the house placeholder. Post-fix: 0 new hits on content, 0 on paths, 0 on a
full --path . walk including untracked files. Whole-tree scan cost 3.50s to 4.13s.

IT CATCHES THE THING THAT GOT THROUGH. Replayed against the pre-removal revision the item cites, the
detector fires on exactly one line of that file and on zero lines after the removal.

WIDTH IS PINNED AT EXACTLY SIX WITH NO LEADING-ZERO CARVE-OUT. A 5-to-7 band only works with a
no-leading-zero rule, and that is a silent under-detection hole in a gate whose filed defect IS a
silent hole -- the numeric prefix accepts a leading zero, so it is reachable.

A HAZARD ALL THREE CANDIDATE DESIGNS MISSED: each excluded a dot after the digit run, so a feed module
FILENAME written in prose did not match -- and a filename was half the evidenced leak. Permitting the
dot costs zero additional hits on either corpus. Both arms now cover it.

THE SELF-SCAN CANARY NEEDED EIGHT DIGITS, NOT SIX. A probe literal in the scanner's own source must
survive its own new detector AND a real prefix list no author can see. An eight-digit run has no
six-digit window with a boundary on both sides, so it cannot be a site code under any prefix list.

WHAT THIS DOES NOT CLOSE, and the module docstring now says so in the file itself: the item names TWO
token classes and only the SITE-CODE half is closable by shape. A partner-product name is a proper
noun in prose with no width, character class, separator or position regularity. That half closes only
under Proposed 1, which is owner-run token data and is not mine. Shipping this as "the estate-identifier
backstop" would let a green run read as "no estate identifiers present" -- the same defect the item
diagnoses, recreated one level up.

Tests assert TOKENS_PRESENT is False first: a prefix-free detector has no globals to monkeypatch, and
that precondition is what makes the backstop claim non-vacuous. Includes a liveness guard that the
detector is not the _NEVER sentinel, because no floor mechanism counts a structural detector.

Verified independently of the build: scanner exits 0 over the tracked tree, detector fires on a
synthetic positive and stays quiet on a git sha and a bare number; ruff check and format clean, mypy
strict clean over 266 files, 106 passed on the directly-affected modules.

NOT DONE, deliberately: docs/BACKLOG.md is untouched. The item's own proposed regex at :2703 matches
NEITHER example the item itself gives, and correcting a ledger body is not a builder's.
…ntent below INFO (BACKLOG #343)

The worker was spawned with stderr=None, so the child's stderr WAS the engine's own stderr, inherited
raw. fd 1 is strictly framed; fd 2 had no discipline at all. Admin-authored Handler code could write
arbitrary bytes into the operator's log of record -- forged engine lines, control sequences, or a
printed message body. Both halves are conditional, not live: zero deployments, so a deploying site
WOULD inherit this on first deployment.

CONTENT RELAYS AT DEBUG AND ONLY DEBUG. At INFO and above the engine emits an attributed,
rate-limited notice carrying identity and a COUNT and no content, so CLAUDE.md section 9 holds BY
CONSTRUCTION rather than by operator discipline: there is no call site at which child stderr content
becomes a record above DEBUG. The per-line byte cap was rejected in ADR 0166 for a reason specific to
this payload -- truncating an HL7 v2 message to its first N bytes keeps MSH and PID, so it preserves
precisely the most identifying part of the record.

THE DEADLOCK THIS CREATES IS CLOSED IN THE SAME COMMIT. stderr=PIPE with no drainer blocks a flooding
child, and the window that matters is bootstrap, where load_config() runs untrusted admin code before
the boot reply is read. The relay thread starts in the same window the frame reader does.

IDENTITY IS (inbound, pid, generation), NOT pid. An OS recycles pids, and the design turns on a stale
generation's relay still draining a killed child while the live one runs.

THE LINE CAP IS A MEMORY BOUND, NOT A REDACTION. A Handler can write megabytes with no newline, and an
unbounded carry lets the child size the parent's heap. Reaching it splits one write across several
DEBUG records and DISCARDS NOTHING, which is what distinguishes it from the rejected byte cap.

PHI redaction is NOT reimplemented here -- it is a property of the log handlers this relay rides like
any other record, and a second call site would be the drift SDS-3.5 warns about. Control-character
scrubbing IS applied at this seam, because "one child write is one log record" is the relay's own
framing contract and must not depend on how a host configured logging.

ADR 0166 IS CORRECTED BY THIS BUILD, and the correction is the useful part: the draft claimed the
stdout rebind leaves fd 1 "exclusively for frames". IT DOES NOT. Rebinding the NAME sys.stdout does not
seal the descriptor -- sys.__stdout__.buffer, os.write(1, ...) and open(1, "wb") all still reach it.
What keeps a raw writer harmless is unchanged: the closed-tag codec and the parent's unsolicited-frame
check. Claiming the rebind sealed fd 1 would have been a compensating control resting on a false
premise (SDS-3.7); what it actually buys is that the ACCIDENTAL case, print() in a Handler, can no
longer sit one buffering change away from corrupting a frame.

The ADR's attribution site is also corrected -- the identity is plumbed from RegistryRunner._sandbox_for
in pipeline/wiring_runner.py, NOT engine.py, which builds only the policy and the config source -- and
its line-number citations are replaced with symbol references, because a line anchor goes stale the
moment the code it points at moves.

Three consequences the ADR did not originally carry, each recorded when the build measured it: the
drain is EOF-driven rather than cooperatively stopped (closing a pipe under a mid-read thread raises
ValueError past an except OSError); close() takes a BOUNDED join, because this drain calls into logging
and can be inside a handler's emit when logging.shutdown runs at exit; and the relay being the sole
drainer makes a stalled off-box log collector back-pressure on a DEBUG-level child.

Verified: mypy strict clean over 266 source files, ruff check and format clean over messagefoundry and
tests, 87 passed across test_sandbox, test_sandbox_worker_logging, test_accepts_seam and
test_phi_logging_inventory, in the lane venv built against constraints.lock.
… (BACKLOG #343)

Both were found by the review round AFTER the implementation was committed, and both are claims rather
than behaviour -- which is exactly the class that survives a green suite.

F1. _reject_unsolicited's docstring asserted that the ADR 0166 stdout rebind means "the text layer
cannot reach fd 1 at all", so "there is no benign case to preserve". BOTH FALSE, and this docstring is
where a DESTRUCTIVE action is reasoned from -- drop the worker and dead-letter the message in hand.
Rebinding the NAME sys.stdout leaves the descriptor open: sys.__stdout__ is still a text layer on fd 1,
its .buffer IS the BufferedWriter the worker captured as the frame writer, and os.write(1, ...) and
open(1, "wb") reach it too. The reviewer measured a benign one-liner that destroys the worker.

THE SAME COMMIT ALREADY REFUSED THIS CLAIM TWICE -- in _sandbox_worker.py's bootstrap comment and in
ADR 0166, both citing SDS-3.7 -- so the change contradicted itself and the false half was the one
driving the destructive path. That is the compensating-control-on-a-false-premise shape, reintroduced
one file away from where it had just been rejected.

THE ACTION IS UNCHANGED AND NEVER NEEDED THE STRONGER CLAIM. A frame no outstanding request asked for
violates the one-request-one-frame protocol whether it was written deliberately or by accident, and the
queue cannot tell the difference: benign-but-unsolicited is still a frame the next dispatch would
misread as its answer. The justification is now the protocol violation, not an impossibility.

F2. The drain-ordering test's FALSIFICATION instruction was measurably wrong. It said to move the drain
start below the boot-frame WRITE; ADR 0166 records the measurement that this does NOT wedge, because
the parent then blocks on the reply while the drain is already running. It wedges when the drain starts
below the point the boot REPLY is read. Corrected, with the reason kept: a falsification that does not
falsify is worse than none, because it reads as a checked escape hatch and the one person who follows
it concludes the guard is untestable rather than that the instruction was wrong.

The PHI hunt found no section 9 violation, and found it by measurement rather than reading: the relay
was driven through the real configure_logging() filter chain -- not caplog, which carries no filters --
at INFO, WARNING and DEBUG with a full synthetic HL7 body plus an over-cap terminator-free run. At
INFO/WARNING: two records, both the counts-only notice, and none of the synthetic identifiers in either
the records or the rendered stream.

Verified: ruff check and format clean, mypy strict clean over 266 source files, tests/test_sandbox.py
34 passed.
… SQLite (BACKLOG #328)

audit-verify cannot detect a truncated tail. The startup auto-verify is a BARE WALK -- it confirms the
chain it can see is internally consistent and has nothing to compare that chain's LENGTH against, so
removing the tail leaves a shorter, perfectly valid chain and nothing objects.

THE STORED ANCHOR COULD NOT BE WIRED THERE, and that is why this was a design fork rather than a
fill-in. expected_anchor is an EXACT point-in-time seal: it requires the CURRENT head to equal the
recorded one, so any appended row diverges. A running instance writes audit rows, so consuming a stored
anchor at startup would alarm on essentially every restart. That property is DESIGNED and pinned by
test_an_anchor_goes_stale_on_the_next_appended_row; this adds a SECOND comparator beside it and does
not weaken that test, which still passes unmodified.

expected_prefix asks the weaker, useful question: was the recorded state ever true, and has the chain
only GROWN since? It holds the head captured AT the recorded position against the recorded one.

CHOSEN OVER SEAL-ON-STOP / CHECK-ON-START BECAUSE THAT IS BLIND EXACTLY WHERE THE THREAT LIVES. Sealing
during a clean shutdown detects truncation across a clean stop, and a tamperer does not shut down
cleanly. A control that needs the adversary's cooperation to arm itself is a ceremony, not a control.
Prefix-assertion is also strictly stronger than the item asked for: it catches a mid-chain rewrite too.

WRITTEN ONCE AND EXPORTED rather than stated per backend -- audit_prefix_verdict lives beside
audit_row_hash / audit_mac_bytes, which postgres.py and sqlserver.py already import. A predicate
restated per backend is the copy-versus-single-source defect BACKLOG #1253 catalogues, where a later
hardening reaches one copy and silently misses the rest.

THE CAPTURE IS A POSITION TEST, NOT A DATA-DEPENDENT BRANCH, so it does not reintroduce the early
return the walk deliberately avoids (ASVS 11.2.4, stated in the walk's own comments). A prefix_head of
None means the walk never reached the recorded position -- the truncation case -- and must FAIL rather
than pass vacuously.

THE NEGATIVE CONTROL CAUGHT A VACUOUS TEST OF MY OWN AND THE FIRST VERSION IS RECORDED IN THE TEST.
Deleting the head compare left the suite GREEN. The rewrite-a-row-in-place construction breaks the hash
chain, so the WALK reports "chain broken" and returns before the comparator is consulted -- the test
passed for a reason unrelated to what it claimed. Rebuilt as a SAME-COUNT TAIL REPLACEMENT (truncate
behind the engine's back, then let the engine append replacements through its own API, so the chain is
internally valid and the count is restored); only the head at the anchored position distinguishes it.
With that shape, deleting the head compare reds exactly that test and no other.

SQLite only in this commit. Postgres and SQL Server share the primitive but NOT the loop: both SQLite
and Postgres carry a running `count`, while SQL SERVER USES len(rows) AND TRACKS NO POSITION, so its
capture needs a counter the other two already have. Wiring those two plus the Store protocol is the
next layer, deliberately not folded in here.

Verified: mypy strict clean over 266 source files, ruff check and format clean, tests/test_audit_integrity.py
48 passed, mutation-proved in both directions with the plant asserted before the run.
…Server and the Store protocol (BACKLOG #328)

Completes 839575e, which added audit_prefix_verdict and wired it into SQLite only. The predicate is
still written ONCE, beside audit_row_hash / audit_mac_bytes, and imported by both server backends --
restating it per backend is the copy-versus-single-source defect BACKLOG #1253 catalogues.

SQL SERVER IS THE ODD ONE OUT AND GENERALISING FROM EITHER TWIN WOULD HAVE SHIPPED A NO-OP THERE. The
SQLite and Postgres walks carry a running `count`; SQL Server reports len(rows) and tracks NO POSITION
at all. A prefix capture needs a position, so this introduces the counter the other two already had.
My own written recipe for this item said "all three backends share one loop shape" -- that was WRONG,
and reading the third backend rather than generalising from the first two is what caught it. A fix
derived from the twins would have passed on two backends and silently done nothing on the third, which
is the shape this item exists to prevent one level up.

The Store protocol now declares expected_prefix, so a caller can reach it polymorphically rather than
only through a concrete SQLite store. That is what makes the startup auto-verify able to consume it
later; nothing calls it yet, deliberately -- wiring the caller is a separate decision with its own
alerting consequences.

Verified: mypy strict clean over 266 source files with the protocol and all three implementations
agreeing, ruff check and format clean over messagefoundry/store, tests/test_audit_integrity.py 48
passed. The SQLite behaviour -- including the mutation-proved negative control from 839575e -- is
unchanged by this commit; Postgres and SQL Server carry no local suite here and their legs are CI's.
…st failure (BACKLOG #1260)

THREE LAYERS OF NAMING SAID "TESTS FAILED" AND NOT ONE WAS TRUE. Confirmed live on PR #398 tonight:
the check is named `test (windows-2025, py3.14)`, the step `Tests (pytest)`, and the process exited
139 -- 128 + SIGSEGV(11) -- printing "Segmentation fault". ZERO tests failed. There is no pytest
summary line and no FAILED id anywhere in the log, because the process died before it could write
one. A reader at any of those three layers reaches for a test regression that does not exist.

GitHub reports `steps.tests.outcome` as "failure" for ANY non-zero exit, so a segfault and a failing
assertion are indistinguishable to everything downstream. The distinction has to be made at the step,
which is what this does.

PASS/FAIL IS UNCHANGED. The exit code is captured and re-raised, so a crash still reds the leg; only
the log line and the annotation become true. Exercised for real rather than reasoned about: rc=139
emits the annotation and exits 139, rc=134 likewise with signal 6, rc=1 emits NOTHING and exits 1 --
so a genuine test failure can never be relabelled as a crash -- and rc=0 stays clean.

IT DELIBERATELY DOES NOT RETRY, and that is the item's other half left open on purpose.
scripts/ci/retry-native-crash.sh exists and is correct, but its documented scope is the pyodbc/py3.14
SQL Server binding crash (upstream #1459), down to a "REMOVE THIS WRAPPER once #1459 ships a fix"
instruction. The engine suite does not use pyodbc, so this leg's crash has a DIFFERENT and currently
unknown cause. Wrapping it here would couple an unrelated leg's crash handling to that removal note,
and retrying an unknown-cause crash is closer to laundering than the pyodbc case, where the cause is
documented upstream. That is a decision, not an oversight, and it is recorded at the call site.

THE GUARD THAT PINS THIS STEP HAD TO BE RE-AIMED, AND THE FIRST RE-AIM WAS WRONG.
tests/test_ci_engine_step_excludes_webconsole.py located the step by scanning for a line starting
`run: pytest -q`, which pinned it to being a ONE-LINE `run:`. Wrapping the invocation broke the
LOOKUP rather than any assertion, and the failure read "no engine step found" instead of "the step
moved" -- a locator coupled to a step's spelling blocks every change to how that step is invoked.
Broadening the scan to any `pytest -q` line was measured WORSE: it matches ci.yml's EARLIER
doc-guards step (`pytest -q -rs $DOC_GUARDS`) and asserts against the wrong invocation entirely.
That was caught only because the test went red on it. Disambiguating by `--ignore-glob` would have
been circular -- that is the thing under assertion, so the locator would be satisfied by its own
subject and could never fail. It now locates the step STRUCTURALLY by name, via the parsed workflow.

Verified: ci.yml still parses as YAML (10 jobs, the step's run is a block); the three pinning tests
pass; and the guard is mutation-proved in two directions with each plant asserted before the run --
swapping --ignore-glob for plain --ignore reds it, and renaming the step reds it. Both restored
byte-identical. yaml was already a test dependency (three sibling tests import it).
…sing a live fail-open (BACKLOG #1229)

The gate blanks quoted spans before scanning so a commit message cannot supply a verb. It did that
with two sequential regexes, DOUBLE QUOTES FIRST -- and inside a SINGLE-quoted shell word a double
quote is an ordinary literal. So a command shaped like

    echo 'say "hi' ; <a gated git command> ; echo 'bye" now'

hands the shell two harmless arguments and leaves the middle LIVE, while the double-quote pass pairs
those two literal quotes ACROSS the live command and deletes it. No rule ever sees it: ALLOW.

REPRODUCED INDEPENDENTLY HERE BEFORE FIXING, with the old code kept as its own control and an inert
marker standing in for the gated command so no dangerous string was ever built:

    shape                                       old        new
    plain single-quoted (control)               VISIBLE    VISIBLE
    stray DOUBLE quote in single-quoted words   GONE       VISIBLE     <- the fail-open
    stray APOSTROPHE in double-quoted words     VISIBLE    VISIBLE
    unterminated quote                          VISIBLE    VISIBLE

THE ASYMMETRY IS THE PROOF AND IT IS WHY THIS WAS INVISIBLE FROM ONE SIDE. The mirrored shape still
denied, because the double-quote pass ran first and consumed those spans before the single-quote pass
could straddle. The cause is the blanking ORDER, so a fix aimed at the command classifiers would not
have touched it. Two independent regexes cannot express "whichever quote opened first wins", which is
why this is now a single left-to-right scan rather than a better pair of patterns.

AN UNTERMINATED QUOTE IS STILL NOT BLANKED, PRESERVING THE OLD BEHAVIOUR RATHER THAN CHANGING IT.
`'[^']*'` required a closing quote, so an unpaired one never matched and the text stayed VISIBLE --
failing CLOSED. A scanner that swallowed everything after a lone quote would fail OPEN, turning one
stray character into a total bypass. That is a regression this fix could easily have introduced, so it
is pinned by its own test rather than assumed.

SCOPE, from the gate's own SYNOPSIS: this is a local developer guardrail against an accidental primary
edit and explicitly NOT a security boundary. Nothing here touches the engine, and per CLAUDE.md
section 0 there are no deployments. A bypass weakened a working-tree control on a maintainer
workstation -- worth fixing, not worth overstating.

ONLY ONE OF THE THREE PARAMETRIZED CASES DISCRIMINATES, and the test says so at the call site. It
takes a PAIR of stray quotes to straddle; a single one has nothing to pair with. The two single-sided
cases are kept as BOUNDARY pins -- they catch a future over-blanking fix -- but unlabelled they would
read as three independent proofs of something only one of them can see fail.

Verified: gate parses; 621 passed and 3 skipped across every gate suite (worktree_gate, gate_rule,
collision_gate, gate_installed, install_gate); 6 new tests pass; and mutation-proved by restoring the
original two regexes, which reds exactly the straddle case and leaves the other five green, with the
plant asserted before the run and the file restored byte-identical after.

NOTE FOR WHOEVER INSTALLS: this changes the SOURCE. The installed copy at ~/.claude/hooks/ is what
runs, so the fix does not take effect on this box until the owner re-installs from a current checkout.
…il channel (BACKLOG #1215)

Three records described a channel that is wired and delivering as an unwired prototype. No behaviour
changes; every edit is a comment or a status line. The reason it is worth a commit is that all three
fail in the same direction -- they invite a reader to reason about a RUNNING mechanism as hypothetical.

(1) ADR 0161's Status line and its "Status and what gates wiring" section both called the code a
prototype "deliberately not wired", with "nothing live in any session". FALSE AT HEAD:
scripts/coord/install-coordination.ps1:238-239 carries a SessionStart row AND a Stop row, both
pointing at scripts/hooks/mail-drain.ps1. The ADR's decision, measurements and trade-offs are
untouched -- only its claim about its own subject's deployment state was wrong.

(2) mail-drain.ps1's header said "THIS DOES NOT WIRE ANYTHING ... install-coordination.ps1's rows are
untouched". THAT SENTENCE WAS FALSE IN THE COMMIT THAT ADDED IT: fdec72c (#210) introduced those rows
itself. A "this changes nothing" claim is worth exactly as much as the diff it ships beside, and it is
a shape to distrust -- the claim is about the commit's own blast radius, so the only thing that can
refute it is the commit, and a reader who trusts the comment never opens it.

(3) THE MARKER PARAGRAPH HAS NOW BEEN WRONG IN BOTH DIRECTIONS, which is why it is written out rather
than quietly corrected. It first said "marker state can only ever suppress a re-display"; that was
false against the code of the day and was corrected to "A MARKER THEREFORE DOES GATE A CONSUME". Then
the consuming path changed underneath the correction and re-inverted it. The shipped guard is
`$markerPath -and -not $consuming`, so the marker check is SKIPPED ENTIRELY when consuming, and the
code's own comment says so at that site: "A CONSUMING DRAIN THEREFORE IGNORES MARKERS ENTIRELY". The
ORIGINAL claim is now the true one.

THE THIRD IS THE DANGEROUS ONE AND THE ITEM NAMES WHY: the wrong sentence sat inside a paragraph whose
whole subject was correcting a previous falsehood, so it read as the CHECKED statement -- the most
convincing form a wrong sentence can take. A reader who doubted it and re-read the header got the
inversion CONFIRMED. Only the running code disagreed, and only at a different site.

Verified: mail-drain.ps1 parses clean (every session runs it at SessionStart and Stop); 169 passed /
2 skipped across the mail, session-mail, ADR-index and feature-map suites; and the no-glyph rule
enforced with the cp1252 encodability test rather than by eye -- my added lines introduce NO
non-cp1252 character, measured against the diff rather than the file, because the ADR carries
pre-existing ones elsewhere that are not mine to sweep.
…ng test plan (BACKLOG #1100)

Five cells in chapter 15 assert that the alert/security-notify STARTTLS hop is unauthenticated and
that docs/PHI.md and docs/BACKLOG.md contradict each other about it. BOTH PREMISES WERE ALREADY FALSE
WHEN THE PLAN WAS WRITTEN: #323 closed it on 2026-08-02.

I VERIFIED BOTH PRECONDITIONS AGAINST THE CODE BEFORE TOUCHING A WORD, because this chapter's only P0
"with a real security consequence" was one of the cells, and correcting it wrongly would have silently
closed a live security question:
  alert_sinks.py:385 states "The STARTTLS hop is VERIFIED (#323, layer 3)", and :430-431 pass it --
    `smtp.starttls(context=tls_context)`, commented "context= is REQUIRED (#323): starttls()'s own
    default verifies NOTHING".
  docs/PHI.md ROW 11 (:1015) states the verifying posture in full -- explicit context, chain +
    hostname + strict RFC 5280, TLS 1.2 floor, via tls_policy.build_smtp_tls_context() -- and records
    the pre-#323 state as history.
  tests/test_alert_smtp_tls.py exists, 21 tests.

THE TRAP THAT NEARLY CAUGHT ME IS IN THE FILE I WAS READING. alert_sinks.py:387-388 describes
`ssl._create_unverified_context`, `CERT_NONE`, `check_hostname=False` -- in the PAST TENSE, as the
defect #323 fixed. Read as current, it confirms the plan's claim exactly. The first pass of this work
stopped and reported the preconditions as UNMEASURED rather than guess which tense governed; the
answer came from :385 and :430-431, not from :387.

THE TESTS SURVIVE; ONLY THE PREMISE GOES. ALERT-08, 58 and 67 are still worth building -- pinning the
posture at send time and binding the docs to the code catch a FUTURE divergence, which is the only
thing they were ever able to catch. What changed is that ALERT-67 is now expected to PASS on arrival
rather than "fail today", and S4's manual matrix expects a self-signed and a hostname-mismatched cert
to be REJECTED. Running S4 against the old sentence would have recorded three passes as the expected
result and read a working control as a finding.

THE EXIT CRITERION WAS THE WORST OF THE FIVE: "the three contradicting documents agree with the code",
naming a contradiction that was already resolved. An exit criterion demanding that a resolved
contradiction be resolved CANNOT FAIL, so passing it says nothing while a reader believes a check ran.

AND OQ-3 WAS THE MOST EXPENSIVE: an OPEN P0 blocking four rows, describing a fix as a live exposure.
Its second half has a recorded answer too -- this path did NOT adopt the connector hop gradient; its
deviations are gated by a [security].allow_unverified_alert_smtp_tls acknowledgment switch at the
serve gate. It blocks nothing.

Each dead assertion is QUOTED inside its correction rather than deleted, so a reader can see what the
plan used to claim and why it was wrong -- the same reason #1215's marker paragraph records both of its
inversions. A grep for the old strings therefore still matches, inside the corrections.

SCOPE: this is the clearest cluster only -- five cells in 15-alerting-and-observability.md, whose
premise I verified. The item names NINE sites; the other four are NOT verified and the item stays open
for them. The cited docs/BACKLOG.md:5152 anchor has drifted and is flagged in place as re-derive-by-content.

Verified: 112 passed / 91 skipped across the test-plan, doc-drift, feature-map and phi-logging suites;
no-glyph cp1252 test run against the DIFF rather than the file, because the chapter carries
pre-existing glyphs that are not mine to sweep. My added lines introduce none.
…r test plans (BACKLOG #1100)

Both rows were re-measured against the current tree, and both were making claims
the code and docs had already overtaken.

02-pipeline-reliability.md: the Postgres 2-engine crash-and-restart row said
tests/test_shard_recovery_postgres.py "runs nowhere". It runs -- in ci.yml's
postgres-store job -- but that job is gated on
schedule || workflow_dispatch || serverdb == 'true', so it does not run on a PR
that touches no server-DB path. "Runs nowhere" understates the coverage and
"runs in CI" would overstate it; only the gated form supports a decision about
PIPE-01, which is what the row exists to inform.

05-connections-and-transports.md: the "CONNECTIONS.md contradicts the code" row
is fully closed. SFTP-IN, REST-IN and SMTP-OUT are all marked shipped now; DB-IN
agrees with FEATURE-MAP's "Production" rather than contradicting it; SOAP-IN is
receive-only rather than planned; and all six connectors the row called
undocumented have settings headings. FHIR-IN still reads "planned" and that is
correct -- the facade is unshipped -- so the row's inference (the listener is
built, therefore FHIR-IN is built) does not follow: shipping the substrate does
not ship the facade.

Both rows are rewritten in place rather than deleted, so the re-measurement is
auditable and the tables keep their shape. All seven line citations in the
connector row had drifted off their subjects and had to be re-found by content
before any of them could be judged; that is the sixth recorded instance of the
anchor rule this sweep has produced.
… run (BACKLOG #1100)

Both rows asserted that live server-DB suites are invoked by no workflow.
Measured against ci.yml by parsing the YAML rather than grepping it:

Row 80: tests/test_cluster_failover_postgres.py runs at ci.yml:1570, in the
postgres-store job's step "Run the failover + engine-shard recovery suites on
real Postgres". The anchor the row cites as its evidence, ci.yml:614, has
drifted and now lands on a comment about arithmetic.

Row 81: all six DR suites exist and all six are invoked -- the Postgres trio by
postgres-store, the SQL Server trio by sqlserver-store, each in a step named for
exactly those suites.

BOTH STAY P0. The residual risk is real, but it is a GATING risk rather than an
absence: both jobs carry schedule || workflow_dispatch || serverdb == 'true', so
a PR that changes election or DR logic without touching a server-DB path still
ships unverified. "Detected today?" moves from "No" to "Partly -- on the gated
server-DB leg only, never on an ordinary PR", which is the form that supports a
decision. "No" understates the coverage and a bare "yes, it runs" would overstate
it.

Row 81's MEFOR_TEST_* env gating is a SECOND, INDEPENDENT condition and was not
re-measured here. The row now says so, so that correcting one half of its claim
does not read as clearing the whole row.

Found by transferring probe 6's shape rather than by a new search: the identical
"runs nowhere" phrasing about a sibling Postgres suite was already falsified in
02-pipeline-reliability.md, and the two test files turn out to sit on consecutive
lines of the same CI step. A defect class, once named, is worth re-running across
the corpus -- this is the third and fourth instance of it.
…w that says it cannot (BACKLOG #1100)

05-connections-and-transports.md row 98 claimed "Inbound HTTP listener has no
application-layer authentication", evidenced by "grep for auth/Authorization/
bearer/hmac in http_listener.py returns 0 hits". EVERY PART OF THAT EVIDENCE IS
NOW FALSE:

  the same grep measures 52 matching lines;
  Http() does not expose "caps + TLS/mTLS only";
  ADR 0023 no longer defers auth -- ADR 0154 (Accepted 2026-07-31) is titled its
  "deferred tail" and delivered it.

Built and measured: intake_auth: Literal["none","api_key","bearer",
"mtls_subject"], enforced by _authorize_head (http_listener.py:618) with a 401
plus WWW-Authenticate, credentials env()-only, rotation via intake_api_key_next,
health probes inside the gate by default, and failed-attempt rate limits at
10/min/peer and 60/min global. The row's "Covered?" cell is equally stale: there
is a dedicated tests/test_inbound_http_intake_auth.py plus four more files, 18
test functions naming the surface.

THE ROW STAYS P1 BECAUSE ITS CONCERN SURVIVES ITS EVIDENCE, IN A NARROWER FORM.
intake_auth defaults to "none" and _authorize_head returns early when unset, so a
site deploying the listener off-loopback without setting it would accept
unauthenticated POSTs. That is now an explicit, documented, tested opt-in rather
than an implicit omission -- a different decision, and the only one still open is
whether "none" is the right default for a PHI intake path.

Written in the conditional per CLAUDE.md section 0: there are no deployments, so
this is what a deploying site would hit, not something happening now.

Found by a reversed discriminator: rows asserting a grep returns ZERO hits go
stale precisely because code gets added. Four such claims exist in the plan; this
is the one that broke, and the other three (ADR coverage-plan hits in 05:95 and
09:122, and 0 occurrences of "validate" in 06:86) were re-measured and HOLD.
…G #1100)

05-connections-and-transports.md row 105 said five ADR status lines contradict
their code. Re-measured against the ADR files, both halves of each claim:

  0011  "Proposed"                     transports/timer.py, 341 lines      LAGS
  0015  "No code written yet"          transports/soap.py, 844 lines       LAGS
  0016  "No code written yet"          tests/test_x12_rte.py, 625 lines    LAGS
  0022  "Design-only (no code yet)"    test_ack_capture_runner.py, fhir.py LAGS
  0021  "No code yet"                  -> NOW READS "Built and shipped"    FIXED

ADR 0021's status has been corrected since the row was written and now reads
"Accepted (2026-06-19, owner go). Built and shipped (eventlog #16, Lane S)". It
is struck from the count rather than left inflating it.

The row keeps its point and its priority: four is still four, and a wrong ADR
status is still a governance defect. What changes is that a count carried forward
without re-measurement drifts upward relative to reality -- 0021 is itself the
evidence that these get fixed one at a time, so the count has to be re-derived
rather than quoted.

Found by generalising the discriminator that broke row 98 in the same file: that
row cited "ADR 0023 defers auth" when ADR 0154, titled ADR 0023's "deferred
tail", had closed it. A plan row citing an ADR's status is asserting something
about a FILE THAT MOVES INDEPENDENTLY of the plan, which makes it stale by
construction.
…s one drifted anchor (BACKLOG #1100)

04-high-availability-and-dr.md row 97 was probed for staleness and turned out to
be CORRECT. Every claim re-measured:

  FEATURE-MAP omits ADR 0047/0048/0049/0056/0096   0 grep hits each   TRUE
  BACKLOG #100 ranked Tier cell still reads "P1"   BACKLOG.md:373     TRUE
  BACKLOG #101 ranked Tier cell reads DEMAND-GATE  BACKLOG.md:380     TRUE
  ADR 0096 is Accepted                                                TRUE
  code is in settings.py:2896-2910                 that range is now
                                                   ADR 0014 alert
                                                   rules              DRIFTED

Only the code anchor was wrong. The ADR 0096 surface is `promotable: bool = True`
at settings.py:3026, with its explanation from :3016, so the citation is corrected
to settings.py:3016-3026 and named rather than left as a bare line range.

The row is annotated as re-verified rather than rewritten, because a sweep that
only marks stale rows leaves the next reader unable to tell "checked and live"
from "not yet checked". Both are useful; only one of them was recorded until now.

NOTE FOR WHOEVER OWNS THE LEDGER: the two Tier cells are a real, still-open
defect -- two archived/shipped items carrying pre-shipping scores in the ranked
backlog. They live in docs/BACKLOG.md, which a Builder may not edit under the
owner ruling, so this commit records and locates the defect without touching it.

Found by probing plan rows that cite a BACKLOG item as open. 28 raw hits, of
which nearly all were co-occurrence rather than claims -- "#1"/"#2" were
"synthetic ADT #1", and one trigger was the word "pending" in unrelated prose.
One row carried real, checkable ledger claims, and it was right.
… drifted citation (BACKLOG #1100)

04-high-availability-and-dr.md row 82 was probed on the assumption that its
"18 members" count had drifted, since counts were the class that broke row 105.
IT HAD NOT. Measured via AST rather than a text window:

  _ALERT_EVENT_TYPES  frozenset, settings.py:2599, EXACTLY 18 members
  only leader-related member is leadership_acquired -- nothing fires on ABSENCE
  alerts.py:206-213 still lands on leadership_lost, "Emits no notification"

So the row is correct on every claim and the P0 gap it describes is real and
open: a cluster that loses leadership entirely pages nobody, because the alert
vocabulary has a member for ACQUIRING leadership and none for having none.

Only the settings anchor was stale (cited :2499-2526, declared at :2599). It is
now cited by NAME plus declaration line rather than as a range, because a range
drawn around a growing frozenset re-drifts the next time a member is added --
which is precisely how this one drifted.

The row is annotated as re-verified rather than left silent, matching the
practice adopted in c4d6030: a sweep that marks only stale rows cannot tell the
next reader "checked, still true" from "not yet checked".
… at startup (BACKLOG #1100)

04-high-availability-and-dr.md row 83 claimed engine shards and [cluster] "collide
on one lease", on the strength of two claims. The load-bearing one is false.

  "no validator relates serve --shard to [cluster].enabled"
      THERE IS ONE, IT FAILS CLOSED, AND IT IS TESTED.
      ADR 0073 makes them mutually exclusive; __main__.py:2649-2659 refuses the
      combination with exit 2 BEFORE the store or app is built; and
      test_shard_recovery_engine.py:321::test_serve_refuses_shard_with_cluster_enabled
      asserts rc == 2. Executed here: 1 passed.

  "_lease_key is not engine-shard-namespaced"
      STILL TRUE, and the anchor drifted (cited cluster.py:414, actual :484).
      But it is MOOT for this failure mode: N engine-shard processes can never
      come up against an enabled [cluster] to contend at all.

The stated blast radius -- "silent full stop for every engine shard but one,
looking healthy on /cluster/status" -- CANNOT OCCUR. A fail-closed startup
refusal is the opposite of silent, so the row is closed rather than narrowed.
That makes it the first row in this sweep whose concern did not survive its
evidence; the previous nine were all narrowings.

What remains is a design note, not a gap: the un-namespaced lease key matters
only if ADR 0073's mutual exclusion is ever lifted, so it is a CONSTRAINT TO
PRESERVE and is recorded as such.

Also noted in the row: this satisfies the HA-03 exit criterion at :399 by its
FIRST alternative (a config-load rejection, not an engine-shard-namespaced lease
key) -- though the assertion lives in test_shard_recovery_engine.py rather than
the tests/test_cluster_shard_interaction.py that the criterion names, so anyone
grepping for that filename would wrongly conclude the criterion is unmet.
…is actually missing (BACKLOG #1100)

04-high-availability-and-dr.md row 84 was re-measured and is CORRECT on all
three claims -- the last unchecked P0 in this chapter's risk table:

  dr.py:296-301 disclaims a cross-store guarantee   TRUE, and the anchor lands
                                                    exactly on "the engine gives
                                                    no cross-store loss/duplicate
                                                    guarantee -- documented, not
                                                    an engine AC"
  harness/reconcile/ has capture/compare/normalize/report   TRUE, all four
  nothing binds it to the DR release path           TRUE -- 4 unit-test files
                                                    exercise harness.reconcile,
                                                    but no workflow and no
                                                    runbook step invokes it

The two "reconcile" hits under .github/workflows/ are an unrelated ingress probe
and an English verb, not a binding. Worth stating because a grep for the word
alone suggests coverage that does not exist.

AND THE GAP IS SHARPER THAN THE ROW SAID. AOAG-DEPLOYMENT.md:708 DOES instruct
the operator -- "reconcile before you discard; do not rubber-stamp the loss" --
and never names harness/reconcile/. The runbook asks for the activity and points
at no tool, which is worse than saying nothing: the operator is told to do it and
left to invent how, at the exact moment they are recovering from a failover.

That makes the remedy cheap and specific rather than open-ended: have :708 name
the tool. Recorded in the row so whoever picks up this P0 starts from a one-line
fix rather than from "bind the harness to the release path".

Note: correcting the AOAG runbook is not in this claim's scope, and the row now
carries the pointer instead.
… is its inverse (BACKLOG #1100)

02-pipeline-reliability.md row 145 claimed six MEFOR_TEST_*-gated pipeline suites
are "named in no workflow step", citing batch_handoff_statements and engine-shard
recovery, and asserting they are "in neither the steps nor the gate regex".

BOTH PARTS ARE FALSE FOR BOTH NAMED EXAMPLES:
  tests/test_adr0075_batch_sqlserver.py     ci.yml:1375, sqlserver-store step
  tests/test_shard_recovery_sqlserver.py    ci.yml:1371, same step
  adr0075 and shard_recovery are both in the gate alternation at ci.yml:993
The cited anchor :424-428 had drifted onto a comment about CI run timings; the
"MUST list every file" comment is at :983-988.

THE RESIDUAL GAP IS REAL AND SHARPER THAN THE ROW STATED. Of 54 MEFOR_TEST_-gated
suites, 19 are named in no workflow step, and every server-DB step invokes
EXPLICIT FILES rather than a directory -- so an unnamed suite runs nowhere on a
real backend. THREE OF THE 19 ARE MATCHED BY THE GATE REGEX:

  test_adr0157_fence_scope             8 tests
  test_sqlserver_sync_handoff_offline  6 tests
  test_adr0071_fusion_wiring

each named ZERO times anywhere in .github/ (positive control: shard_recovery_
sqlserver = 1). A change to any of them PULLS the expensive server-DB legs and
then never executes them -- the leg goes green having not run the suite the gate
fired for.

ci.yml:983-988 states only one direction of the invariant: the alternation must
list every file the steps run. THE INVERSE IS UNSTATED AND VIOLATED THREE TIMES:
every file the alternation lists should be run by some step. That asymmetry is
why this went unnoticed -- the stated half is checked by the comment's own
instruction, and nothing looks at the other half.

Stays P0. The original blast radius (duplicate PHI delivery across engine shards)
is in fact covered, since shard_recovery and adr0075 both run; what remains is
ADR 0157 fence scope with no real-Postgres execution, which is a correctness
mechanism against duplicate delivery in its own right.
…s ceiling is missing (BACKLOG #1100)

02-pipeline-reliability.md row 146 is CORRECT, and re-deriving it from the code
turns "no ceiling exists" into something a fixer can act on.

What is actually there:
  queue table carries an attempts column for EVERY stage    store.py:1319
  a max_attempts ceiling IS enforced                        :5756 mark_failed
                                                            :5816 mark_batch_failed
  reset_stale_inflight, 69 lines                            :5948 -- references
                                                            NEITHER attempts NOR
                                                            dead_letter

So the ceiling is real but sits ONLY on the caught-Python-exception path. A hard
abort -- C-extension segfault, OOM kill -- calls neither mark_failed nor
mark_batch_failed, and recovery runs reset_stale_inflight instead, which re-pends
the head without counting anything. The lane re-runs and the process dies again,
exactly as the row says.

THE FIX HAS A LOCATION: the increment must happen at CLAIM time or inside
reset_stale_inflight, NOT on the failure path -- because the failure path is
precisely what a hard abort skips. A ceiling added to mark_failed would pass
review and change nothing about this failure mode.

Also recorded: G6 is an OUTBOX-stage mechanism throughout (every reference reads
OutboxItem.attempts), which is why it does not cover the split ingress/routed
path. Worth stating because "there is a poison ceiling" is true and misleading
in the same breath.

Verified by reading the whole function via AST rather than a byte window -- the
same instrument that produced a wrong member count earlier tonight.
…rvives (BACKLOG #1100)

16-security-phi-and-supply-chain.md row 201 said nothing asserts that the
MEFOR_MIN_DETECTORS floor matches the real list, that the spec parses, or that a
partially-mangled secret is caught. TWO OF THOSE THREE ARE NOW FALSE.

test_scan_tokens_source.py carries 56 tests. The spec IS parse-asserted
(test_min_spec_parsing_rejects_nonsense, test_unrecognised_require_value_refuses)
and a partially-mangled secret IS covered (test_present_but_unusable_token_source_
fails_closed, parametrized over `mangled`, whose docstring records that a mangled
secret once yielded ZERO detectors). Ran the cited tests: 7 passed.

Materially, the ESTATE half no longer depends on the token list at all. BACKLOG
#321's structural estate-identifier shape detector fires with NO token source
present, and the allowlist validator refuses an entry broad enough to disable it.

DEPENDENCY STATED IN THE ROW ITSELF: that detector is commit c395944, which is on
this builder branch and NOT on main. If the plan edit lands without it, the cell
is wrong. A row whose truth depends on an unlanded sibling commit has to say so,
or it becomes a false claim the moment the two are separated -- and they are
separable, because I reported these items as individually landable.

THE SURVIVING CLAIM IS THE INTERESTING ONE AND IT STAYS P0. Every floor test uses
a SYNTHETIC floor (names=2 + estate=2 + site_prefixes=1), so nothing asserts the
real names=7,estate=13,site_prefixes=1. That cannot be fixed in pytest:
scan-tokens.local.txt is gitignored and the real list arrives only via
MEFOR_FORBIDDEN_TOKENS, so no checkout can hold it. Any real fix must compare the
floor against the list INSIDE THE GATE RUN. Recorded so the next attempt does not
start by writing a unit test that cannot see the data.

Anchor corrected: security.yml:403 -> :674 (commented at :655).
…G #1100)

16-security-phi-and-supply-chain.md row 200 said the continue-on-error guard
pattern "was never extended to security.yml". IT WAS. tests/test_security_posture.py
is that guard -- 12 tests, all passing, last touched 72e6709 on 2026-08-10 under
BACKLOG #1079.

It covers BOTH vectors the row names:
  test_required_jobs_carry_no_continue_on_error
  test_required_jobs_declare_no_skippable_job_level_if
       -- "a job-level `if:` is the other way a required context silently never
          reports", allowlisted per job

_BLOCKING_SECURITY_JOBS is exactly the seven jobs this row lists, and each is
asserted present in .github/required-contexts.txt, so "blocking" is a checked
claim rather than a label. The module also runs the REVERSE direction (sbom and
trivy must KEEP continue-on-error, catching a silent promotion), and it is not
vacuous by construction: test_every_security_job_is_classified fails when a new
job arrives in security.yml unclassified.

THE REASON THIS ROW SURVIVED IS WORTH RECORDING, BECAUSE IT WILL RECUR. The
guard's own module docstring restates this row's claim VERBATIM -- "nothing
guarded it: the three tests in this repo that read a workflow's continue-on-error
cover quality-advisory.yml and freethread-smoke.yml" -- as THE HISTORY IT WAS
WRITTEN TO CLOSE. Anyone who greps for the claim finds it, in the very file that
refutes it, and comes away confirmed. A test that documents the defect it fixes
reads exactly like evidence the defect is open.

Second closure of this sweep, after row 83. Both were P0s asserting a gap that
the engine or its CI had already closed, and in both cases the refutation was one
file away from the row's own citation.
…e control (BACKLOG #1100)

16-security-phi-and-supply-chain.md row 199 is CORRECT and still open.
FEATURE-COVERAGE-PLAN.md returns zero hits for all 17 of ADR 0135 and 0138-0153,
and its status blocks still date to 2026-07-13.

Re-measured WITH A POSITIVE CONTROL, which is the part worth keeping: ADRs
0010/0023/0030/0066 DO resolve in that file. Without that, "zero hits" is
indistinguishable from a grep that matches nothing for a reason of its own -- the
exact failure that made an earlier probe in this sweep report 0 for eight ADRs it
had never actually tested.

Zero-hits claims now stand 3 verified-true (05:95, 09:122, this row) to 1 broken
(05:98, the HTTP listener auth row). Worth recording as a base rate: the class is
productive precisely BECAUSE it usually holds -- when one breaks, it breaks
loudly and in the direction of understated coverage.

The row is annotated rather than changed. It is also the row whose staleness would
be hardest to notice from inside the document, because the instrument it indicts
is the same one a reader reaches for to check it.
…rse than suspected (BACKLOG #1100)

10-auth-rbac-and-active-directory.md row 91 carried this as a SUSPECTED live
defect. It is confirmed, against pyspnego's own signature rather than by
inference:

    spnego.server(hostname: str = 'unspecified', service: str = 'host', ...)
      hostname: The principal part of the SPN. Required to build the SPN.
      service:  The service part of the SPN. Required to build the SPN.

The library BUILDS the SPN from the two fields. Both acceptor sites pass the whole
SPN into service= -- auth/ldap.py:315 and :375 -- and settings.py:1905 documents
kerberos_spn as "HTTP/host.example.com".

WORSE THAN THE ROW ASSUMED: hostname is never passed at EITHER site, so it takes
its default. The acceptor principal is HTTP/host.example.com/unspecified, not
.../<hostname>. The row inferred a hostname would be supplied from somewhere; none
is.

Scope stated honestly per CLAUDE.md section 0: kerberos_enabled defaults to False
and is marked experimental (settings.py:1904), so this WOULD bite the first site
that turns Kerberos SSO on. It is not affecting anything now, and the conditional
is the accurate tense -- but the row's blast radius (a working-looking feature
that always fails, every failure an audited generic reject) is correct for that
site.

Three anchors re-pointed: :300 -> :315, :360 -> :375, :1846 -> :1905.

Not fixing the code here: that is auth-surface engine work outside this claim, and
the row now carries the exact evidence -- both call sites, the signature, and the
missing hostname= -- so the fix does not need re-derivation.
…drifted anchors (BACKLOG #1100)

10-auth-rbac-and-active-directory.md row 93 is CORRECT on every claim. Only its
citations had rotted, and they had rotted in a way that reads as confirmation:

  cited auth/ldap.py:182-187 as the ACCOUNTDISABLE reject
        -> that range now lands on the ATTRIBUTE LIST, which is the other thing
           this same row cites. A reader checking the anchor sees plausible code
           and moves on.
  actual reject          auth/ldap.py:197-201   (uac & 0x2)
  actual attribute list  auth/ldap.py:185-192   (requests userAccountControl)
  _find_user             auth/ldap.py:174
  resolve_principal      auth/ldap.py:277
  _probe_principal       service.py:1244        (cited :1207), calls it at :1253

Verified by reading _find_user and resolve_principal whole via AST rather than by
grepping a window: neither contains accountExpires, lockoutTime or UF_LOCKOUT.

So an AD account that is EXPIRED or LOCKED but not explicitly DISABLED is accepted
by all three password-free paths -- Kerberos SSO, OIDC, and the ADR-0079
reconciler, which would probe it PRESENT every pass. Offboarding-by-expiry, the
common HR pattern, would not propagate. service.py:959 states the shared path in
as many words: "Roles come from resolve_principal -- the same password-free LDAP
lookup Kerberos uses".

Not fixing it: auth-surface engine work outside this claim. The row now carries
the exact reject site, the exact attribute list, and the three entry points, so
the fix does not need re-deriving.
…can see (BACKLOG #1100)

10-auth-rbac-and-active-directory.md row 92 makes three claims. Two are confirmed
from here; the third cannot be, and saying so is the point of this commit.

CONFIRMED
  the ADR status line still reads exactly "Proposed -- code COMPLETE, awaiting
  lab validation", and its inline note adds "flips to Accepted only when runbook
  cells L6a, L9 and L18 report"
  docs/testing/ holds 26 files, all plan documents, with no AD-lab run record

NOT CHECKABLE FROM THIS REPOSITORY
  whether L6a / L9 / L18 have since run. The runbook is
  docs/security/AD-FEDERATION-LAB-RUNBOOK.md, and docs/security/ DOES NOT EXIST
  in this checkout -- it is the private companion repo. My brief also assigns
  that half to the ASVS Tracker, so the constraint and the practical limit
  coincide.

The row now says UNKNOWN for that clause rather than leaving it reading as
CONFIRMED OPEN. The distinction matters here more than usual: L18 is described as
the proof of a control that a review once found to be a live privilege-escalation
route, so "we have not verified this" and "this is still broken" are very
different statements to leave in a security test plan. The ADR status is the
honest public proxy -- it has not flipped -- and the row now says that instead of
implying more.

This is the first row in the sweep whose evidence lives outside the repository. A
verification pass has to be able to say "I cannot see this from here" without
either guessing or going quiet.
… reader could refute it with (BACKLOG #1100)

10-auth-rbac-and-active-directory.md row 90 is substantively CORRECT. All six
acceptor sites are still pragma: no cover, annotated "needs real AD" and
"requires a domain-joined server + keytab":

  ldap3 LDAPException arms   :267  :289          (cited :252, :274)
  SPNEGO acceptor lines      :313 :321 :373 :378 (cited :298, :306, :358, :363)

Zero workflows mention ldap, and there is no OpenLDAP / Samba / 389ds service
container anywhere.

ONE CLAUSE IS FALSE AS WRITTEN: "no self-hosted runner ... exists in
.github/workflows/". One does -- selfhosted-win2025-sql.yml :: sqlserver-real,
"SQL Server 2025 suites (real hardware)". It mentions no ldap, kerberos, spnego,
ad_domain or directory, so the row's INTENT holds exactly; its literal claim does
not.

That is worth fixing in both directions. Defensively: as written, a reader can
refute a P0 by pointing at one file, and a row that can be dismissed on a
technicality does not survive the meeting it matters in. Constructively: A
SELF-HOSTED WINDOWS RUNNER WITH A LABEL SCHEME ALREADY EXISTS AND IS PROVEN, so
the remedy here is "point an existing pattern at a directory", not "stand up
runner infrastructure". The row previously implied the expensive half was
missing when it is already built.

This is the sixth row in the sweep that understated something -- coverage, its own
gap, or as here, how close the fix already is.
…at the moved gate (BACKLOG #1100)

03-store-and-data-lifecycle.md R3 is CONFIRMED. The gate has MOVED since the row
was written, which is why its anchor no longer showed the defect:

  cited  __main__.py:1968-1975 "builds unbounded_windows"
  actual config/retention_classification.py:186 defines it (20 lines)
         __main__.py:2240 is its ONLY caller: _unbounded_windows(settings)

Read whole via AST, unbounded_windows contains no registry / connection /
per_connection / overrides / inbound token. It sees global settings and nothing
else.

The override that defeats it is documented in the code that creates it,
wiring.py:3125-3126: "None = inherit the global [retention].messages_days window;
0 = keep this connection's bodies forever; >0 = days" -- and pipeline/retention.py:150
honours it at purge time.

BOTH HALVES ARE INDIVIDUALLY CORRECT AND JOINTLY PERMISSIVE. A deploying PHI
instance with a global 30-day window would pass the startup gate while every
inbound set to messages_days=0 retains bodies forever, with no warning, no audit
entry and no test. Written conditionally per CLAUDE.md section 0: there are no
deployments, so nothing retains PHI today; it is wrong in the shipped code.

This is the most consequential of the three code defects this sweep has confirmed,
because the control is LABELLED fail-closed and audited (ASVS 14.2.4) -- its
existence is exactly what a reviewer would rely on instead of checking. That is
the compensating-control-on-a-false-premise shape in its purest form.

Not fixed: store/config surface, outside this claim. The row names the fix -- hand
the gate the registry's resolved per-connection windows rather than settings alone.
…what is actually missing (BACKLOG #1100)

03-store-and-data-lifecycle.md R2's core claim is CONFIRMED: no workflow sets
MEFOR_TEST_FORCE_AAD_BIND -- 0 occurrences across .github/workflows/, against a
positive control of 14 for MEFOR_TEST_SQLSERVER. aad_bind still defaults True
(settings.py:388) and make_cipher's library default is still write_v2=False
(crypto.py:812).

BUT "THE SHIPPED WRITER IS BARELY EXERCISED" NOW OVERSTATES IT, and the flag's own
docstring (tests/conftest.py:133-138) is the authority:

    "The flag is OFF by default and stays meaningful even though [store].aad_bind
     now DEFAULTS TRUE (ADR 0148 GIVEN 1). ... The settings default governs what
     open_store builds; this flag governs every cipher in the process, which is
     what makes the sweep exhaustive rather than merely representative."

The flag is a SWEEP AMPLIFIER, not a gate: unset, the suites still run and
open_store still builds the mfenc:v2 writer because the setting defaults True. So
the shipped writer IS exercised. What never runs is the process-wide forcing that
also catches ciphers constructed with an EXPLICIT write_v2=False.

The parenthetical was wrong too: EIGHT test files reference the flag, not
conftest.py alone.

STAYS P0. The residual risk is exactly as stated -- a half-threaded cell_aad on
purge re-encrypt, document strip write-back, attachment re-seal or restore
surfaces only under the forced sweep, and that sweep runs nowhere. Narrowing the
headline does not shrink the gap; it stops the row being refutable by anyone who
checks whether the writer runs at all.
… name the false premise (BACKLOG #1100)

Anchors had drifted ~500 lines (:3523 -> :4026, :3732 -> :4229/:4235).
Substance CONFIRMED, and by a live run rather than a reading:

  body 'DOE^JANE\X00\SMITH'
  guard at :4026, '\x00' in text  -> False
  summarize()                     -> 'MRN MRN123 \xb7 DOE, JANE\x00SMITH'

So the NUL is MANUFACTURED after the control that promised there was
none, and rides summary=summarize(peek) into a pre-ACK enqueue_ingress
that the AST pass confirms is outside every try.

The sharpest part is that the guard's OWN COMMENT (:4031-4033) is the
false premise -- it claims summary is NUL-free 'for the rest of this
handler', and summary is exactly the derived value for which that is
untrue. SDS-3.7 in the engine's own words.

Also corrected two things the row got wrong in MY favour: summarize
lives in parsing/summary.py:27, not parsing/peek.py, and the Postgres
SQLSTATE 22021 claim is now ATTRIBUTED to the engine's docstring at
:410 rather than asserted -- a live Postgres reproduction is still
owed and the row now says so.
…hapter that did not drift (BACKLOG #1100)

TrayApp is tray/app.py:42-154, which is 113 lines, not the '154 lines'
the row claimed. 154 is the END LINE NUMBER relabelled as a LENGTH,
overstating the untested surface by 36%. Same root cause as the three
false enumerations I committed earlier this session: take the number a
tool returned, then call it something narrower than what it measures.

Everything else in ch14 verified EXACT, which is itself the finding:
  :450  Start SERVICE_AUTO_START
  :463-464  AppExit Default Restart + AppThrottle 5000
  :472-477  the virtual-account default block
  :516-548  the S4 ACL block ('applied AFTER ... ObjectName is set')
  :81   Resolve-Nssm
  winshell.py:299-451 spans precisely the ten dispatch functions
        _add_icon through _message_loop, which ends at :451

Every wiring_runner.py anchor checked in ch02-10 had moved; none here
did. So drift tracks the CHURN OF THE CITED FILE, not the age of the
plan -- a re-sweep should re-point per file, not uniformly. Recorded in
the row so the next sweeper does not redo this chapter.
… three-state collapse (BACKLOG #1100)

Every hop of the row's chain verified in code:
  _read_toml (tray/config.py:279-286) -- 'None on any read/parse
    failure. Never raises' -- catches (OSError, ValueError) at :284,
    and PermissionError IS an OSError, so -LockConfigDir yields None
  service_toml_uses_tls  :212-213  'if not service_toml: return False'
  build_engine_url       :188      renders http:// when tls is False

The row described a symptom; the defect underneath is a THREE-STATE
COLLAPSE. Parsed-and-no-TLS, file-absent, and file-present-but-
UNREADABLE all become the same None and then the same False. The
distinguishing information is destroyed at :284, so NO downstream fix
is possible and the test has to drive the unreadable case specifically
-- which is why 'a healthy engine renders WEDGED' is not a UI bug.

Recorded the contrast rather than just the finding: seat-tick.ps1
handles the identical distinction correctly, with a roster-blind flag
and a comment saying a roster that could not be read is not evidence
that nobody is live. Same distinction, one place kept it and one
folded it into the empty case.
…tion' P0 -- it is false (BACKLOG #1100)

The most consequential correction of this sweep. The row asserted a
TOTAL coverage gap over work that has DEDICATED CI STEPS BUILT TO
COVER IT, and would have sent someone to build tests that already
exist and already run.

Refuted, two of three clauses:
  'no workflow file contains shard'  -- ci.yml has it 7+ times, incl.
    named steps at :1348 and :1551 and the path gate at :993.
    Positive control: 'test' matched 24/24 workflow files.
  'named by no CI step, so they execute nowhere' -- all three are
    named (ci.yml:1371, :1372, :1571) and the steps set EXACTLY the
    variable the modules gate on (MEFOR_TEST_SQLSERVER: '1' against
    not os.getenv('MEFOR_TEST_SQLSERVER')), so the gate makes them RUN.

The ci.yml comments say these steps were added to close this very gap,
and tests/test_serverdb_ci_coverage.py now fails if a module-gated
suite is added without being named -- a meta-gate against exactly this
regression. The row was describing a state that had already been fixed.

What survives is real but far narrower than P0: test_supervisor.py
drives _FakeProcess (11 refs, docstring 'without launching real engine
subprocesses'), no Popen/create_subprocess. Re-scoped the row to that:
shard RECOVERY is covered on both server backends, SUPERVISOR PROCESS
HANDLING against a real subprocess is not.

Checked the surviving clause BEFORE withdrawing, so the correction does
not overshoot from 'zero coverage' to 'fully covered'.
…ology P0 confirmed exact (BACKLOG #1100)

Row 112 WITHDRAWN. The document was FIXED after the plan was written:
the '~500 - low-thousands msg/s / ~40M+/day' tier NO LONGER EXISTS.
SYSTEM-REQUIREMENTS.md:216-219 now tops out at ~165 msg/s at 4 engine
shards and discloses the topology inline. Anchors drifted too (:163 is
blank; :195-198 is bench guidance). The alleged self-contradiction is
unreproducible: 'future direction, not built' appears NOWHERE in docs/.
Flagged the arithmetic even though it is moot -- ~500/~72 is 6.94x, not
the 7.23x claimed, so the multiplier did not come from the two numbers
the row set beside each other. Kept the row's last column, which is
still true: no doc-vs-measurement guard exists, so nothing caught the
over-claim while it was live and nothing will catch the next one.

Row 113 CONFIRMED, anchor EXACT -- worth stating precisely because the
two rows above it in the same chapter did not survive. TUNING-BASELINE
.md:150 is verbatim the 'per-shard SQLite ... no shared DB' store line,
with E_core ~42 / eta ~0.85 at :161-162. One qualification: both files
now DISCLOSE the topology (:165-171 separates the portable shape from
the non-portable absolute; SYSTEM-REQUIREMENTS:219 names it), so this
is a reproducibility problem, not a hidden-caveat one.

Three P0s examined in this chapter, three different verdicts. Grading
them as a block would have been wrong in both directions.
… row stated (BACKLOG #1100)

Row 92 CONFIRMED verbatim. The webconsole pyproject dependency really
is a bare 'messagefoundry', and the comment beside it reads: 'A PEP 508
compat RANGE is ideal (messagefoundry>=X,<Y); a bare dep is fine for
now -- the ENGINE_UI_SEAM handshake (assert_engine_seam) is the runtime
backstop.' That sentence IS the finding, not evidence for it: layer 1
is knowingly absent and the stated justification is that a LATER layer
covers it.

COMPOSED IT WITH THE serve_ui ROW, which neither row says alone. If the
PEP 508 range does not exist, assert_engine_seam is not a backstop, it
is the ONLY layer -- and per that row it does not degrade to a broken
/ui, it propagates UiSeamMismatch and takes the whole engine down. A
documented three-layer defence that is really one layer whose failure
mode is total, with the pyproject comment pointing AT that layer as its
reason for relaxing.

Row 94 CONFIRMED with a positive control on the absence claim: an AST
pass finds 13 add_argument calls in harness/reconcile/__main__.py (zero
would have meant a broken probe, not clean code), the capture ones
being --port/--out/--host/--ack-mode, and none is --anonymize or
--salt-env. anonymizer appears nowhere in __main__.py.

The sharp part is that the de-identification is BUILT AND CORRECT and
simply unreachable: capture.py:133-137 applies it and FAILS CLOSED on
any anonymizer error, calling itself 'this PHI choke point'. Not a
missing control -- a finished fail-closed control with no way to switch
it on, which is exactly why capture.py reads as safe in isolation.
…-output defect found beside it (BACKLOG #1100)

Row 93 CONFIRMED, anchors exact -- but the line that actually leaks is
NEITHER of the two cited. Both renderers get their values from one
shared helper, Difference.describe() at normalize.py:102-104, whose
entire body is:

  return f'{self.kind} @ {loc}: left={self.left!r} right={self.right!r}'

The !r on a raw HL7 field value IS the PHI, and because it is one
helper feeding both paths the fix belongs there, not twice in
report.py. render_text's default really is max_diffs=20 (:50) and
render_json really does emit left/right unconditionally (:35-36).

SEPARATE DEFECT FOUND WHILE VERIFYING, recorded nowhere else:
report.py writes non-ASCII glyphs to operator stdout at :63 (U+2717),
:67 (U+2026), :72 (U+2713/U+2717). On a stock Windows cp1252 console
that raises UnicodeEncodeError -- on a WINDOWS-TARGETED product. So the
reconcile report can crash WHILE PRINTING rather than print wrongly,
and no assertion about report CONTENT would ever catch it.

Row 91 anchors re-pointed: settings.py :672 -> :710, api/app.py :4951
-> :5166 (~215 lines). Worth noting why that one is nasty: :4951 now
lands on an unrelated DR_OPERATE dependency, so the stale anchor reads
as plausible code rather than as an obvious miss.
…rse than stated (BACKLOG #1100)

Row 97 CONFIRMED, and the confirmation is sharper than the claim. No
JavaScript-execution tooling exists anywhere: playwright, jsdom,
selenium, puppeteer, node --test all return zero across tests/,
packaging/ and .github/workflows/ (positive control: 173 test files
match 'console', so the probe was sound).

But EIGHT test files DO reference app.js -- csp_canary, hardening,
logout_affordance, mfa_gate, session_watchdog, static_allowlist,
webui, webconsole_mount -- all asserting on the SERVED TEXT. Those
eight are exactly the 'grep-matched strings' the row warns about, and
ONE OF THEM IS NAMED FOR THE WATCHDOG ITSELF. So a coverage review
that counts files touching app.js finds eight and concludes the
surface is tested. Asserted-as-text versus executed is the distinction
that matters, and no count distinguishes them.

Row 99 CONFIRMED, all three anchors exact -- each range ends precisely
on its 'Approval id:' line (:105, :212, :685), under 'Reload/Purge/
Replay held for approval'. Three independently-written dead-ends with
identical shape, which is what makes it a design gap and not three
oversights.

Recorded a navigation note because it cost me time: the module tree is
messagefoundry_webconsole/pages/ at the REPO ROOT; packaging/
messagefoundry-webconsole/ holds only metadata and tests.
…the asymmetry is the defect (BACKLOG #1100)

G2 CONFIRMED, all four anchors exact. db_lookup and fhir_lookup are
imported at :32/:33 and listed in __all__ at :150/:153; content_match
appears NOWHERE in messagefoundry/__init__.py. This row is trustworthy
precisely because it carries its own positive control -- the same
search that returns zero for content_match finds both comparators, so
the zero is a fact about the code and not about the probe.

G3 CONFIRMED, anchor re-pointed :100 -> :101 (the cited line holds the
sibling 'connection_restored': 'connection_error' entry).

Ran the absence claim with a control, and the control is what makes it
a finding rather than a failed grep: 'connection_started' occurs in
exactly ONE place in messagefoundry/ -- the _AUTO_RESOLVE mapping --
while the same search finds 'connection_stopped' genuinely emitted at
alert_sinks.py:682.

So the asymmetry IS the defect: one half of an auto-resolve PAIR can
never fire. connection_stopped raises and connection_started only ever
resolves, so a lane that stops on an internal error and is restarted
never clears. An alert that is raisable but not resolvable is worse
than one never wired, because the operator sees a live alert against a
healthy lane and learns to distrust the panel.
…chors drifted (BACKLOG #1100)

Substance CONFIRMED and stronger than the row states. Anchors fixed:
the assignment is api/app.py:1134 (cited :1120), /config/reload is at
:2791 (cited :2741, now blank), and the cited :5485 lands on an
unrelated phi_read_hop_secure parameter.

The row claims TWO write sites. There is exactly ONE.
'app.state.alerts_settings =' occurs once in the module (:1134);
every other occurrence is a constructor parameter (:1038, :5453), a
call argument (:1546, :5580), or a READ via
getattr(request.app.state, 'alerts_settings', None) or AlertsSettings()
(:1516, :2517, :4517). The 'lifespan startup' site is not a second
write, it is the plumbing feeding the one write.

That makes the gap CLEANER to test than the row implies -- a single
assignment is a single point to prove unreachable from reload. And the
read pattern matters: 'or AlertsSettings()' means a reload-time change
does not merely fail to apply, it silently falls back to DEFAULTS at
every read site, so the operator sees alerting behaviour that matches
neither the old config nor the new one.
…alked into first (BACKLOG #1100)

The row's own assessment is CONFIRMED structurally. AST census:
_ALERT_EVENT_TYPES holds 18 types, messagefoundry/ emits 22 distinct
{'type': ...} literals, giving 4 emitted-but-not-routable and 0
routable-but-never-emitted. All 4 are deliberate --
connection_restored, leadership_lost and dr_released are three of the
four _AUTO_RESOLVE KEYS (resolution events, not raisable alerts), and
test_email is the API's diagnostic probe. So there is no live
type-level drift, exactly as the row already said.

RECORDED A SECOND NAIVE-GUARD TRAP, worse than the method-name-vs-
event-type one the row already names, because I hit it: the constant
is frozenset({...}), NOT a bare set literal, so a regex expecting '{'
after '=' matches nothing and yields an EMPTY routable set. Every
emitted type then reads as unroutable. My first pass produced a
confident 22-of-22 'EMITTED BUT NOT ROUTABLE' list -- indistinguishable
from a catastrophic real finding, and refuted only by noticing that 0
routable-but-never-emitted cannot coexist with it.

This matters because the row's whole point is that someone must WRITE
this guard. Parse with AST and assert the routable set is non-empty
before comparing; the failure mode is to fail LOUD and WRONG.

Independent corroboration of G3 fell out of the same census, from a
probe built for a different purpose: exactly 3 of the 4 _AUTO_RESOLVE
keys are emitted, and the missing one is connection_started.
… trap recorded (BACKLOG #1100)

Every figure in the chapter-05 summary paragraph checks out when the
tables are PARSED rather than read: 67 CONN-nn rows, the 63 T / 4 C /
0 A split, CONN-34/35/38/49 present as the C rows, and the nine
claimed P0 T rows all present and all P0 with nothing claimed that is
missing. A clean accounting row, which is worth recording so nobody
re-derives it.

Recorded the trap that caught me, because it will catch the next
counter: a naive scan for a P0 priority cell returns ELEVEN, not nine.
The two extras are RISK-TABLE rows -- the risk table carries its own
priority column. The chapter has TWO tables with P0 cells and only ONE
is the T-row matrix this sentence counts, so a discrepancy against 9 is
the counter's error and not the document's.

This is the same shape as the false enumerations I committed earlier in
this sweep: rows from two tables, counted together, then named after
one of them.
…ied forward unchecked (BACKLOG #1100)

Ran the Steward's audit method against my own work: a correction that
replaces a wrong NUMBER while leaving the surrounding STORY standing.
Two hits, both mine, both blessed by me earlier today.

ch14 r113 -- the coverage claim was FALSE. I corrected TrayApp's line
count (154 -> 113) and carried 'test_tray_shell.py only asserts imports
+ non-zero struct sizes' forward without opening the file. It has SIX
tests; only ONE is the imports/structs one. Two of the other five cover
this row's OWN stated risk: test_disabled_action_is_not_dispatchable
(an action routed to the wrong handler) and
test_assign_command_ids_maps_actionable_items_only (TRAY-20's subject).
The gap is real but much narrower than 'behaviourally untested' -- what
is genuinely uncovered is the Win32 pump (which icon paints, whether a
toast fires, WM_DESTROY/WM_ENDSESSION teardown). Re-scoped TRAY-19/20/
22 to the pump rather than to action routing.

ch17 r112 -- conclusion survives, its SUPPORT does not. I kept 'no
doc-vs-measurement guard exists' as still-true, including its
enumeration. test_feature_map_claims.py does not check 'only' three
things; it has six tests. None compares a PUBLISHED number against a
MEASURED one, which is WHY the conclusion survives -- but a reader
quoting the enumeration to argue the file is nearly empty would be
wrong, and the enumeration is what gets quoted.

Both are the same shape I have been writing into other people's rows
all afternoon: I checked the part that was false and carried the
adjacent part because it sat next to something I had just verified.
…tradicting themselves (BACKLOG #1100)

Both rows I withdrew earlier today kept their ORIGINAL coverage and
priority columns, which I never touched. As published in between, ch17
r111 CONTRADICTED ITSELF: its evidence column said the suites run in
CI on both server backends while the coverage column beside it still
said 'No' and the priority still said P0. r112 carried the false
'checks only three things' enumeration verbatim in its coverage column
even after I corrected that same enumeration two columns to the left.

Fixed both. Coverage columns now state what is actually covered.
Priorities are FLAGGED as needing re-grading rather than re-graded by
me: I am not the party to assign the number, but a P0 left standing on
a withdrawn finding reads as an open defect forever, which is the worse
of the two errors.

Also re-verified the ch06 r74 claim I had carried while re-pointing its
anchors, and that one HOLDS verbatim: _eq() at :74 is
'return type(expected) is type(got)' with the docstring 'exceptions
compare by type', and _EMPTY_FIELDS at :183-189 contains a literal
blank-segment line whose own comment names it. The parity suite really
does certify the defect as a PASS, via a type-only exception comparison
that is correct for its purpose and wrong for this case.

Not every carried claim was wrong. The point of the audit is that I had
not checked any of them -- I verified what a row got wrong and then
took its neighbours on trust because they sat next to something I had
just confirmed.
…pointed (BACKLOG #1100)

The chapter I wrongly skipped, and the row is right. ci-gate is at
ci.yml:2132 and its needs: (:2135-2141) parses to exactly changes,
sqlserver-store, postgres-store, load-test, load-test-sqlserver,
windows-service-smoke. 'ide' is ABSENT (that job is :818), so the leg
is not rolled up and a red IDE leg does not block a merge.

Anchors re-pointed: the cited :265-274 is now a uv pip install block
and :1386-1392 is a DR seed-gate step, so neither landed on what it
claimed.

The distinction is easy to invert and I had it inverted in my own
project memory, which lumped 'ide' in with the rolled-up legs. Fixed
there too. 'Not individually required' and 'cannot block a merge' are
DIFFERENT properties: the server-DB and load legs have the first and
not the second; ide is the only leg with both.
… (BACKLOG #1100)

Applied to myself the standard the Lander named: a retraction needs the
same evidence as an assertion, and the asymmetry feels like humility
while being the same laziness in the other direction.

I withdrew this P0 as STALE and wrote 'the document was FIXED after
this row was written'. I never checked that. 'The claimed text is not
in this file' and 'the text was removed from this file' are different
statements and I published the stronger one.

git log -S settles it, and the answer is a THIRD verdict:
  'low-thousands' NEVER appears in docs/SYSTEM-REQUIREMENTS.md at any
  point in that path's history -- nothing was removed from it
  it DID exist elsewhere in the repo before this plan (5fa6db9,
  abedf86, 39990f8 'bring the documentation set back in line with
  the code')
  today it survives in docs/ ONLY in this row
  the file's current ~165 msg/s table arrived via 959821a (#79)

So the over-claim was real in SOME document and this row attributes it
to a file that did not contain it. Whether it was ever live in THIS
file is UNDETERMINED and a path-scoped query cannot settle it.

MIS-CITATION, not staleness -- and the worse of the two: staleness is
blameless drift, while a quotation that cannot be sourced to the file
it names discredits the row carrying it.

Three passes to get here ('stale', then 'never existed', then this).
The first two were reached faster and on thinner evidence than I would
have accepted for an assertion.
…OG #1100)

Row 128 CONFIRMED, and its ranges were right where row 122's were not:
isExecGated() is defined at cli.ts:67 and guards at :152 and :186,
both inside the cited :147-152 / :183-189. The 'nothing asserts' half
holds with a POSITIVE CONTROL -- isExecGated is referenced by NO file
under the IDE test directories, while 8 files there mention 'exec', so
the directories exist and the search works. The zero is about coverage,
not about the probe. A CWE-426 untrusted-workspace exec gate with no
test is exactly as bad as the row prices it.

Row 131 CONFIRMED VERBATIM, and the module states both halves in one
comment: invariant 1 opens 'NOTHING ON THE RECORD IS EVER DROPPED' and
then explains why that must be engineered -- 'connection upsert is a
FULL REPLACE of the table, so a key the form fails to render is a key
the form DELETES.' The invariant is the MITIGATION; the full replace is
the HAZARD that makes it load-bearing. The row's real point is that the
tested part (planSave) is the mitigation while the untested part is
what the mitigation depends on: the webview posting every key.

Recorded a caution in the row because it nearly caught me. Reading ONLY
the cited first line makes the module look like it CONTRADICTS the row.
The qualifying sentence is two lines below. I had the false finding
half-written before reading the whole block -- a byte-window read where
a structural one was needed, which is the same mistake this sweep keeps
correcting in the plan.
…t (BACKLOG #1100)

Row 123's title 'auth.ts has zero tests' is literally false
(ai-policy.test.ts:14 imports peekToken from it) and its framing
understates the trap. Corrected to name the real gap.

Measured:
  signIn is auth.ts:108; the guard is assertTargetAllowed(url) at :111,
    inside the cited :110-115 -- anchor EXACT
  assertTargetAllowed is NOT untested. engine-target.test.ts imports it
    from ../../engineTarget and asserts at least six cases, including
    'non-loopback over plain http is REFUSED (the core SEC-005 case)'
    and 'an unparseable URL fails safe'
  NO test exercises signIn, so nothing asserts :111 is ever reached

So deleting that one line leaves all six gate tests GREEN. The control
is proven correct and its call site is unpinned -- the same shape as
the planSave/full-replace row, and the reason 'write tests for auth.ts'
is the wrong instruction. The test to write asserts that signIn
CONSULTS the gate BEFORE prompting: an ORDERING property, which no test
of the gate alone can express.

Second time today a 'zero tests' claim was not zero (after
test_tray_shell.py). Both times the coverage that existed sat one
import away from the thing the row was worried about.
…act (BACKLOG #1100)

Four for four, which is worth stating because it is the opposite of
what ch02-10 produced against wiring_runner.py. Drift really does track
the churn of the cited file.

124 signOut revoke -- the code states it in its own comments: :76 is
  'return true; // nothing to revoke' and :82 is 'return false; //
  could not reach the engine to revoke -- the session lives until it
  times out'. BOTH non-revoking paths return a value the caller cannot
  distinguish from success, which is what makes the missing test
  load-bearing rather than merely absent.

125 chat prompt -- the cited span really is four bare parts.push()
  calls in the handler body (summary, active editor code, task, user
  request). Adding a fifth is a one-line edit with NO seam to assert
  against. That is why it is a PHI risk and not a style complaint:
  CLAUDE.md section 9 confines the assistant to code_only, and that
  confinement currently exists only as the ABSENCE of a parts.push of
  a message body.

129 runTest.ts:13 is exactly
  'const extensionDevelopmentPath = path.resolve(__dirname, "../../");'
  so the suite loads the source tree, never the packaged artefact.

130 test_ide_artifacts.py contains exactly TWO tests, both HL7 media
  artifacts -- count and subject both right. Flagged as a CLEAN
  enumeration, because several counts elsewhere in this plan were not.
… monotonic (BACKLOG #1100)

All ten mirror anchors resolved against the 33 function declarations in
ide/media/stepsWebview.js. blockExtent:68 and captureBlock:83 were
already exact; the rest drifted +1, +17, +18 or ~+22.

The drift is MONOTONIC IN LINE NUMBER (+0, +0, +1, +1, +17, +17, +18,
+18, +18, ~+22), which is the signature of insertions ABOVE rather than
edits within. A single uniform offset would NOT have re-pointed these
correctly, so each was resolved individually. Worth recording as a
re-pointing method: check whether the offset is constant before
applying one.

The row's SUBSTANCE needed nothing -- it is already self-maintained,
recording 'Yes, as of BACKLOG #233', the steps-mirror.test.ts jsdom
parity suite, that both original grounds are spent, and the single live
divergence that suite found (canDropRow accepting a read-only code row
the webview refused) now closed.

Also correcting myself: I first read the anchor as clipLabel:30 and
diagnosed a dropped-digit transcription error. It is :309 -- MY OWN
TRUNCATED PRINT cut the last digit, and I diagnosed from the truncation.
Reading the full row dissolved it. Same byte-window mistake this sweep
keeps finding in the plan, committed against the plan.
…R than stated (BACKLOG #1100)

Row 65 CONFIRMED and the row UNDERSTATES its own finding. All 7
committed fixtures under ide/src/test/fixtures/lens/ lack 'suite', and
they ALSO all lack 'label' and 'operand' -- not merely adt.json and
IB_RADIOLOGY_SR.json as written. adt.json's complete key set is 13
keys (control, def_line, handler, handlers, kind, line_end, line_start,
module, nesting, outbounds, recognized, rows, test_src) with none of
the three at any depth, while messagefoundry/lens.py emits all three.
Positive control: the same walker that reports them absent returns
those 13 keys, so the absence is about the fixtures, not the probe.

Anchor re-pointed: suite is stepsModel.ts:42-44, not :29-32 (which is
now a row-KIND union). The comment at :42 confirms the drag/drop
scoping role -- it greys an up/down at a suite edge so a reorder never
crosses into or out of an if/for body -- and :552-553 consumes it.

Row 67 CONFIRMED, all three anchors drifted. The real path filter is
ci.yml:1007, grep -qE '^(ide/|\.github/workflows/ci\.yml)', so a PR
touching messagefoundry/lens.py does not match and the leg never runs.
The ide job is :818 and ci-gate's needs: is :2135-2141 without ide.

Best evidence is the workflow's own comment at :820: 'ide is NOT a
required check and ci-gate does NOT needs: ide'. The row's claim is
written into the file it describes.
…the prior commit (BACKLOG #1100)

60 broke lines 65 and 67 -- 7 and 6 columns against a 5-column header.
My replacement text contained bare | characters: a TypeScript union
rendered as 'note | ... | route', and a grep -qE alternation quoted
verbatim. Both are cell separators in a markdown table.

Replaced both with prose that carries the same meaning and no pipes.

THE GATE CAUGHT THIS AND I COMMITTED ANYWAY. I batched the column check
and the commit into one command block, so the MISALIGNED lines printed
and the commit ran regardless. That is the exact failure I hit early in
this session and wrote a rule against: RUN THE GATE AS ITS OWN STEP AND
READ IT BEFORE STAGING. Having the rule and having written it down did
not help, because batching is what makes the mistake convenient.

The information was on screen the whole time. It was not missing, it
was unread -- which is worse, and is the same shape as several findings
in the plan itself.
…ount (BACKLOG #1100)

I had ch01 down as out of scope because it has ZERO P0 rows. It has
THIRTEEN file:line citations, which is the sweep's ACTUAL subject.
'Chapters with P0 rows' and 'chapters with verifiable citations' are
different sets, and I had been prioritising by the wrong one all
session -- the same measure-one-thing-name-another error this sweep
keeps finding, now in my triage rather than my probes.

The chapter itself is in good shape. Checked:
  __main__.py:98   --shard        EXACT (serve.add_argument( at :98,
                                  '--shard' at :99)
  __main__.py:115  supervise      exact
  release.yml:477  release-harness EXACT
  __main__.py:349  generate       DRIFTED +1 -> :350

Re-pointed the one drift. The generate subparser is
'generate = sub.add_parser(' at :350 with the name on :351.

Worth recording how nearly I got that wrong: my first probe searched
for add_parser("generate" and returned ZERO, which reads as 'the
subcommand was removed'. It failed because the name is on the NEXT
line. A control (38 add_parser calls exist in the file) plus a broad
search found it immediately. Fourth misleading zero today from a
pattern-shaped probe, and the first one I caught BEFORE drawing the
conclusion rather than after.
…t (BACKLOG #1100)

ch07 cites the lens Steps backend at lens.py:270/285/1406/1423. :270
had drifted onto a BLANK LINE; the function is def _native_action_row(
at :271. Re-pointed.

Deliberately did NOT re-point the other three. They land on real code
-- :285 an assignment inside a params loop, :1406 a 'return (', :1423
an 'if field is not None:' -- but all three are MID-FUNCTION rather
than at a definition, and the row states no intent to check them
against. Marked NOT VERIFIED, ONLY NOT OBVIOUSLY WRONG.

That distinction is the whole limit of the blank-line scan and it is
worth carrying in the document rather than only in the handoff: the
scan finds anchors that drifted onto WHITESPACE and is blind to ones
that drifted onto PLAUSIBLE CODE. Silently 'fixing' the other three to
the nearest def would have manufactured precision I do not have.

One anchor rather than several, on purpose: ~8 minutes remained before
the projected window closed, and an uncommitted edit at cutoff is the
one state worth avoiding.
…1100)

ch07 cites EnvRef decode and bounded casts at wiring.py:195/226. :195
had drifted onto a BLANK LINE between the end of the EnvRef dataclass
and the factory below it. Re-pointed to :197, which is
def env(key, *, default=_UNSET, cast=...) -> EnvRef -- the definition
carrying the 'cast' this row names. EnvRef's own cast field is :194.

:226 NOT CHECKED and deliberately untouched. It lands on code, and the
row states no intent I can test it against, so re-pointing it would
manufacture precision I do not have. Same call as the three lens.py
anchors in the previous commit, and for the same reason: a confident
wrong anchor is worse than a visibly stale one, because a spot-check
reads it as fine.

Two anchors now off the 66-item worklist. Both were the whitespace
kind, which is the only kind the scan can find -- the plan's remaining
exposure is anchors that drifted onto PLAUSIBLE code, and no cheap
signal exists for those.
…6 row

Pre-resolving the mechanical half of this PR's conflict so only the semantic half is left
for its author. Lander-authored, joint-evaluated with the Liaison.

Computed target rather than resolved by eye: A=156 (merge-base), B=157 (head), C=158
(origin/main), so 159 entries. Compared by ADR NUMBER, this branch adds exactly one number
main lacks -- 0166 -- so the formula and the number-set agree here and the result is main's
index with the 0166 row inserted.

VERIFIED AFTER RESOLVING, and the first attempt was wrong in a way the count could not see:
appending 0166 to the end produced the right total of 159 while placing it AFTER 0167. It
now sits between 0165 and 0167.

The index is NOT strictly sorted on main -- it already carries three out-of-order pairs
(0086 after 0088, 0092 after 0096, 0100 after 0103). That is pre-existing and untouched
here: the out-of-order count is 3 before and 3 after, so this commit introduces no new
disorder and does not silently reorder anything.

Not touched: .github/workflows/ci.yml, a genuine semantic conflict for this branch's author.
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

PARKED -- this needs a design decision, not a merge resolution

Lander disposition, 2026-08-21, on the owner's go. Deliberately not closed and not re-cut. This PR changed disposition twice during assessment, both times because a live lane told me something the diff could not.

Durability first. Tagged on origin:

rescue/2026-08-21/pr433  ->  4c0b652834f9903d8ba5d7a223c25b55a02d078d

The pre-existing archive/mf/hopeful-chaplygin-3158c6 tag points at ddb7b073 -- 74 of this branch's 75 commits short of the tip. Closing on the strength of that tag would have discarded essentially the entire PR while looking like a filing decision.

Why parked rather than closed

1. It collides with an active rewrite. Four files on its gate surface are genuinely divergent from main:

scripts/hooks/worktree_gate.ps1     +47
scripts/worktree/_gate_receipt.ps1  +138  (absent from main)
scripts/worktree/install-gate.ps1   +45
scripts/hooks/mail-drain.ps1        +47

scripts/hooks/worktree_gate.ps1 is under three-way contention: main has moved it twice since this branch's base, this branch adds 47 lines, and it is being rewritten on another branch right now.

2. There are two competing receipts mechanisms, and resolving that as a text conflict would pick a winner by accident. main already has a receipts test with different content and no _gate_receipt.ps1, so its receipts mechanism lives somewhere other than a standalone file. This branch brings its own receipts test plus a 138-line standalone implementation. That is not a feature landing on empty ground -- it is a second implementation of something main already does differently.

The blocking question is which receipts mechanism survives. That is a design call about main's existing implementation versus this one. It is not a merge mechanic and it must not be settled by whoever resolves the conflict.

One file to DROP from any re-cut

tests/test_worktree_gate_quote_straddle.py
  #433 blob 11db30ab...  ==  main blob 11db30ab...   IDENTICAL

Already on main, byte for byte. It appears in the three-dot diff as "+133, new file" only because this branch's base predates the commit that landed it. Re-applying it is a no-op at best and a conflict at worst.

Measured honestly: that is one file, not a category. A sweep I ran for others of its kind reported .github/workflows/ci.yml as also already-landed; that was a false positive from a shell path-mangling failure that returned empty on both sides and compared equal. ci.yml genuinely diverges (3120d0f6 vs 8fde3b9c) and genuinely conflicts. The set is exactly one file.

State

behind main 71
commits / files (three-dot) 75 / 52
conflicts .github/workflows/ci.yml, docs/adr/README.md, scripts/hooks/worktree_gate.ps1
reviews 0

Park costs nothing -- it is already unmergeable, and its tip is now durable independent of this branch. Re-cutting it after the gate rewrite settles is a cheaper job than re-cutting it today against a file about to change underneath us.

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

LARGEST BODY OF UNLANDED WORK IN THE OPEN QUEUE -- measured, so "stranded" is not being read as "empty".

Method: for each of the 52 changed files, the lines this branch ADDED relative to its merge base ae76b9f, searched against main's copy of the SAME file at aed856b. Dot-prefixed paths read as origin/main:./<path>, after that rewrite silently emptied a comparison file elsewhere tonight and produced a confident wrong verdict.

landed (>=90% of added lines on main) 2
partial (<90%) 47 -- most at 0%
absent from main entirely 3

ABSENT
docs/adr/0166-sandbox-child-stderr-is-captured-and-relayed-with-content-confined-below-info.md
scripts/worktree/_gate_receipt.ps1
tests/test_gate_install_receipt.py

0% -- ALL 18 master-test-plan documents under docs/testing/master-test-plan/,
plus docs/CONFIGURATION.md (0/13), messagefoundry/logging_setup.py (0/15),
tests/negative_controls.toml (0/12), tests/test_scan_forbidden.py (0/7)
2-3% -- messagefoundry/pipeline/_sandbox_worker.py (1/36),
scripts/worktree/install-gate.ps1 (1/36), docs/PHI.md (1/26)

ONE RESULT THAT IS NOT UNLANDED WORK AND WOULD READ AS IT. docs/adr/0161-async-session-mail-for-unreachable-peers.md scores 0/23, but ADR 0161 IS on main. This branch carries a DIFFERENT VERSION of an ADR that already landed, which is a conflict to resolve rather than content to add. A file-level score cannot tell those apart, and it is the reason the numbers above are a map rather than a verdict.

TWO THINGS THIS MEASUREMENT DELIBERATELY DOES NOT SAY. It does not say the content is CORRECT -- this PR's own title records P0s withdrawn as false, so some of it is known-wrong by its author, and 75 commits of self-flagged mixed quality needs review rather than a landing decision. And it does not say the work is at risk: the branch is on origin and this PR is open, so it is stalled, not endangered.

WHO CAN LAND IT. ADR 0166 is allocated to the worktree hopeful-chaplygin-3158c6, which is this branch's own. ledger_check requires owns("adr","0166") for an added ADR file and keys that on the WORKTREE PATH rather than a live session, so the allocation is intact and resolvable from that directory and from no other.

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