The problem
The producer can open a PR whose prose is false, and then cannot correct it. Its whole body-write surface is two narrow repairs — repair_qa_block (append-only, every byte outside ## QA identical) and weaken_closes (direction-locked, can only remove a closing reference). Neither touches Summary prose.
So a PR opened with a wrong description is permanently human-gated, and the human's job is to run one gh pr edit.
The live case
rainlanguage/raindex#2777. The body claims:
When outputAmountSum === 0, falls back to unweighted mean of ioratio values
Adds an inline vitest case … verifies the result is finite and equals the unweighted mean
The diff is const ioratioAverage = outputAmountSum === 0 ? 0 : ioratioSum / outputAmountSum; and the test is expect(result[0].value).toEqual(0). There is no unweighted mean and no isFinite assertion. Both claims are false.
The producer already did everything available to it. It posted a trusted 🤖 ai:producer comment headed "Producer note — body-claim correction at head d4e88d9…" quoting both false clauses verbatim and stating what the diff does. It appended a truthful ## QA block via repair-qa-block. It then raised a design question asking a human to apply a staged body file.
The vetter rejected four times. Every verdict says the code is sound and the body is false — including at the exact head carrying the correction comment. So a trusted in-comment correction does not cure it.
Four vetter runs, one parked design question, and a human slot, for two sentences of prose.
Proposed: an append-only Summary update block
A producer verb in the same shape as repair_qa_block, and for the same reason it is safe: append-only, every byte outside the block byte-identical.
- It does not rewrite. The original claim stays visible with a dated correction beside it, so the record is a trail rather than a silent swap — which is strictly better than a body-edit verb.
- No new authority of the dangerous kind. It cannot rewrite
## QA evidence and cannot restore a closing reference, which is exactly what the two existing repairs are shaped to prevent.
- Place the block ABOVE the Summary, not at the end of the body. A reader who stops after the first paragraph must hit the correction rather than the stale prose. Appended at the bottom it is the same burial as a comment, just inside the body.
The vetter rule is part of this, not a follow-up
The false text remains in the body by design, so the vetter must treat a claim superseded by a later update block as superseded rather than false. Without that, the verb ships and #2777 collects a fifth reject on identical grounds.
This is the cheaper half of a rule change that was going to be needed anyway. The alternative framings both need a looser one:
- Accept a trusted correcting comment as curing the body — the vetter must decide whether a comment somewhere in the thread cures a specific body claim, which is a judgement.
- Let the vetter rewrite the body — that makes the check vacuous, since the vetter would grade a record it authored. The independence between who states a claim and who checks it is the same property the
human:* namespace and the 👤 marker protect.
With an in-body update block the vetter's question is mechanical: is there a superseding block, and does it address this claim. That is the version worth having.
Open questions
- Block format, so the vetter's check is a parse rather than a judgement — a fixed heading and an anchor to the head the correction was made at, mirroring how
## QA is validated by require-qa-block's own predicate.
- Repeated corrections. A PR reworked repeatedly accumulates blocks. Bounded by rework count and honest, but worth deciding whether a later block supersedes an earlier one explicitly.
- Scope: Summary only, or any non-
## QA prose.
The problem
The producer can open a PR whose prose is false, and then cannot correct it. Its whole body-write surface is two narrow repairs —
repair_qa_block(append-only, every byte outside## QAidentical) andweaken_closes(direction-locked, can only remove a closing reference). Neither touches Summary prose.So a PR opened with a wrong description is permanently human-gated, and the human's job is to run one
gh pr edit.The live case
rainlanguage/raindex#2777. The body claims:
The diff is
const ioratioAverage = outputAmountSum === 0 ? 0 : ioratioSum / outputAmountSum;and the test isexpect(result[0].value).toEqual(0). There is no unweighted mean and noisFiniteassertion. Both claims are false.The producer already did everything available to it. It posted a trusted
🤖 ai:producercomment headed "Producer note — body-claim correction at head d4e88d9…" quoting both false clauses verbatim and stating what the diff does. It appended a truthful## QAblock viarepair-qa-block. It then raised a design question asking a human to apply a staged body file.The vetter rejected four times. Every verdict says the code is sound and the body is false — including at the exact head carrying the correction comment. So a trusted in-comment correction does not cure it.
Four vetter runs, one parked design question, and a human slot, for two sentences of prose.
Proposed: an append-only Summary update block
A producer verb in the same shape as
repair_qa_block, and for the same reason it is safe: append-only, every byte outside the block byte-identical.## QAevidence and cannot restore a closing reference, which is exactly what the two existing repairs are shaped to prevent.The vetter rule is part of this, not a follow-up
The false text remains in the body by design, so the vetter must treat a claim superseded by a later update block as superseded rather than false. Without that, the verb ships and #2777 collects a fifth reject on identical grounds.
This is the cheaper half of a rule change that was going to be needed anyway. The alternative framings both need a looser one:
human:*namespace and the👤marker protect.With an in-body update block the vetter's question is mechanical: is there a superseding block, and does it address this claim. That is the version worth having.
Open questions
## QAis validated byrequire-qa-block's own predicate.## QAprose.