Skip to content

Clear the Markdown half of the prose backlog, hub-only files first - #605

Merged
ptr727 merged 3 commits into
developfrom
prose-backlog-markdown-hub-only
Aug 7, 2026
Merged

Clear the Markdown half of the prose backlog, hub-only files first#605
ptr727 merged 3 commits into
developfrom
prose-backlog-markdown-hub-only

Conversation

@ptr727

@ptr727 ptr727 commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Takes the next batch of the The Prose Content Backlog cluster from TODO.md, following #600 (snippets) and #604 (comments). Part of #519.

The anchor was re-verified first

develop at c9c92dd, where python3 scripts/prose_lint.py --summary reports 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/*.md and catalog/README.md. That is 90 findings across 9 files (79 dash, 11 semicolon), 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 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.

File Findings
docs/devcontainer.md 22
docs/ssh-signing.md 17
spec/type-model.md 17
spec/fidelity-model.md 8
docs/repo-config-carry.md 7
spec/scope-model.md 7
catalog/README.md 6
docs/token-cost.md 5
spec/readme-structure.md 1

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 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):

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. 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.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. Hub-only, presence fidelity, no re-vendor owed. Happy to split it out if it does not belong in this batch.

Verification

Run from the repository root:

prose_lint.py gating list              exit 0
prose_lint.py backlog list             131/15 -> 41/6, the carried six exactly
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 in any of the 9, and the full word-diff was read for meaning drift.

TODO.md carries the updated Checked anchor and four new Settled lines: the batch figures, the two rejected exemptions, the one-off bullet list, and the CRLF gap.

🤖 Generated with Claude Code

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

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 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, and catalog/README.md to resolve dash/semicolon findings without changing the checker.
  • Update TODO.md with the new verified anchor and additional settled notes, plus new reference-link definitions.
  • Expand OPERATIONS.md guidance to run editorconfig-checker not 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.

Comment thread OPERATIONS.md Outdated
Comment thread docs/devcontainer.md Outdated
Comment thread docs/ssh-signing.md Outdated
Comment thread spec/type-model.md Outdated
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>
Copilot AI review requested due to automatic review settings August 7, 2026 19:45

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

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>
Copilot AI review requested due to automatic review settings August 7, 2026 19:49
@ptr727

ptr727 commented Aug 7, 2026

Copy link
Copy Markdown
Owner Author

Round 2 generated no thread and suppressed one finding, answered here since a suppressed finding has none to reply in.

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.

Accepted and fixed in f66607d. It is this branch's own doing: splitting that line's dash into two sentences is what promoted For a codegen or config repo to the front of one, so the phrase arrived without the comma that closes it.

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. 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, so it is left alone.

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.

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

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

@ptr727
ptr727 merged commit d791930 into develop Aug 7, 2026
7 checks passed
@ptr727
ptr727 deleted the prose-backlog-markdown-hub-only branch August 7, 2026 20:05
ptr727 added a commit that referenced this pull request Aug 8, 2026
…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>
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)
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