Skip to content

backlog: file #1004-#1011 and recompute the census from open-bannered headings - #182

Merged
wshallwshall merged 2 commits into
mainfrom
claude/backlog-file-1004-1011
Aug 4, 2026
Merged

backlog: file #1004-#1011 and recompute the census from open-bannered headings#182
wshallwshall merged 2 commits into
mainfrom
claude/backlog-file-1004-1011

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Authored by the ASVS-cleanup session; opened by the coordinator on the owner's push/merge authority. I verified it independently before pushing rather than taking the reported numbers.

Independent verification

Re-measured with the canonical parser (parse_items imported from scripts/docs/backlog_status_check.py), not a hand-rolled scan:

items 101
OPEN 100
closed in file [335]
items with no banner none
live table rows 101
open heading with no row NONE
row whose item is not open [335]
ranks contiguous 1..101
Value / Difficulty / Tiers / Quadrants each sums to 100

Shipped gate: OK - 287 backlog items, each declaring exactly one status.

This was a pre-registered prediction, not a post-hoc check. Before the filing began I sent that session the expected post-filing numbers and said a census line reading 101 should be treated as a failure signal meaning rows had been counted rather than open-bannered headings. It measured, reported, and matched on every field. Two independently-derived models agreeing is worth more than one derived twice.

It also corrected a pre-existing error

The published census read 93 against 92 open before this branch. It now reads 100 against 100. So this does not merely add items, it fixes a drift that was already live on main.

Known, deliberate, and NOT defects

  • fix(test): pin the RecursionError contract without a real stack overflow (#1222) -- unreds main #335 is still row-not-open - the single remaining bijection break. That is the coordinator's archive pass, tracked separately, and is deliberately out of scope here.
  • feat(#114): the outbound validate_startup hook, with its ledger banner (train) #327 is counted OPEN with its banner recorded stale-with-evidence, not flipped. Its work merged while its banner still reads not-started. The reasoning is worth keeping: a census must be reproducible from the record, not true about the world, and those two come apart exactly here. Flipping it is a closure judgment for whoever owns its remaining scope.
  • At least three items now have banners that understate what shipped. Stated as "at least" deliberately - the sweep is what establishes the real count, and an enumeration here would be the completeness claim CLAUDE.md section 11 warns against.

One defect I am NOT fixing in this PR, and why

The fourth census line still reads 93 where the other three read 100: "Every one of the 93 open items is re-scored here".

This is the second occurrence of the same defect on the same line - corrected once already in #178 after the same finding. The cause is that the fix went to the output and not the generator: the recompute script rewrites the three lines it emits and has never touched the prose sentence, so every future filing re-introduces it.

I could not fix it here. The ledger gate correctly blocked me: #1004-#1011 are allocated to the authoring session's worktree, and the gate diffs against main, so any commit I make on this branch reads as introducing eight numbers I do not hold. That guard exists because two sessions adding the same number land far apart in one 6.7k-line file and merge clean. Working around it with --no-verify was not an option. It follows in the coordinator's archive pass, where the line will be re-derived along with everything else.

Gates run locally because this PR will not run them

The pytest legs are gated on code == 'true' || push, and .md is in the noncode allowlist - so on a docs-only PR they are skipped pre-merge and fire only on the push to main afterwards. For a 1,219-line prose addition that matters, so I ran them here:

  • tests/test_cutover_slug_rot.py - the two-way prose ratchet (_PROSE_CEILING = 54, with a companion test that fails if the ceiling has unused slack). Green.
  • tests/test_backlog_status_check.py. Green. 21 passed.

Worth flagging on its own: a docs-only PR merging green and then turning main red is a live gap, not specific to this change.

… headings

Eight items from an ASVS build-or-accept analysis, filed in one operation with the four
distribution lines re-derived. Numbers allocated atomically via scripts/coord/alloc.ps1;
none was carried from a handoff message.

  #1004 V8 D4 P1           ASVS 13.3.4 DEK calendar expiry - OWNER-DECIDED BUILD, opt-out
  #1005 V8 D5 P1           CRL checking on the three mTLS-terminating listeners
  #1010 V7 D3 P2           No licence-header gate in any language; 196 sources untagged
  #1011 V6 D2 P1           Rule on the shipped tools/ech-sidecar/ Go tree: keep or retire
  #1006 V6 D3 P2           The absence-claim gate proves syntax, not behaviour
  #1007 V6 D3 P2           Sweep 345 ASVS cells for present-tense impact language
  #1008 V6 D4 DEMAND-GATE  Startup preflight on the store principal's privileges
  #1009 V5 D2 P2           SOAP body_secret_value_<i> is never rotation-fingerprinted

CENSUS: 92 -> 100 open. The published census was ALREADY WRONG BY ONE before this commit -
it read 93 against 92 open items, off in four buckets, because an item was closed while
retaining its ranked row and that commit deliberately did not recompute. Both are corrected
here, from source.

THE UNIT IS OPEN-BANNERED HEADINGS, NEVER ROWS. Rows and open items are not
interchangeable: one item holds a row it is not entitled to, so the row count is 101 while
the open count is 100. A census derived from rows would have read 101 and passed every
total-only assertion. Verified two-directionally - zero open headings without a row, and
exactly one row whose item is not open (that one is the archive pass's, not mine).

Status was read with parse_items imported from scripts/docs/backlog_status_check.py, not a
hand-rolled scan. I had written one; CLAUDE.md §11 forbids exactly that ("a hand-rolled scan
is a second, silently different definition"), and mine agreed with the canonical parser only
by luck on this corpus. Replaced before filing.

GLYPHS STRIPPED FROM ALL PROSE. The drafted bodies carried 18 occurrences of the CLOSED
banner alphabet (16 ⛔, 2 ✅) outside their banner blocks. parse_items classified all eight
correctly - the glyphs sat outside the leading blockquote - but that is placement luck, and
§11's own argument is that a bare glyph's meaning is positional and invisible to review. One
blockquote-shaped edit would have flipped an item to closed. Only the machine-parsed banner
glyph remains, one per item.

#327 IS COUNTED AS OPEN AND ITS BANNER IS STALE. Its work is merged on main
(tests/test_private_paths_stay_ignored.py is present) while its banner reads not-started. It
counts as OPEN because the file names the banner as the live record and a census must be
reproducible FROM THE RECORD, not true about the world - those come apart exactly here, and
reproducible has to win or every recompute becomes an argument. Not flipped: that is an
item-status decision on someone else's merged work. Recorded here so whoever owns it acts
deliberately rather than discovering it.

Item bodies run 8.0k-15.6k chars against a file median of 3.4k - all eight in the top decile,
deliberately. The length is verified traps (the CRL loader that silently loads zero CRLs, the
swallowed-exception siting, the paired-record coupling), each of which would ship the work
broken if dropped. Still inside the existing range; the longest item in the file is longer.

Scores: three drafters, then a scorer blind to their numbers. Six of seven matched on value,
difficulty and quadrant. The one dispute went to the blind scorer - #1008 is DEMAND-GATE, not
P2, because the rubric's override is literal and a prerequisite clearing is not a decision.
Roughly a dozen citations were corrected or dropped first, including two ADR filenames that
do not exist. #1010's headline was re-measured rather than inherited and grew from "64 files
across two languages" to 196 across six - the original was a Python-only reading.

Verified after writing: the shipped gate reports OK, 287 items across both ledger files, each
declaring exactly one status; ranks contiguous 1..101; all four census lines sum to 100.
NOT MINE, LEFT FOR THE RECONCILE PASS: archiving the closed-but-rowed item, and #1002.
@wshallwshall
wshallwshall enabled auto-merge (squash) August 4, 2026 17:47
@wshallwshall
wshallwshall merged commit fbe3c9a into main Aug 4, 2026
31 checks passed
@wshallwshall
wshallwshall deleted the claude/backlog-file-1004-1011 branch August 4, 2026 17:49
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