ci(review): the reviewer flags docs prose, and the rule that forbids style nits says so (#455)
The CI reviewer now flags docs prose that breaks CONTRIBUTING.md's plain-language
rules, as a NON-BLOCKING note, on the file set that document binds: `README.md`,
anything under `docs/`, `config.example.yaml`'s comments, and the prompts in
`agents/`. CONTRIBUTING.md has required concise plain language since `6bb4fbc`
(#454) and nothing enforced it; this is the enforcement half, split out because it
edits a workflow.
The same prompt already forbids flagging style, so that bullet now names this as
its one exception and re-states what stays out of scope inside those files:
heading style, line length, Markdown layout, and wording the reviewer would have
chosen differently. A prompt holding a rule and its own prohibition produces
neither reliably.
Four floors keep it from becoming a style review: quote the sentence and name the
rule it breaks, three instances at most, detail is explicitly not the target, and
five of CONTRIBUTING.md's six rules apply. "Shorter over completer" is left out on
purpose — whether a document earns its length is not a judgement a diff supports,
so it stays the maintainer's call, and that limit is stated in all three files
rather than left as a silent narrowing.
`test/review-prompt-plain-language.test.ts` (6 tests) pins the reconciliation, not
the wording. The file set has one home — CONTRIBUTING.md's Documentation section —
and three enforced copies (the prompt, `docs/ci.md` step 4, `BOUND_FILES`), each
pinned by set equality so a widening cannot land in one file alone. It reads the
prompt GitHub hands the model rather than the file's bytes, because the clause
lives in a block scalar where a byte-level grep matches indentation and wraps that
are not part of the string.
Twelve review rounds, eleven of them with notes: twenty-three notes, all fixed.
Eleven were a message that named the wrong cause, so 81 mutations were run and the
last twenty-six were graded on WHICH MESSAGE PRINTED rather than on red/green — an
assertion that fires with a remedy belonging to a different input costs a reader a
run. 76 killed; the 5 survivors are named in the PR body and are the
sentence-grading ones this change deliberately leaves to a human.
Three rules came out of those rounds and are written into the test:
- Two failures over one region are ordered by which remedy subsumes the other.
- A failure is composed from what is MISSING and what is EXTRA, not selected by an
`else` — an `else` is a catch-all wearing a diagnosis.
- A clause attaches only to the branches whose reason it states, and a branch may
ask for a deletion only when the state its own advice produces would still fail.
Gates: `tsc --noEmit` clean, `npm test` 1698 / 1698, `./test/e2e.sh` ALL ENDPOINTS
PASSED, `actionlint` and `shellcheck` green in CI. No runtime code changed, so
nothing about the delivered HTML moves.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>