Context
On 2026-08-07/08 I posted a correction to my own earlier factual claim on #16463 as a second comment, leaving two comments where a reader must read both to be safe — and where the economical read (first comment, stop) returned the withdrawn conclusion. @tobiu named it: "isn't that the classic case for updating the wrong comment again, instead of adding more => split brain?" I consolidated it (superseded comment reduced to a 711-byte pointer, live comment made self-contained), under the same operator direction that produced the ticket-body compaction that day: "history does not matter, facts do."
I first read this as a personal-discipline failure and drafted it as one. It is not only that. The substrate's nearest-matching rule prescribed the append, and I only found that by grepping for the owner instead of reasoning about the habit.
The Problem
review-response-protocol.md §13 PR Comment Hygiene (Polish vs. Pivot) is a five-row table keying comment behaviour to lifecycle stage. Two rows are adjacent to a correction, and neither covers one:
| §13 row |
what it prescribes |
why it did not apply |
Polish commits landing (:116) |
UPDATE the existing comment in place — "Readers see current state, not evolution." |
Keyed to a commit event. A withdrawn measurement lands no commit, so the trigger never fires. |
Scope reductions / architectural pivots (:118) |
NEW comment. "Do NOT rewrite the original — callout preserves the pivot in history." |
The nearest match by shape — and it actively prescribes appending. |
A withdrawal is neither. It is not better execution of the same idea (polish), and it is not a change of architectural direction (pivot) — it is the same direction with a fact removed. Falling through to the pivot row is the correct reading of the table as written, and it produces exactly the split-brain outcome.
Three further gaps in the same table:
callout preserves the pivot in history is in direct tension with the operator's standing "history does not matter, facts do." For a genuine pivot the rationale holds — the decision change is the content. For a correction it inverts: preserving a withdrawn claim in readable form is the harm, and the reader who stops early gets the wrong answer.
- Every row assumes the PR is yours. They are written for an author on their own PR, where the body is also available. On another author's artifact, §11 authorship respect makes comments the only channel — and
UPDATE in place has no commit to hang on.
- No row states the invariant. What is missing is not a stage but a property: exactly one comment is live; superseded ones are reduced to a pointer. Editing your own comment is authorship-respecting; leaving sediment is not.
The Architectural Reality
.agents/skills/pull-request/references/review-response-protocol.md — 14,633 bytes. §13 at :109, table at :113-119 (header :113-114, five rows :115-119), §14 A2A Comment-ID Propagation immediately after at :121. This is the owning surface: it already governs comment count and update-vs-append.
- Budget check — corrected TWICE, and the binding gate is the tightest of the three.
maxPositiveDeltaBytes: 250 does bind, through a global net-growth gate over all .agents/skills Markdown — proven by lint-skill-manifest --base origin/dev failing the first implementation at +888. Membership in defaults.oversizedWorkflowMaps governs a separate per-file check that merely shares the same constant, so absence from that list says nothing about the net gate. The binding budget is the per-skill override skills.pull-request.perFilePayloadBudget: 22000 — not the defaults value of 25000 — leaving 7,367 bytes of headroom against the current 14,633. The per-file budget was ample and therefore never the blocker. Two corrections, two parties: @neo-gpt caught the 25,000-vs-22,000 error at intake (IC_kwDODSospM8AAAABN2VrbA), and the lint caught the does-not-bind error — which was mine, and which I wrote into this body while simultaneously proving it false in the PR. Overrides run both directions — skills.pr-review is 37000 — so the default is neither a floor nor a ceiling and reading it alone is never sufficient.
- ADR 0008 governs skill shape: a row added to a
references/ payload is Atlas-side, not router-side, so Progressive Disclosure holds and routerByteBudget: 12 is untouched.
learn/agentos/process/correction-culture.md is the adjacent practice doc and deliberately NOT the owner. @neo-gpt made that scope call on PR #16651: this is correction-channel mechanics, distinct from that ticket's correction-as-probe-constraint tell. Keeping them apart is what stopped a twelve-line diff from becoming the accretion it argues against.
The Fix
Amend §13's table in place. No new file, no new section, no router change.
- Add one row for a correction or withdrawal of a published claim: UPDATE in place; when a new comment is genuinely warranted, reduce the superseded one to a pointer so exactly one comment is live.
- Scope the pivot row's rationale so
preserves the pivot in history reads as applying to direction changes, not to withdrawn facts.
- State the channel case once: on another author's artifact, comments are the only channel and the same one-live-comment invariant applies.
An offset is available in the same file if a reviewer wants net-zero (§12 and §13's preamble both carry expandable prose), but no budget requires one.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
review-response-protocol.md §13 table |
this ticket; ADR 0008 for shape |
+1 row: correction/withdrawal → update in place, else superseded → pointer |
the five existing rows keep their prescriptions |
the payload is the doc |
anchors verified live: §13 :109, rows :115-119 |
§13 Scope reductions / pivots row rationale |
same |
scoped to direction changes, not withdrawn facts |
row keeps its NEW-comment prescription |
same |
quoted verbatim from :118 |
| Skill-Markdown net growth — the binding gate |
skills.manifest.json → defaults.maxPositiveDeltaBytes |
net at most 250 bytes across all .agents/skills Markdown; offset or justify |
fails CI at --base origin/dev |
manifest + lint |
proven binding: +888 FAILED, +224 OK |
perFilePayloadBudget compliance |
.agents/skills/skills.manifest.json → skills.pull-request |
stay under 22,000 bytes (per-skill override, not the 25,000 default) |
n/a |
manifest |
14,633 bytes at origin/dev; 7,367 headroom — never the blocker |
Decision Record impact: none. No ADR governs comment hygiene — checked all 37 in learn/agentos/decisions/. ADR 0008 constrains the shape of the edit and is respected, not amended.
Acceptance Criteria
Out of Scope
learn/agentos/process/correction-culture.md — the practice doc. @neo-gpt's scope call on PR #16651 keeps channel mechanics out of it, and that PR's own restraint is the reason.
- A mechanical lint for comment sediment. Probably real, but it needs a detector design; this ticket is the rule such a detector would enforce.
#16613 — mechanical deference detection. Adjacent discipline, different substrate.
- Ticket-body compaction. Already done under operator direction; this is the comment channel only.
- Every other comment surface. The evidence is PR/issue review comments. A general rule covering A2A and Discussions is not what was observed.
Avoided Traps
- Filing it as a personal-discipline note. The first draft was "remember to consolidate comments." That shape does not transfer, and it is wrong about the cause — the pivot row prescribed the append.
- A new process doc. Three findings on 2026-08-07 would each have justified one. §13 exists and owns the concern.
- Concluding the 250-byte gate does NOT bind, on the grounds that the file is absent from
oversizedWorkflowMaps. Wrong, and mine: that list governs a separate per-file check sharing the same constant, while a global net-growth gate binds every skill Markdown file. Only running the lint the way CI does (--base origin/dev) found it — the bare invocation prints OK and states that byte-delta gates were skipped, so reading that OK as a pass ships a red PR.
- Then asserting the
defaults budget as the effective one. Same error one layer in, and I made it after avoiding the first: defaults.perFilePayloadBudget is 25000, but skills.pull-request overrides it to 22000. I printed the defaults block and never looked for a per-skill entry. Caught by @neo-gpt at intake, not by me — a default is a fallback, never a reading of the effective value.
- Reasoning about the habit instead of grepping for the owner. The mechanism — that the nearest row prescribes appending — is not available by introspection. It took one grep.
Related
#16650 / PR #16651 (correction-as-probe-constraint — the sibling finding, and where this one was scoped out) · #16463 (the consolidated specimen) · #16566 (the operator's "history does not matter, facts do" rewrite) · #16613 (adjacent, mechanical) · ADR 0008 (skill shape authority).
Live latest-open sweep: checked the latest 20 open issues at 2026-08-08T03:33:15Z; no equivalent found. A2A in-flight claim sweep at the same time: active claims are #16604 + #16629 (@neo-opus-ada) and #16526 (@neo-opus-grace); none overlap this scope.
Origin Session ID: 4141258c-36d3-4788-b0c2-ab3ebe0867be
Retrieval Hint: query_raw_memories("one live comment superseded comments collapse to a pointer, review-response-protocol section 13 polish vs pivot, correction channel on another author's artifact")
Retrieval Hint: the discriminating question is which §13 row fires when a published claim is withdrawn? — as written, the pivot row does, and it prescribes appending.
Context
On 2026-08-07/08 I posted a correction to my own earlier factual claim on
#16463as a second comment, leaving two comments where a reader must read both to be safe — and where the economical read (first comment, stop) returned the withdrawn conclusion. @tobiu named it: "isn't that the classic case for updating the wrong comment again, instead of adding more => split brain?" I consolidated it (superseded comment reduced to a 711-byte pointer, live comment made self-contained), under the same operator direction that produced the ticket-body compaction that day: "history does not matter, facts do."I first read this as a personal-discipline failure and drafted it as one. It is not only that. The substrate's nearest-matching rule prescribed the append, and I only found that by grepping for the owner instead of reasoning about the habit.
The Problem
review-response-protocol.md§13 PR Comment Hygiene (Polish vs. Pivot) is a five-row table keying comment behaviour to lifecycle stage. Two rows are adjacent to a correction, and neither covers one:Polish commits landing(:116)Scope reductions / architectural pivots(:118)A withdrawal is neither. It is not better execution of the same idea (polish), and it is not a change of architectural direction (pivot) — it is the same direction with a fact removed. Falling through to the pivot row is the correct reading of the table as written, and it produces exactly the split-brain outcome.
Three further gaps in the same table:
callout preserves the pivot in historyis in direct tension with the operator's standing "history does not matter, facts do." For a genuine pivot the rationale holds — the decision change is the content. For a correction it inverts: preserving a withdrawn claim in readable form is the harm, and the reader who stops early gets the wrong answer.UPDATE in placehas no commit to hang on.The Architectural Reality
.agents/skills/pull-request/references/review-response-protocol.md— 14,633 bytes. §13 at:109, table at:113-119(header:113-114, five rows:115-119), §14 A2A Comment-ID Propagation immediately after at:121. This is the owning surface: it already governs comment count and update-vs-append.maxPositiveDeltaBytes: 250does bind, through a global net-growth gate over all.agents/skillsMarkdown — proven bylint-skill-manifest --base origin/devfailing the first implementation at+888. Membership indefaults.oversizedWorkflowMapsgoverns a separate per-file check that merely shares the same constant, so absence from that list says nothing about the net gate. The binding budget is the per-skill overrideskills.pull-request.perFilePayloadBudget: 22000— not thedefaultsvalue of25000— leaving 7,367 bytes of headroom against the current 14,633. The per-file budget was ample and therefore never the blocker. Two corrections, two parties: @neo-gpt caught the 25,000-vs-22,000 error at intake (IC_kwDODSospM8AAAABN2VrbA), and the lint caught the does-not-bind error — which was mine, and which I wrote into this body while simultaneously proving it false in the PR. Overrides run both directions —skills.pr-reviewis37000— so the default is neither a floor nor a ceiling and reading it alone is never sufficient.references/payload is Atlas-side, not router-side, so Progressive Disclosure holds androuterByteBudget: 12is untouched.learn/agentos/process/correction-culture.mdis the adjacent practice doc and deliberately NOT the owner. @neo-gpt made that scope call on PR#16651: this is correction-channel mechanics, distinct from that ticket's correction-as-probe-constraint tell. Keeping them apart is what stopped a twelve-line diff from becoming the accretion it argues against.The Fix
Amend §13's table in place. No new file, no new section, no router change.
preserves the pivot in historyreads as applying to direction changes, not to withdrawn facts.An offset is available in the same file if a reviewer wants net-zero (§12 and §13's preamble both carry expandable prose), but no budget requires one.
Contract Ledger Matrix
review-response-protocol.md§13 table:109, rows:115-119Scope reductions / pivotsrow rationale:118skills.manifest.json→defaults.maxPositiveDeltaBytes.agents/skillsMarkdown; offset or justify--base origin/dev+888FAILED,+224OKperFilePayloadBudgetcompliance.agents/skills/skills.manifest.json→skills.pull-requestorigin/dev; 7,367 headroom — never the blockerDecision Record impact:
none. No ADR governs comment hygiene — checked all 37 inlearn/agentos/decisions/. ADR 0008 constrains the shape of the edit and is respected, not amended.Acceptance Criteria
Polish commits landingandScope reductions / architectural pivots.Scope reductions / pivotsrationale is scoped so it cannot be read as authority to preserve a withdrawn fact in readable form.lint-skill-manifest --base origin/devpasses — the binding gate is net at most 250 bytes across all.agents/skillsMarkdown, satisfied by offset rather than by the[skill-growth-justified]escape, which a routine rule addition does not warrant. The PR states the net delta.review-response-protocol.mdalso stays under its effectiveperFilePayloadBudget—skills.pull-request: 22000, not thedefaults: 25000.SKILL.mdrouter.#16463consolidation and PR#16651's own second comment — as origin evidence rather than a hypothetical.Out of Scope
learn/agentos/process/correction-culture.md— the practice doc. @neo-gpt's scope call on PR#16651keeps channel mechanics out of it, and that PR's own restraint is the reason.#16613— mechanical deference detection. Adjacent discipline, different substrate.Avoided Traps
oversizedWorkflowMaps. Wrong, and mine: that list governs a separate per-file check sharing the same constant, while a global net-growth gate binds every skill Markdown file. Only running the lint the way CI does (--base origin/dev) found it — the bare invocation printsOKand states that byte-delta gates were skipped, so reading thatOKas a pass ships a red PR.defaultsbudget as the effective one. Same error one layer in, and I made it after avoiding the first:defaults.perFilePayloadBudgetis25000, butskills.pull-requestoverrides it to22000. I printed thedefaultsblock and never looked for a per-skill entry. Caught by @neo-gpt at intake, not by me — a default is a fallback, never a reading of the effective value.Related
#16650/ PR#16651(correction-as-probe-constraint — the sibling finding, and where this one was scoped out) ·#16463(the consolidated specimen) ·#16566(the operator's "history does not matter, facts do" rewrite) ·#16613(adjacent, mechanical) · ADR 0008 (skill shape authority).Live latest-open sweep: checked the latest 20 open issues at 2026-08-08T03:33:15Z; no equivalent found. A2A in-flight claim sweep at the same time: active claims are
#16604+#16629(@neo-opus-ada) and#16526(@neo-opus-grace); none overlap this scope.Origin Session ID: 4141258c-36d3-4788-b0c2-ab3ebe0867be
Retrieval Hint:
query_raw_memories("one live comment superseded comments collapse to a pointer, review-response-protocol section 13 polish vs pivot, correction channel on another author's artifact")Retrieval Hint: the discriminating question is which §13 row fires when a published claim is withdrawn? — as written, the pivot row does, and it prescribes appending.