Skip to content

Clear the carried half of the prose backlog, and plan its re-vendor - #606

Merged
ptr727 merged 1 commit into
developfrom
prose/carried-semicolons
Aug 8, 2026
Merged

Clear the carried half of the prose backlog, and plan its re-vendor#606
ptr727 merged 1 commit into
developfrom
prose/carried-semicolons

Conversation

@ptr727

@ptr727 ptr727 commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Takes the last batch of the The Prose Content Backlog cluster from TODO.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

develop at d791930, where python3 scripts/prose_lint.py --summary reports 41 violations across 6 files, all semicolon. That is the figure #605 predicted, and merging it made the figure develop's own rather than a branch's.

File Findings Fidelity
GOVERNANCE.md 14 intent, 5 sections verbatim
WORKFLOW.md 14 intent, whole
CODESTYLE.md 6 intent, whole
.github/copilot-instructions.md 4 intent, whole
repo-config/README.md 2 intent, whole
HISTORY.md 1 presence

The 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.md and of nothing else, which changes what the sweep owes:

  • verbatim, hash-detected. All 14 GOVERNANCE.md findings sit in five verbatim sections: Branching Model, Release Model, Documentation Style Conventions, PR Review Etiquette, Workflow YAML Conventions. Every downstream copy is now byte-mismatched and spec/audit.py classifies 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.md and repo-config/README.md are 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.md is 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 verbatim content" grows from five files to seven and carries both halves as Detail lines. 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:

Content Checker Result
the six files at 69688ec that commit's own prose_lint.py 0
the six files at 69688ec today's prose_lint.py 38

semicolon was in DEFAULT_RULES the 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:

prose_lint.py --summary            41/6 -> 0/0
scripts/ unittest (375 tests)      OK
spec/audit.py --selftest           SELFTEST PASS
spec/validate.py                   22 cataloged, 0 backlog
scripts/repo_gate.py               eol 0, sha-pin 0
markdownlint-cli2 (44 files)       0 issues
cspell (README.md, HISTORY.md)     0 issues
editorconfig-checker               0 on tracked files

Every edit is a within-line replacement, so all seven CRLF files stayed CRLF — verified by an \n versus \r\n count per file, not by file. The full word-diff was read for meaning drift; the change is 31 lines, 31 insertions and 31 deletions.

editorconfig-checker reports 221 errors, every one of them under .artifacts/ or Tests/obj/ — untracked pre-repurpose build leftovers in the working tree, not tracked files. Pre-existing and untouched here.

TODO.md

  • The The Prose Content Backlog cluster is deleted, per selection rule 9.
  • #519 moves to "Verified Complete, Awaiting Close" with both of its questions answered and the checker-versus-tree finding as closing evidence.
  • The Fleet Sweeps re-vendor entry grows to seven files and gains the two Detail lines above.
  • Four link reference definitions orphaned by the cluster deletion are dropped.

🤖 Generated with Claude Code

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>
Copilot AI lite review requested due to automatic review settings August 7, 2026 21:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.md to 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.

Comment thread WORKFLOW.md
@ptr727
ptr727 merged commit 20916ad into develop Aug 8, 2026
7 checks passed
@ptr727
ptr727 deleted the prose/carried-semicolons branch August 8, 2026 00:12
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>
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.

2 participants