docs(pm-skill): record the PR-body rule-plus-footer eat, paid by two cuts - #13007
Conversation
…cuts A PR body that ends with a `---` horizontal rule followed by the attribution footer loses BOTH on write, while the write call reports success. Re-writing the footer without the preceding rule survives intact. Issue comments are unaffected in either spelling, so the failure is conditional on the spelling (rule-then-footer at end of body) AND on the surface (PR body yes, comment no) — which means a seat that verified the footer in a comment has proved nothing about a PR body. The row carries the operative rule: write the footer bare in PR bodies and read the body back, which is the only detection. Net 0 at the 314-line ceiling, funded by two cuts with surviving homes: the author-rule row is reduced to the two measurements this table alone carries (the rule itself lives in AGENTS.md, which this table now points at instead of restating), and the credential-discrimination clause in the REST-availability row, which references/rest-channel.md already states in full. Co-authored-by: Claude <noreply@anthropic.com>
The fourth measurement — resultRecorded as a comment on purpose. Editing the body would destroy the very artifact the The bare footer survived verbatim. This PR body was written with the attribution footer And the platform then appended its own copy — rule and all. Beneath the surviving bare This independently reproduces the corroboration the card mentioned, and it sharpens the fact
The row as landed does not claim the platform's append is eaten, so nothing above Generated by Claude Code Generated by Claude Code |
Fixes #12909
One fact row in
.claude/skills/pm-dispatch/references/platform-readings.md, beside thetwo existing write-side sanitizer entries. Net 0 lines at the 314/314 zero-headroom
ceiling: 14 insertions, 14 deletions.
The row as landed
Placed directly after the
写侧实测行为 · 评论row, so the cluster now reads issue body /comment / PR body. The
写侧实测行为 ·naming is the cross-reference to the same silentsanitizer class — it costs no line and it is the idiom the two siblings already established.
Four lines, widest 120 bytes, at the cap and not over it.
Premise re-verified before writing, not inherited
The card grades another seat's measurement, so both cited bodies were read back on
origin/mainbefore the row was written. Both end the same way — a## Provenanceheading, the session URL as durable body prose, then the bare footer with no preceding
horizontal rule:
## Provenance/Authoring session: .../_Generated by [Claude Code](https://claude.ai/code)_Both were created 2026-08-28 within one minute of each other, which is the "both repos,
same run" the card claims. Premise holds.
Boundary the row deliberately does not cross. The eat was observed on the create /
body-write path, and the surviving spelling was written by a later edit. The row therefore
says
写调用rather than naming create and PATCH separately: a PATCH that still carries thetrailing rule was not measured, and the operative rule (bare footer plus read-back) covers
every path without needing that distinction.
A fourth measurement — this PR body itself
This body practises the row it lands: the attribution footer below carries no preceding
---rule. The body was read back in full after creation and the result is recorded in thedev report. Whatever it shows, it is a measurement either way; if the footer is missing when
you read this, that is the row failing open on its own remedy and worth a follow-up card.
Cut ledger — surviving homes, no re-wrap line-buying
Both cuts remove content that is stated in full somewhere else. Neither buys lines by
re-flowing; the re-wrapping visible in the diff is the consequence of deleting bytes from
the middle of a wrapped paragraph, and every resulting line is at or under 120 bytes.
Cut 1 — the
写侧 sanitizer 作者规则row, 6 lines to 3 (saves 3).The row restated the author rule. That rule's home is
AGENTS.md, under GitHub mutatesbody BYTES, which already carries: poison-shaped tokens spelled out in words, fences do
NOT protect them, and read the body back after writing any less-than fragment.
AGENTS.mdin the same breath delegates the measured shapes to this table — so the division is
already written down, and this table was holding a narrow copy of the other half.
.claude/agents/os-dev.mdstates the same division explicitly: 「一条规则一个家;此处不再复制窄版」.
What was kept, because this table is its only home: the entity spelling for a literal
angle bracket, and bare identifiers surviving, which is what keeps the SKILL extraction
contract valid.
What was dropped, with its surviving home named:
AGENTS.md("or are described in words");os-dev.mdcarries the placeholder spelling 「一律改占位词拼写」os-dev.md干净收尾: 「写完读回那条评论到尾部」 and 「PR 正文同欠一次全文回读」Cut 2 — the credential-discrimination clause in the REST-availability row (saves 1).
references/rest-channel.mdalready carries it verbatim in its 通道边界 block: therepo-scoped probe first, then 403 leads to a single
/rate_limitcall, 15000/hr means livecredentials refused by repo-scoping while 60/hr or an auth error means no credentials. That
file delegates only 按班矩阵 and 降级梯 back to this table, and both stay here untouched.
The clause is replaced by a pointer to it.
Genuinely lost, and stated rather than hidden: the parenthetical that one seat's token was
measured as a 14-byte placeholder string, and the phrase 两形同症不同治. The operative
discrimination they decorate survives in full at the named home.
No issue numbers were added to protocol prose —
check:pm-skill-id-lintis green below.Gates — union derived mechanically, run on
2e9ff3e2bnode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackderived the changeset from git itself and matched 8 families. All were run under
scripts/pm/os-verify-lock.shwith slotissue-12909, after the final commit, on the headquoted above. Exit codes were captured by redirecting each gate to its own file before
any pipe, so no
tailstatus is being read as a gate verdict.check:pm-skill-ratchet(ceiling)✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/platform-readings.md is 314 lines (ceiling 314; headroom 0).check:pm-skill-ratchet(max-line)✓ check-skill-line-ratchet self-test: 111 cases pass.— includes✓ budget is 120 bytes; widest line in the file measures 120check:pm-skill-id-lint✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).check:pm-governed-prose✓ check-governed-prose: 2 instruction surface(s) name all 5 registered governed surfaces (docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md) and claim no others.check:skill-frame-sync✓ check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic across 3 filescheck:skill-frame-freshness✓ check-skill-frame-freshness: the decision frame in this tree is current with origin/main (fetched just now).check:pm-governed-merges✓ check-governed-merges --self-test: 206 assertions ...check:agent-test-spelling✓ check-agent-test-spelling: 0 violations — 395 file(s) ...check:doc-authoring✓ doc authoring guard: 392 files clean — no bare metadata literals.check:doc-formula-expressions✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 425 files / 1453 TS blocks judged cleancheck:nul-bytes(every-edit convention)check-nul-bytes: OK (scanned 7220 text file(s) ... no raw ASCII control bytes).The ratchet verdict is quoted positively: the gate names this file and states 314 lines
against a ceiling of 314. The ceiling HOLDS and was not raised.
One derived family is NOT MEASURED rather than red — it refuses for want of CI-supplied
context and never reaches its predicate:
node scripts/pm/check-governed-queue-guard.mjsreturns exit 1 with⛔ Governed Surface Queue Guard: could not read GITHUB_EVENT_PATH— its own text says"could not look" must never exit 0 here. It runs with the event payload in CI.
check:doc-formula-expressionsneeds@objectstack/lintbuilt; the dependency closure wasbuilt inside the same locked run, and the verdict quoted above is the post-build reading.
Draft, and staying that way
This edits a governed surface (
.claude/**), so: draft only. No ready flip, noreviewers requested, no auto-merge, nothing approved — the PM runs the four-piece.
skip-changesetapplies: the diff is one.claude/markdown file and releases nothing fromany package. This seat's repo-scoped REST probe returned 403
(
GitHub access is not enabled for this session), so the label goes on through the MCPfallback — read current values, union, whole-group write, then a comparative read-back plus
a delayed second read, per the label discipline this very table carries.
Generated by Claude Code
Generated by Claude Code