Group the backlog by what ships rather than by what it touches - #592
Merged
Conversation
Selecting the next item meant re-deriving the grouping every session, because entries were grouped by the surface they change and the working question is what fits one pull request. A `###` heading is now one pull request, and the cluster carries what it touches and what it costs as fields, which states more than the old heading implied. Three defects made the file unsafe to select from. Three open issues appeared nowhere in it, so a pass that read only this file could not see #538, #550 or #557. Two open issues were already fixed. And two claims contradicted the tree, where the entry called `repo-config/configure.sh` carried `verbatim` while the manifest no longer declares it and the ledger dispositions it `retire`. An entry now carries `Blocked by`, `Issue` and `Checked` exactly once each and never omits one, since an omitted field reads as unknown rather than as none. `Checked` is a per-entry anchor naming the branch, commit and date a claim was last read, replacing a file-level anchor that already carried two commits for two passes. `Open` states what a future session decides and `Settled` states what it does not re-derive. Two structural slots are new. `Fleet Sweeps` holds work that lands on a downstream visit, which had no home and left #353, #379 and #489 sitting under a heading promising a close they could not take, and its `Rides with` field turns six repetitions of naming the same visit into one manifest. `Recorded for the Maintainer` holds the issue actions that are the maintainer's to take, each with the evidence to use. A selection procedure states how the file is read, and its first step is confirming every open issue has an entry, which is the honest maximum a hand-maintained file gives and the reason the step is first. A generated ledger was considered and rejected: the divergence report earns its generator by joining against live fleet reality, and a backlog has no such reality to join against. `spec/readme-structure.md` said a `TODO.md` is a flat bullet list, which #535 already contradicted. It now states the minimum rather than the shape, and says this repo's file is a worked example rather than a template every repo adopts, since a five-line backlog needs no selection procedure. `reports/divergences.md` is regenerated. It rendered `repo-config/configure.sh` under a re-vendor disposition across six repos while its own ledger carried it as `retire`. Regenerating it also disproved a claim written into this pass, that Blog is the only repo carrying `AGENTS.md` "Fleet Bootstrap", where HomeAutomation-Config carries it too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Reorganizes the repo’s running backlog so the primary grouping unit is “what ships in one pull request” (clusters), and updates accompanying spec/report artifacts to match the new TODO.md structure and the retired repo-config/configure.sh carry model.
Changes:
- Restructured
TODO.mdinto “Work Clusters” where each###heading represents one PR, with standardized per-entry fields and a documented selection procedure. - Relaxed
spec/readme-structure.mdwording to allow either flat or headed/grouped TODO backlogs (with this repo as the worked example). - Regenerated
reports/divergences.mdto reflect theretiredisposition forrepo-config/configure.shand updated divergence listings.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| TODO.md | Reframes the backlog around shippable PR-sized clusters and adds a repeatable selection/update procedure. |
| spec/readme-structure.md | Updates the TODO.md guidance to define minimum requirements while allowing grouping when selection itself becomes work. |
| reports/divergences.md | Refreshes the generated divergence report to align with current spec/divergences.json dispositions (including retire). |
Selection step 9 applied to 9d85941, which carried "Reaching the Hub in Your Own Checkout" whole, so the cluster is deleted rather than annotated and nothing moves out of it. #557 and #579 take its place under "Verified Complete, Awaiting Close", each citing the commit and quoting the rule text that answers it, since both close on the develop to main promotion rather than on the merge that completed them. The two recorded maintainer comments those entries subsume go with them, because a recorded action telling the maintainer that an issue stays open until a cluster lands is a stale instruction once the cluster has landed. #509 and #490 leave the same section for the opposite reason: both were closed on 2026-08-03, so a section whose whole subject is what still awaits a close was carrying two entries that had already had one. Four link definitions the deletions orphaned go too, along with the pull request block left holding none, since MD053 is enabled by default and an unused definition is a lint failure rather than a spare. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 7, 2026
ptr727
added a commit
that referenced
this pull request
Aug 8, 2026
Closes #607. ## What was wrong A Copilot review body states how many of the pull request's changed files it read, and nothing parsed that line. A round that read part of the diff carries the correct `commit.oid`, raises no inline threads, and reports "generated no comments", so it is the clean pass byte for byte in everything the loop checks, and `status` printed `review_on_head=yes` over it and exited `0`. Measured over **332 Copilot review bodies** on this repository, five rounds across three pull requests reported reading fewer files than were changed, and all three merged. #592 is the sharpest: three changed files, one never read, across *both* rounds, both reporting no comments. ## What changed, and why it is wider than the issue asked Partial coverage is the third instance of a shape this script already answers twice, and the generalization is the point. Every reader here keys on a structural marker, so a marker that changes spelling is a section the reader stops finding and reports as absent. All three failures on record have that shape: | Drift | Result | | --- | --- | | Suppressed heading reworded | `suppressed=0` over a body carrying findings | | Suppressed section moved inside another wrapper | `suppressed=0` again | | Coverage line never parsed | a partial round reported as a covered head | Each was found by the maintainer after it had landed, rather than by the gate. So the digest now vets the reviewer's output as a whole and **fails closed**: - `coverage=full` / `PARTIAL` / `unstated`, with exit **42** on a partial round. - `shapes=ok` / `UNRECOGNIZED`, with exit **43** on any heading, `<summary>`, metadata label, coverage wording or reviewer login the script has no vetted spelling for. It outranks 42, because a reader that does not understand the output cannot be believed about what it read of the diff. The `43` message states the remedy in two parts: **file an issue on the repository hosting the reader**, quoting the body the shape came from, and **the merge decision is the maintainer's**. An unrecognized shape does not say the pull request is bad, only that nothing here can vouch for the review of it. ## The inventory is measured, not imagined With fenced blocks dropped and text reduced to ASCII, all 332 bodies reduce to **7 headings, 6 `<summary>` texts and 3 metadata labels**, and every body carries at least one. Counts normalize to `(N)` and the verdict headings' colored circle is dropped before comparing, since both change on every review without the section changing, and dropping the emoji is also what keeps the source inside the charset rule. Two exemptions, both required by the corpus: - **A body stating no coverage** reads as `unstated`, never as pass or failure. 28 of the 332 are an overview and a change list, that shape is current and interleaves with the counted one, and one pull request carries both across its two rounds. Failing on it would cry wolf on about one review in twelve. - **A refusal** is exempt, being a bare paragraph by design and already classified. The exemption is the pattern rather than a carve-out, so a refusal reworded stops being exempt and blocks, which is the refusal check's own failure mode caught one rewording later. The quietest reading is the reviewer **login**: a rename leaves every filter here matching nothing, so a review that landed reads as `rounds=0` and a wait polls out its timeout against it. ## Evidence Both readers were swept over the full corpus before this was written, and over it again after: - Shape inventory: **0** items raised across all 332 bodies, and **0** across every review and comment author on those 120 pull requests (`copilot-pull-request-reviewer` and `ptr727`). - Coverage: `full 299 / unstated 28 / partial 5`, the five being exactly #476 (x2), #479 and #592 (x2). - Live: #592 reports `coverage=PARTIAL shapes=ok` and exits `42`. #595, #604 and #606 report `shapes=ok` and exit `0`. 166 tests pass, up from 132. The two fixtures the issue named as unasserted filler are promoted to assertions, and a case reads the vetted coverage spellings out of the runbook and hands them to the script's own parser, so the pair fails in both directions on drift. The old fixtures crafted review bodies with no heading, which no real body has, so they were made realistic rather than the check loosened. ## Also carried - `.github/copilot-instructions.md` - the verify step checked `commit.oid` only, which is what this shows to be insufficient, plus a new section stating that an unrecognized shape blocks and earns an issue. - `GOVERNANCE.md` - merge-gate precondition 4, and the "all four preconditions" restatement swept to five. - `scripts/README.md` - both readings. - `TODO.md` - a `measure` cluster to survey whether GitHub publishes anything structured about a Copilot review, since this whole design rests on prose being the only surface. Introspection says it is: `PullRequestReview` exposes `body`, `bodyText` and `bodyHTML` and no field naming a finding or a file count, and the only Copilot-named GraphQL types configure review-on-push in a ruleset. ## The accepted cost The shape scan reads every round rather than the head's, so once Copilot changes format, every open pull request blocks at once until the inventory is updated. That is deliberate and the maintainer's call: it is well balanced against a reviewer silently missing a raised finding. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
ptr727
added a commit
that referenced
this pull request
Aug 8, 2026
… that blocks on what it cannot read (#609) Promotes 14 commits from `develop`. Merge with a **merge commit** (`gh pr merge --merge`), never a squash, and **without `--delete-branch`**, since this pull request's head is `develop` itself. Closes #607 through the closing keyword already carried in `530cf71`, which is why it is not repeated here. ## The prose backlog, cleared end to end `#600`, `#604`, `#605`, `#606` took the tree from **557 findings across 45 files to 0 across 0**, in four batches ordered by surface: snippets, comments, hub-only Markdown, then the carried files. Each batch measured the checker's own exemption against the live corpus *before* sweeping, and twice the measured answer was **"do not change the checker"**, which is a result of that pass rather than a skipped one. `#594` added the floor that makes those numbers trustworthy: a diff-scoped run now asserts what it actually scanned, since a check whose scan matches nothing reports zero findings and reads exactly like a pass. One finding from that work is worth carrying up: an exemption that is too **loose** produces silence rather than false positives. #519 recorded the governance files as clean; today's checker reports 38 findings against those same files as they stood at the commit that measured them. ## A review loop that fails closed `#599`, `#601`, `#602`, `#603` and `#608` are one arc on `scripts/pr_review.py`, each removing a shape in which the loop reported a clean pass over a review it had misread: - **`#599`** removed the shape a reply kept failing in, by taking the thread's *words* rather than an id, so there is no argument a hand-typed `PRRT_...` fits in. - **`#602`** made `claims` resolve what a description points at rather than what it looks like. - **`#603`** gave a disproved claim a home the next round reads. - **`#608`** reads the file-coverage line, and then generalizes: every reader keys on a structural marker, so a marker that changes spelling is a section the reader stops finding and reports as absent. The digest now vets headings, `<summary>` texts, metadata labels, coverage wordings and the reviewer login against an inventory measured from **332 review bodies**, and **blocks on anything outside it**, exit `43`, with the remedy stated as filing an issue on the hub. Whether to merge regardless is the maintainer's decision. `GOVERNANCE.md` merge gate went from four preconditions to **five** accordingly. ## Governance and tooling - **`#593`** states which checkout an agent works in and what the hub is, which is the host-wide routing the repositories that most need it cannot carry. - **`#596`** gates the pattern-detectable half of the representative-data rule, honest that no pattern closes the name-shaped case. - **`#598`** declares where a repository states what CI cannot verify. - **`#592`** regrouped `TODO.md` by what ships rather than by what it touches, so a `###` heading is one pull request. - **`#601`** ended a `gh push` argument list at a newline rather than only at `&&`, fixing a write-guard over-block. ## Verification Run on `develop` at `530cf71` immediately before opening this: `test_pr_review.py` (174), `test_prose_lint.py`, `test_repo_gate.py`, `spec/audit.py --selftest`, `gh-write-guard.py --selftest`, `spec/validate.py`, `repo_gate.py`, the prose gate in both CI invocations, markdownlint and editorconfig-checker. All clean. ## Not carried by this promotion - **#519 is complete and still open.** `TODO.md` holds its closing evidence under "Verified Complete, Awaiting Close". Closing it is the maintainer's call, so no keyword for it appears here. - **The re-vendor debt is now nine files.** `#606` queued seven, and `#608` changed `GOVERNANCE.md` "PR Review Etiquette" (`verbatim`) and `.github/copilot-instructions.md` (`intent`) on top. The `intent` half produces no hash and therefore no audit finding, which is why the Fleet Sweeps entry names those files by hand. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ptr727
added a commit
that referenced
this pull request
Aug 8, 2026
Follows the #609 promotion, which went partial at 61 of 62 files and stayed there through two re-requests. That prompted measuring whether the remedy the gate recommends has ever worked. It has not. ## The measurement Over the **332 Copilot review bodies** on the newest 120 pull requests, read beside `gh pr list --json number,changedFiles,additions,deletions`: | Question | Answer | | --- | --- | | Pull requests that went partial | **4** - #476, #479, #592, and the #609 promotion | | Rounds those four produced | **7** | | Rounds that recovered | **0** - every later round repeated the identical ratio | | Files skipped, each time | exactly **1** | ``` PR 592: round 1 = 2/3 round 2 = 2/3 PR 476: round 1 = 10/11 round 2 = 10/11 PR 479: round 1 = 16/17 PR 609: round 1 = 61/62 round 2 = 61/62 (after a re-request on a new head) ``` So the digest was telling a reader to spend a round on a retry that nothing has ever retried out of. ## Two hypotheses tested and rejected, so they are not re-derived **Size does not predict it.** The partials changed 502, 629 and 961 lines. Fully covered pull requests on this repository reach **33 files and 2,219 changed lines**, well past all three. **The denominator is not itself lossy.** I suspected the reviewer might drop a file before counting, which would make `N out of N` a lie. It does not: the stated denominator equals the API's own `changedFiles` on **103 of 104** pull requests, and the single exception is one whose branch shrank between rounds. The reviewer counts the file and does not read it. ## What changed The three places that stated the remedy now state what the record supports, swept by grepping the phrasing rather than by fixing the one the finding pointed at: - `scripts/pr_review.py` - the `status=COVERAGE_IS_PARTIAL` line, the digest's `COVERAGE IS PARTIAL` block, and the `status` exit-code docstring. - `.github/copilot-instructions.md` - the "Counts unequal" bucket. - `scripts/README.md` - the coverage paragraph, carrying the measurements. The new wording says a re-request has never cleared one, that splitting is real for a feature branch and unavailable for a promotion whose head is `develop`, and that the merge decision is the maintainer's, taken knowing one file has no review. **No exit code or verdict changes**, since the gate was reporting the state correctly. Only the advice attached to it was wrong. ## What is left open `TODO.md` gains an entry under the programmatic-reading cluster, with the measurements attached: **which** file is skipped, and why. The reviewer names no file list in these rounds, so it cannot be recovered from the API, and the pull request page may be the only place it appears. Whether it is worth escalating to GitHub needs the file first. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 8, 2026
ptr727
added a commit
that referenced
this pull request
Aug 8, 2026
) Closes #623. **Disposition** `Amends "Find out which file a partial round skips, and why re-requesting never clears it."` in the "A Programmatic Reading of a Copilot Review" cluster. #623 was filed after this repository's last `TODO.md` edit and appeared nowhere in the file, so selection step 1 was false until this change. ## What was wrong The `COVERAGE_IS_PARTIAL` caveat, `scripts/README.md` and the runbook all said the reviewer names no file list in these rounds, so which file went unread cannot be read from the API. Measured over 348 Copilot review bodies on the newest 120 pull requests here and 121 on Blog, that is false. 91 bodies carry a `| File | Description |` table, and every table row in the corpus belongs to one of those tables. ## What the measurement says the table is worth The issue proposed reading a table that names every changed file as evidence that the count is a reporting artifact. It cannot carry that, and the corpus is what says so. | round | states | names | reading | | --- | --- | --- | --- | | #476 | 10 of 11 | all 11 | table contradicts the count | | #592 | 2 of 3 | all 3 | table contradicts the count | | #479 | 16 of 17 | 16, omitting `GOVERNANCE.md` | table corroborates the count and names the file | | #609 | 61 of 62 | 50 of 62 | short by 12 where the count is short by 1 | | #574 | 33 of 33, full | 32, omitting `TODO.md` | a short table on a fully covered round | | #606 | 7 of 7 | names `GOVENANCE.md` | a path no diff carries | On Blog every table names exactly the changed set, on all seven partial rounds and on every full round alike. A reading identical under both outcomes discriminates neither, so a full table is reported as corroborating nothing rather than as a miscount. #574 kills the converse, since a short table sits on a round that read everything. ## What ships - `Q_FULL` selects the pull request's own `files`, windowed at 100 with `hasNextPage` carried, since a path outside a short window reads exactly like a path the reviewer left out and the record holds a pull request of 301 changed files. - `file_table` reads the table, quotations dropped for the reason the coverage line's are. - `head_table` takes it from any round covering the current head and never from a round before a push. Three of the four partials here carry their table on the pre-push round, describing a diff that push replaced, and comparing that against the current changed files would name a file unreviewed on a stale list. Thirteen commits here carry more than one round, and on one of them a round with a table sits beside a round without, so which of the two the verdict reads must not decide whether a table is found. - `table_against_diff` prints one sentence and decides nothing. It names an omitted file only where the table is short by exactly what the counts leave unread **and** names nothing outside the diff, that second guard existing because #606's typo would otherwise push the real `GOVERNANCE.md` into the omissions and report it as the file nobody reviewed. - Exit `42` is unchanged in every arm, and the caveat keeps its maintainer-decision framing, which is the issue's third suggestion. ## Verified against live data #479 the reviewer's own file table omits exactly the 1 file the counts leave unread, naming GOVERNANCE.md Blog #60 the reviewer's own file table names all 6 changed files, ... so it corroborates nothing #476/#592/#609 no round covering this head carries a file table ## Gates 228 `test_pr_review` cases, plus `test_prose_lint`, `test_repo_gate`, `spec/audit.py --selftest`, `spec/validate.py`, both `prose_lint.py` invocations, `markdownlint-cli2` and `editorconfig-checker`, all green locally. Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Selecting the next work item meant re-deriving the grouping every session. Entries were grouped by the surface they change, which is #535's convention and answers what a change costs, while the working question is what fits one pull request. That analysis is what the file should carry forward and did not.
Three defects made it unsafe to select from, each verified against
developat3d1a0b1:repo-config/configure.shcarriedverbatimwithappliesTo: "*", whilespec/files.jsonno longer declares it andspec/divergences.jsondispositions itretire.reports/divergences.mdstill rendered it underre-vendoracross six repos, so the committed report disagreed with its own ledger.What changed
A
###heading underWork Clustersis one pull request. 20 clusters, 28 entries, after the follow-up commit retired one. The #535 rationale is not discarded, it moves from an organizing axis to a per-clusterTouchesandCostfield, which states more than the old heading implied: a cluster confined to one surface says so in a clause and a cluster spanning two states both.An entry carries
Blocked by,IssueandCheckedexactly once each, in that order, and never omits one, because an omitted field reads as unknown rather than as none.Checkedis a per-entry freshness anchor naming the branch, commit and date a claim was last read against the tree, replacing a file-level anchor that already carried two commits for two passes and could not carry a third.Openstates a decision a future session makes,Settledstates a finding it does not re-derive, and aSettledbullet carries a number, a proper name, or a rejected alternative.Two structural slots are new:
Fleet Sweepsholds work landing on a downstream visit. It had no home, which left Template .editorconfig contradicts CODESTYLE by relaxing all analyzers repo-wide #353, Fidelity-adoption findings from Financial-Modeling: doc conflicts + source-only workflow prose-vs-impl #379 and Carry findings from Blog: spec conflicts, prose_lint false positives, and two silent carry hazards #489 under a heading promising a close they explicitly could not take. Each item carriesHub state,OutstandingandRides with, so six repetitions of naming the same visit become one manifest. It records the batching preference outright, that the fleet is caught up periodically rather than after every hub change, and names Blog as the pilot.Recorded for the Maintainerholds issue actions that are the maintainer's to take, each carrying the evidence so it is one action rather than a re-derivation.How to Select the Next Itemstates the procedure. Step 1 is confirming every open issue has an entry, which is the honest maximum a hand-maintained file gives and the reason it comes first.Two overlaps folded in
registry/repos.jsonmakes every mirror read a field rather than parse a paragraph, so taking The README intro spec and the HISTORY mirror rule leave no room for a second paragraph, and the audit would report one #577 first means writing an extraction rule the registry change then deletes. They are now one cluster with the sequencing stated.A generated ledger was considered and rejected
spec/divergences.jsonearns its generator by joining a curated ledger against live fleet reality and renderingUNTRIAGEDfor anything live the ledger missed. A backlog has no such reality to join against, and the only mechanizable join is issue open or closed state, which is step 1 of the procedure. What is given up is stated in the file rather than glossed: no enum enforcement, and no automatic surfacing of an open issue with no entry, which is exactly the #538, #550 and #557 failure. The bold-label template stays parseable, so a later checker asserting everyCheckedcommit resolves is buildable without re-shaping the file.Sweep obligations
spec/readme-structure.mdsaid aTODO.md"opens with a# TODOheading and one line saying what it holds, then a flat bullet list". #535 already contradicted both clauses. It now states the minimum rather than the shape, and says this repo's file is a worked example rather than a template every repo adopts, since a five-line downstream backlog needs no selection procedure. That file is not inspec/files.json, so the edit costs no re-vendor.spec/section-model.md,STANDUP.mdandREADME.mddescribe the file's purpose without asserting its shape, verified clean and recorded here so the sweep is done rather than skipped.host-setup/agent-safety/README.mdends the write-guard note with "Tracked inTODO.md", still true.Ledger regenerated
reports/divergences.mdnow rendersrepo-config/configure.shunderretirerather thanre-vendor, resolving the contradiction. Regenerating it also disproved a claim written during this pass: Blog is one of two repos carryingAGENTS.md"Fleet Bootstrap", not the only one. HomeAutomation-Config carries it too, and beingoperationalit exercises the direct-to-developpath rather than the pull request one, which the pilot note now records as the second visit worth making rather than the first.A second correction, to #521's own claim: three merge-bot jobs carry both
contents: writeandpull-requests: writeand the fourth carriespull-requests: writealone, so the issue's "all four" is one job wide. The entry records this rather than repeating the issue.Issues closed
template_ref_outside_verbatiminspec/audit.py, excising verbatim regions by position before the coordination-reference scan, with eight self-test cases. Positional excision rather than content removal is required by the fenced-copy case, since removing extracted text would delete a fenced copy along with the real region and the scan would fail open.parametersobject of every parameterized rule is compared with keys and set-like arrays sorted on both sides, the rule-type set is compared in both directions, and the header states what check verifies and names what stays unaudited.Follow-up: the file's own procedure applied to itself
6bed2d9is the first exercise of step 9, and it is also what gave this pull request the CI run it never had, since the whole thing opened during the Actions outage and a rollup does not re-fire on its own.9d85941merged "Reaching the Hub in Your Own Checkout" whole, so the cluster is deleted rather than annotated and nothing moves out of it. Each of its four entries was re-read againstdevelopbefore the deletion rather than trusted to the merge: the checkout-isolation rule and the stale-clone read rule inGOVERNANCE.md, the hub definition inAGENTS.md"Fleet Bootstrap", the six terms inREADME.md, and the hub-script pointers in.github/copilot-instructions.md.#557 and #579 take its place under "Verified Complete, Awaiting Close" citing that commit, since both close on the
developtomainpromotion rather than on the merge that completed them. The two "Recorded for the Maintainer" comments they subsume go with them, because a recorded action saying an issue stays open until a cluster lands is a stale instruction once the cluster has landed. That section now holds two items rather than four.Two entries left the same section for the opposite reason. #509 and #490 were closed on 2026-08-03, three days before the clustering commit, so a section whose entire subject is what still awaits a close was carrying two entries that had already had one. Their link definitions stay, since other clusters still cite both issues.
Four definitions the deletions orphaned go too,
issue-552,pr-572,pr-588andworkflow, along with the pull request block left holding none. MD053 is enabled by default, so an unused definition is a lint failure rather than a spare, and the reference-and-definition audit in the verification list above was re-run rather than assumed to still hold.Verification
python3 scripts/prose_lint.py . --diff origin/developclean, andTODO.mdholds 0 violations under the default rules as it did before.python3 spec/validate.pyreports 22 cataloged, 0 backlog.TODO.mdafter6bed2d9.Statelines without opening any research.Note the file grew, 61 KB to 73 KB, rather than compressing. Three issues that had no entry were added along with the procedure and the per-entry anchors. The metric that moved is the one selection depends on, which is the 5 KB a re-select actually reads.
🤖 Generated with Claude Code