Clear the carried half of the prose backlog, and plan its re-vendor - #606
Merged
Conversation
The last batch of the "The Prose Content Backlog" cluster: the 41 semicolons across the six carried files, taking the whole tree to zero. The anchor was re-verified first. `develop` at `d791930` reports 41 across 6, which is the figure #605 predicted and is now develop's own. The exemption pass came first and left the checker alone, for the third batch running. Both candidates were rejected by the corpus: the `*Prevents: a; b.*` tail is already comma-spelled on 5 lines against 6 semicolon-spelled, and a two-example parenthetical is already comma-spelled where its items carry no commas. The two `*Prevents:*` lines whose items do carry commas keep their semicolons, which is the rule working rather than an exception to it. Only the 14 GOVERNANCE.md findings are byte-locked. They sit in five `verbatim` sections, so every downstream copy goes stale and the audit reports it. WORKFLOW.md, CODESTYLE.md, .github/copilot-instructions.md and repo-config/README.md are `intent`, where a punctuation edit produces no hash and no finding at all, and HISTORY.md is `presence`. Both halves are recorded on the Fleet Sweeps re-vendor entry, which grows from five files to seven. No rule changed meaning, so the re-vendor is a hash refresh rather than a propagation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR finishes clearing the remaining prose-lint semicolon backlog in the carried documentation surface (governance/workflow/style docs), and updates TODO.md to record the downstream re-vendor sweep implications and closure evidence for #519.
Changes:
- Replace semicolon-joined prose with comma/“and”/sentence-split variants across carried Markdown docs.
- Update
TODO.mdto remove the completed “Prose Content Backlog” cluster and expand the downstream re-vendor sweep notes/evidence. - Minor punctuation/wording fixes in supporting carried documentation (
repo-config/README.md,HISTORY.md, Copilot runbook).
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| WORKFLOW.md | Prose punctuation adjustments in the behavioral contract and audit guidance sections. |
| GOVENANCE.md | Prose punctuation adjustments in carried governance sections (ruleset/configuration, release/workflow guidance). |
| CODESTYLE.md | Prose punctuation adjustments in style guidance (spelling scope, logging guidance, Python section). |
| .github/copilot-instructions.md | Prose punctuation adjustments in the Copilot review runbook mechanics and gotchas. |
| repo-config/README.md | Prose punctuation adjustments in the secrets/mechanisms description. |
| HISTORY.md | Prose punctuation adjustment in the v2.0 changelog entry. |
| TODO.md | Removes completed prose-backlog cluster and records updated sweep/re-vendor planning and closure evidence for #519. |
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
) 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.
Takes the last batch of the
The Prose Content Backlogcluster fromTODO.md, following #600 (snippets), #604 (comments) and #605 (hub-only Markdown). Closes #519 on the prose, subject to the sweep below.The anchor was re-verified first
developatd791930, wherepython3 scripts/prose_lint.py --summaryreports 41 violations across 6 files, allsemicolon. That is the figure #605 predicted, and merging it made the figure develop's own rather than a branch's.GOVERNANCE.mdintent, 5 sectionsverbatimWORKFLOW.mdintent, wholeCODESTYLE.mdintent, whole.github/copilot-instructions.mdintent, wholerepo-config/README.mdintent, wholeHISTORY.mdpresenceThe tree is now at 0 across 0, from 557 across 45 when the backlog opened.
The exemption came first, and left the checker alone again
Two candidates, both rejected by the corpus. That is the third batch running where the pass ends in "do not touch the checker".
The
*Prevents: a; b.*tail. Flagged on 4 lines because the list exemption requires the items to carry commas. The tree already spells the same construct with a comma on 5 lines against 6 semicolon-spelled, so it is a convention half-adopted rather than a construct the rule fails to describe. Two of the six (D1.6,D5.6) keep their semicolons untouched, because their items do carry commas — the rule working, not an exception to it.A two-example parenthetical,
(A does X; B does Y). The tree already spells this with a comma where the items carry none,GOVERNANCE.md"No-op republish guarantee" being the case in point.Only 14 of the 41 are actually byte-locked
The cluster entry said the carried half "rewrites byte-locked sections". That is true of
GOVERNANCE.mdand of nothing else, which changes what the sweep owes:verbatim, hash-detected. All 14GOVERNANCE.mdfindings sit in fiveverbatimsections: Branching Model, Release Model, Documentation Style Conventions, PR Review Etiquette, Workflow YAML Conventions. Every downstream copy is now byte-mismatched andspec/audit.pyclassifies it stale (matches a past hub revision), which is the correct disposition and reaches the fleet without anyone filing anything.intent, detected by nothing.WORKFLOW.md,CODESTYLE.md,.github/copilot-instructions.mdandrepo-config/README.mdare judged by meaning, so a punctuation-only edit produces no hash and therefore no audit finding at all. These are the half that would be silently missed, which is why they are written down rather than left to the run.presence.HISTORY.mdis each repo's own changelog. Its one fix owes nothing downstream.No rule changed meaning anywhere, so the re-vendor is a hash refresh rather than a propagation. A repo still holding the old copy is correct on the rule and wrong on the bytes.
The Fleet Sweeps entry "Re-vendor the changed
verbatimcontent" grows from five files to seven and carries both halves asDetaillines. It does not trigger a dedicated sweep — Blog remains the pilot.What #519 got wrong, and why it is worth recording
The issue states that the governance files were clean and that this was "not a carry problem". That was true of the checker of the day and false of the tree:
69688ecprose_lint.py69688ecprose_lint.pysemicolonwas inDEFAULT_RULESthe whole time. What changed is the unit the list exemption is judged over: scoping it to a sentence rather than a whole bullet accounts for 37 of the 38, because a colon anywhere ahead of the first semicolon had been exempting every semicolon after it, however plainly one joined two clauses.So the carry problem was real from the start and invisible — the stale-exemption hazard running in the loose direction, on the most-carried files in the fleet.
One fix beyond the 41
GOVERNANCE.md"Orchestration vs. build" carried a splice the exemption excused only because the bold label on that sentence happened to contain a comma (...globs it; do not switch a single-target repo...). Same line as a flagged finding, so it is fixed inline rather than stepped around. That is 42 semicolons removed, not 41.Verification
Run from the repository root:
Every edit is a within-line replacement, so all seven CRLF files stayed CRLF — verified by an
\nversus\r\ncount per file, not byfile. The full word-diff was read for meaning drift; the change is 31 lines, 31 insertions and 31 deletions.editorconfig-checkerreports 221 errors, every one of them under.artifacts/orTests/obj/— untracked pre-repurpose build leftovers in the working tree, not tracked files. Pre-existing and untouched here.TODO.mdThe Prose Content Backlogcluster is deleted, per selection rule 9.Detaillines above.🤖 Generated with Claude Code