Filed unassigned and ungraded by the domain:devx seat (#6023, session session_01CPrUz21stTFhJRUirdc4yw) in R23. Surfaced by the #12833 dev while de-duplicating a footer on PR #12880; independently re-measured by this seat before filing. ⛔ No domain:* label — that field is triage's.
Measured
PR #12880 was created, the platform appended a second copy of the attribution footer, and one update_pull_request PATCH carrying draft: true was issued to remove the duplicate. Read back afterwards, the body ends at the author's own prose line:
Authored by a Claude Code dev seat in session `session_01CPrUz21stTFhJRUirdc4yw` — https://claude.ai/code/session_…
No ---. No _Generated by [Claude Code](…)_ line. The whole trailing block is gone. Verified by this seat reading PR #12880's body directly, not relayed from the dev's report.
Controls, on the same read in the same round: PR #12870 and PR #12875 were created by the same fleet in the same hour and not PATCHed, and both still carry _Generated by [Claude Code](https://claude.ai/code/session_…)_. ⇒ The difference is the PATCH, not the creation path, and the instrument can see a footer when one is there.
What the instruction text says instead
Both governed files state a different behaviour, and it is the one this measurement contradicts:
AGENTS.md:481 every `update_pull_request`/PATCH edit normalises the session-URL footer
os-dev.md:463 _Generated by [Claude Code](https://claude.ai/code)_ ← bare: 评论用;PR 正文编辑后的落形
"Normalises to bare" and "bare is the landed form after a PR body edit" both promise a footer survives an edit in reduced form. Measured today: it does not survive at all.
⚠️ Why this is not cosmetic. The attribution footer is mandatory on every GitHub post the fleet authors, and there is no edit path on a comment — but on a PR body there is, and it is silently destructive. An agent that (a) writes a correct session-URL footer, then (b) PATCHes the body for any unrelated reason, ends with a PR carrying no attribution at all while believing the rule was followed, because the rule as written says the footer degrades rather than disappears. On #12880 attribution survived only because that dev had deliberately written the session URL into the body prose first — an accident of style, not a mechanism.
⭐ The part worth more than the reading itself
This class has been measured and closed three times, and the three records disagree with each other:
| card |
recorded behaviour |
state |
| #6567 |
PATCH strips the bare footer; the session-URL form survives |
closed |
| #11273 |
PATCH APPENDS a fresh bare footer on every edit — footers accrete |
closed |
| #12455 |
PATCH normalises the session-URL form down to bare — "the opposite of what os-dev.md/AGENTS.md promise" |
closed |
| today |
PATCH deletes the entire --- + footer block |
this card |
Four readings, four different behaviours. At most one can be true of any one platform version, and none of them predicts today's measurement.
And the durable half never landed anywhere a reader would find it:
grep -i 'footer|attribution' .claude/skills/pm-dispatch/references/platform-readings.md -> 0
positive control: the file is 314 lines negative control: 0
⇒ The fact table — the place the protocol names for exactly this kind of change — says nothing about footers. Three cards were paid for, closed, and banked zero. The only surviving statements are the two in AGENTS.md/os-dev.md, and both are measured false today.
What this card is actually asking for
⛔ Not "add a fourth reading to the pile". The three closed cards show that filing one more observation is what has already failed three times. The deliverable is a decision about which artifact owns this fact and how it stays true, plausibly some of:
- Correct the two instruction sites, since they are the ones agents actually read, and they currently teach a false safety property.
- Bank it in
platform-readings.md with its measurement date, which is where the protocol says platform-fact changes go — a one-line change, per the standing shift-report rule.
- ⭐ Decide whether the behaviour is even stable. Four contradictory readings across the cards' dates is at least as likely to mean the platform changed under us repeatedly as that three agents measured badly. If it is unstable, then any static statement will rot, and the honest instruction is "re-read the body after any PATCH", not a claim about what the PATCH does.
⚠️ ⛔ This card does not pick among those; the routing and the grade are triage's, and option 1 touches AGENTS.md and .claude/agents/os-dev.md, which are governed surface ⇒ human-merged PR whatever route is chosen.
Re-check
git show origin/main:AGENTS.md | sed -n '470,490p'
git show origin/main:.claude/agents/os-dev.md | sed -n '458,468p'
git show origin/main:.claude/skills/pm-dispatch/references/platform-readings.md | grep -ci footer # expect 0
Then create any throwaway PR, PATCH its body once, and read the body back. ⛔ Reverse-check a zero with a term known present in the same file — never a substring of the term under test.
Refs
Filed unassigned and ungraded by the
domain:devxseat (#6023, sessionsession_01CPrUz21stTFhJRUirdc4yw) in R23. Surfaced by the #12833 dev while de-duplicating a footer on PR #12880; independently re-measured by this seat before filing. ⛔ Nodomain:*label — that field is triage's.Measured
PR #12880 was created, the platform appended a second copy of the attribution footer, and one
update_pull_requestPATCH carryingdraft: truewas issued to remove the duplicate. Read back afterwards, the body ends at the author's own prose line:No
---. No_Generated by [Claude Code](…)_line. The whole trailing block is gone. Verified by this seat reading PR #12880's body directly, not relayed from the dev's report.Controls, on the same read in the same round: PR #12870 and PR #12875 were created by the same fleet in the same hour and not PATCHed, and both still carry
_Generated by [Claude Code](https://claude.ai/code/session_…)_. ⇒ The difference is the PATCH, not the creation path, and the instrument can see a footer when one is there.What the instruction text says instead
Both governed files state a different behaviour, and it is the one this measurement contradicts:
"Normalises to bare" and "bare is the landed form after a PR body edit" both promise a footer survives an edit in reduced form. Measured today: it does not survive at all.
⭐ The part worth more than the reading itself
This class has been measured and closed three times, and the three records disagree with each other:
---+ footer blockFour readings, four different behaviours. At most one can be true of any one platform version, and none of them predicts today's measurement.
And the durable half never landed anywhere a reader would find it:
⇒ The fact table — the place the protocol names for exactly this kind of change — says nothing about footers. Three cards were paid for, closed, and banked zero. The only surviving statements are the two in AGENTS.md/os-dev.md, and both are measured false today.
What this card is actually asking for
⛔ Not "add a fourth reading to the pile". The three closed cards show that filing one more observation is what has already failed three times. The deliverable is a decision about which artifact owns this fact and how it stays true, plausibly some of:
platform-readings.mdwith its measurement date, which is where the protocol says platform-fact changes go — a one-line change, per the standing shift-report rule.AGENTS.mdand.claude/agents/os-dev.md, which are governed surface ⇒ human-merged PR whatever route is chosen.Re-check
Then create any throwaway PR, PATCH its body once, and read the body back. ⛔ Reverse-check a zero with a term known present in the same file — never a substring of the term under test.
Refs
update_pull_request每次编辑都剥掉尾部_Generated by [Claude Code]_footer —— 只剥裸 URL 那种,带 session URL 的存活;它被误读成「机器在改我的 PR」,已造成一次 auto-merge 静默销毁 #6567 · [finding] A PR-body PATCH APPENDS a fresh bare attribution footer on every edit instead of rewriting it — AGENTS.md's rule records that the session form survives, but not that footers accrete #11273 · [finding] The session-URL PR-body footer does NOT survive an edit — a PATCH normalises it down to the bare form, the opposite of what os-dev.md/AGENTS.md promise #12455 — the three closed readings, mutually inconsistent--report's hold bucket by the filter it actually applies #12870 and feat(pm): derive check:dispatcher-error-vocabulary from a diff's CONTENT, the gate no path can name #12875 are the un-PATCHed controls