Clear the Markdown half of the prose backlog, hub-only files first - #605
Conversation
Takes the next batch of the `The Prose Content Backlog` cluster from `TODO.md`. Its `Checked` anchor was re-verified against `develop` at `c9c92dd` before anything was written: `prose_lint.py --summary` reports 131 violations across 15 files, which is the figure the comment batch left and which merging that batch made the anchor's own. The batch is the hub-only Markdown files, being `docs/`, `spec/*.md` and `catalog/README.md`. That is 90 findings across 9 files, 79 `dash` and 11 `semicolon`. The 6 carried files are left for a later batch, since they rewrite byte-locked sections and owe a fleet re-vendor while these owe nothing. Every `dash` finding in the tree turned out to be hub-only, so what the carried half now holds is 41 semicolons and no dash at all. ## The exemption came first, and this time it was right `LABEL_DASH` exempts `- **Label** - text` as a definition separator that is structurally a colon. It reaches neither a code-span label nor a paragraph-leading one, and both shapes flagged in this batch. Widening it was the obvious move and the corpus rejected it twice. A code-span definition list is already spelled with a colon in five files, against four dash-spelled lines in one: ```text STANDUP.md:91 - `ARCHITECTURE.md`: how a code repo is built spec/section-model.md:68 - `ARCHITECTURE.md`: how a code repo is built scripts/README.md:81 - `sha-pin`: every workflow `uses:` naming repo-config/README.md:6 - `operational/develop.json`: the `develop` CODESTYLE.md:79 - `.NET Build`: Build with diagnostic ``` A paragraph-leading label is already spelled `**Label.** Sentence`, against nine dash-spelled lines confined to two troubleshooting sections. So both were a file that had not adopted the tree's own convention rather than a construct the rule fails to describe, and the checker is unchanged by this batch. That is the same verdict the comment batch reached on a comment opening on a lowercase identifier. A bulleted list terminating its items with semicolons appeared in exactly one place tree-wide, `spec/type-model.md:24-25`, and its own last item already ended in a period. It was punctuation to make consistent rather than the list construction the semicolon exemption protects, which a line-based checker could not see across bullets in any case. ## A scripted rewrite converts line endings, and only one gate says so Rewriting `docs/devcontainer.md` and `docs/ssh-signing.md` with a script rather than an editor took both from CRLF to LF wholesale. Every prose and Markdown gate stayed green and `editorconfig-checker` was the only one that reported it. `OPERATIONS.md` scoped that instruction to a new file, so it is widened here to a scripted rewrite of an existing one. ## Verification Run from the repository root: ```text prose_lint.py gating list exit 0 prose_lint.py backlog list 131/15 -> 41/6, the carried six test_prose_lint.py 198 tests OK test_repo_gate.py, test_pr_review.py OK audit.py --selftest, gh-write-guard SELFTEST PASS repo_gate.py, validate.py, jq clean markdownlint-cli2 (44 files) 0 issues editorconfig-checker 0 errors ``` Every prose file changed line for line, with no line-count change, and the full word-diff was read for meaning drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR continues clearing the hub's prose_lint backlog by rewriting hub-only Markdown docs/spec content (primarily dash and semicolon findings), updating the prose backlog tracking notes in TODO.md, and tightening operational guidance around line-ending checks after scripted rewrites.
Changes:
- Rewrite hub-only Markdown prose across
docs/,spec/*.md, andcatalog/README.mdto resolvedash/semicolonfindings without changing the checker. - Update
TODO.mdwith the new verified anchor and additional settled notes, plus new reference-link definitions. - Expand
OPERATIONS.mdguidance to runeditorconfig-checkernot only for new files but also for scripted whole-file rewrites that can flip EOLs.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| TODO.md | Updates prose-backlog anchor numbers/notes and adds reference links for newly cited docs. |
| spec/type-model.md | Prose rewrites to avoid dash/semicolon patterns while preserving the type-model contract text. |
| spec/scope-model.md | Prose/structure adjustments (dash -> colon/sentence split) for scoped-rule explanation. |
| spec/readme-structure.md | Minor prose rewrite to remove dash-based clause join. |
| spec/fidelity-model.md | Prose rewrite to avoid dash/semicolon patterns in fidelity definitions and normalization/staleness explanation. |
| OPERATIONS.md | Expands operational guidance for running editorconfig-checker after scripted rewrites that may change EOLs. |
| docs/token-cost.md | Prose rewrites to remove semicolon/dash patterns while keeping measured-cost narrative intact. |
| docs/ssh-signing.md | Prose rewrites to remove dash joins and standardize troubleshooting label formatting. |
| docs/repo-config-carry.md | Prose rewrites to avoid dash joins while keeping carry/apply/regen procedure wording intact. |
| docs/devcontainer.md | Prose rewrites to avoid dash joins and adjust nested list phrasing in the lifecycle section. |
| catalog/README.md | Rewrites intro/list punctuation (dash -> colon/sentence split) to align with prose_lint expectations. |
All four are accepted. Each is in text this branch wrote or in the sentence it rewrote, so none is a pre-existing line left alone. - `OPERATIONS.md:29`: the reduced relative "an existing file a script rewrote" is grammatical but stacks badly against the "rather than an editor" that follows it, so the pronoun goes back in. - `docs/devcontainer.md:3`: "as reference" wants its article. The phrase predates this branch, but the sentence around it is one this branch rewrote, so it is fixed in place rather than stepped around. - `docs/ssh-signing.md:3`: "signing, where one Ed25519 key serves both" reads locative. The relation is causal, and "since" says so. - `spec/type-model.md:37`: "hold X N/A" is this repository's own idiom and it stands unchanged at `spec/type-model.md:69`. It reads there because nothing intervenes. Here a parenthetical sits between the verb and the complement, so "as" is what keeps it parsable. Gates re-run from the repository root: the gating prose list exits 0, the backlog list still reports 41 across the carried 6, markdownlint reports 0 issues across 44 files, and editorconfig-checker reports 0 errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Suppressed comments (1)
spec/type-model.md:49
- Missing comma after the introductory phrase makes the sentence harder to parse: "For a codegen or config repo the C++ is ...". Adding a comma after "repo" clarifies the clause boundary.
- **cpp** - C/C++ present for style only. The check of record is **clang-format** (a shared config driving the editor, the CLI, and CI, a `parity.lang` arm), feeding the operational lint CI. Deeper semantic and static analysis is intentionally out of scope here. For a codegen or config repo the C++ is scaffolded and completed by its downstream toolchain (an ESPHome compile), which does the compilation-time checking, and clang-tidy would need a compile database the repo does not have. A repo's `.h` is read as C++ by context (Arduino/ESPHome), since the extension alone is ambiguous.
The second review round generated no thread and suppressed one finding, that `spec/type-model.md:49` opens a sentence on "For a codegen or config repo" with no comma closing the phrase. It is correct and it is this branch's own doing, since splitting that line's dash into two sentences is what promoted the phrase to the front of one. A suppressed finding carries no thread to answer in, so it is verified rather than accepted on silence, and the same defect is swept for rather than fixed only where it was reported. Every sentence this branch opened on a fronted phrase was checked and the rest already carry their comma. `spec/type-model.md:43` keeps "In particular the coverage checks" bare, which predates this branch and is a short adverbial where the comma is optional. Gates re-run from the repository root: the gating prose list exits 0, the backlog list still reports 41 across the carried 6, markdownlint reports 0 issues across 44 files, and editorconfig-checker reports 0 errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Round 2 generated no thread and suppressed one finding, answered here since a suppressed finding has none to reply in.
Accepted and fixed in f66607d. It is this branch's own doing: splitting that line's dash into two sentences is what promoted Swept rather than spot-fixed, since one instance of a defect this branch introduced implies a class. Every sentence the branch opens on a fronted phrase was checked and the rest already carry their comma. Gates re-run from the repository root: gating prose list exits 0, backlog list still reports 41 across the carried 6, markdownlint 0 issues across 44 files, editorconfig-checker 0 errors. |
…606) Takes the last batch of the `The Prose Content Backlog` cluster from [`TODO.md`](./TODO.md), following [#600](#600) (snippets), [#604](#604) (comments) and [#605](#605) (hub-only Markdown). Closes [#519](#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: ```text 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](#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](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… 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)
Takes the next batch of the
The Prose Content Backlogcluster fromTODO.md, following #600 (snippets) and #604 (comments). Part of #519.The anchor was re-verified first
developatc9c92dd, wherepython3 scripts/prose_lint.py --summaryreports 131 violations across 15 files. That is the figure the comment batch left, and merging that batch made it the anchor's own rather than a branch's, exactly as the cluster entry predicted.Scope, and a correction to it
The batch is the hub-only Markdown files:
docs/,spec/*.mdandcatalog/README.md. That is 90 findings across 9 files (79dash, 11semicolon), not the ~104 the batch was scoped at. The carried six hold 41, and 90 + 41 = 131.The 6 carried files are left for a later batch, since they rewrite byte-locked sections and owe a fleet re-vendor while these owe nothing. Every
dashfinding in the tree turned out to be hub-only, so what the carried half now holds is 41 semicolons and no dash at all.docs/devcontainer.mddocs/ssh-signing.mdspec/type-model.mdspec/fidelity-model.mddocs/repo-config-carry.mdspec/scope-model.mdcatalog/README.mddocs/token-cost.mdspec/readme-structure.mdThe exemption came first, and this time it was right
LABEL_DASHexempts- **Label** - textas a definition separator that is structurally a colon. It reaches neither a code-span label nor a paragraph-leading one, and both shapes flagged here. Widening it was the obvious move, and the corpus rejected it twice.A code-span definition list is already spelled with a colon in five files, against four dash-spelled lines in one (
catalog/README.md):A paragraph-leading label is already spelled
**Label.** Sentence, against nine dash-spelled lines confined to two troubleshooting sections.So both were a file that had not adopted the tree's own convention rather than a construct the rule fails to describe. The checker is unchanged by this batch. That is the same verdict the comment batch reached on a comment opening on a lowercase identifier.
A bulleted list terminating its items with semicolons appeared in exactly one place tree-wide,
spec/type-model.md:24-25, and its own last item already ended in a period. It was punctuation to make consistent rather than the list construction the semicolon exemption protects, which a line-based checker could not see across bullets in any case.One adjacent fix, flagged because it widens scope
Rewriting
docs/devcontainer.mdanddocs/ssh-signing.mdwith a script rather than an editor took both from CRLF to LF wholesale. Every prose and Markdown gate stayed green, andeditorconfig-checkerwas the only one that reported it.OPERATIONS.mdscoped that instruction to a new file, so it is widened here to a scripted rewrite of an existing one. Hub-only,presencefidelity, no re-vendor owed. Happy to split it out if it does not belong in this batch.Verification
Run from the repository root:
Every prose file changed line for line, with no line-count change in any of the 9, and the full word-diff was read for meaning drift.
TODO.mdcarries the updatedCheckedanchor and four newSettledlines: the batch figures, the two rejected exemptions, the one-off bullet list, and the CRLF gap.🤖 Generated with Claude Code