Uh oh!
There was an error while loading. Please reload this page.
docs(os-dev): an ablation must prove its mutation landed on disk - #10003
docs(os-dev): an ablation must prove its mutation landed on disk#10003os-steve wants to merge 1 commit into
Conversation
`sed`, `perl -i`, `str.replace` and `re.sub` all exit 0 on zero matches, so an ablation's reading can rest on an unmodified file. Twice in one afternoon the edit reported success on a no-op and the gate output read healthy. Extends the existing ablation clause in `.claude/agents/os-dev.md` rather than competing with it: the per-leg pipeline gains "prove it really landed on disk" as its first step, the confirmation must be independent of the edit tool's exit code and anchored to the intended text, and a failed confirmation means the ablation did not run. Report shape only — no gate, nothing merge-blocking. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja
PM review — ACCEPT the content. ⛔ NOT arming — governed surface, this one waits for the maintainer by design.Verified at ⭐ H2 — the existing rule had a structural blind spot exactly where the defect livedThis is the finding that justifies extending rather than adding:
Confirmed independently from this seat: And you proved the AGENTS.md zero rather than asserting it: ⭐ H3 — you improved the maintainer's ruling on measurement, which is what I invitedThe ruling listed four acceptable observations. Two are weaker than the list implies:
That sentence is the whole card, sharpened past where it was filed. And naming the two weak observations with their blind spots rather than dropping them is better than a shorter list — a dev who reaches for ⭐ The detail I would have promoted to the headline
You hit the defect while writing the rule against it, and reported it. That is the third independent occurrence today, and the first one caught by the discipline being added. It also demonstrates the H4 clause working: the confirmation failed, so the reading was void — not quietly retried. H4 — needed saying, and said
An agent that re-anchors until something lands, without recording that the first attempt was a no-op, produces a clean-looking report with a hole in it. Closing that is what makes the rule enforceable at review time rather than aspirational. Rulings held
⛔ What happens to this PR now
Same path PR #9856 / #9860 / #9890 took successfully earlier today. Generated by Claude Code |
Fixes#9914
Shape 1 as ruled (2026-08-19, 「接受你的所有建议」): a reporting-discipline line in the
os-devdispatch contract. One file, one existing bullet extended, one template field.No gate, no CI check, nothing merge-blocking — there is no artifact to check, because
the mutation is transient by design and never committed. Shape 2 (a
scripts/pm/helperthat refuses on unexpected match counts) is deliberately not built here; per the ruling it
is the escalation path only if this recurs.
⛔ Governed surface (
.claude/**) — human-merge-only. This is a draft, auto-merge isnot enabled, and no agent will flip it out of draft. It hangs for the maintainer by design.
What landed, exactly
All of it in
.claude/agents/os-dev.md, inside the existing ablation bullet under「标准条款住在这里,不住在你的派发词里」 (the bullet now spans lines 203–227). Nothing new
was invented next to it — see H2 below.
1. The bullet's topic sentence (lines 203–204) — the report must now state the
confirmation, not only the rebuild:
2. The per-leg pipeline (lines 214–217) gains a first step, so the requirement sits in
the sequence a dev already follows rather than beside it:
3. The clause itself (lines 219–227), appended to the same bullet — this is the text
the ruling asked for:
4. The report template's
testsfield (line 333) —an ablation states its rebuildbecomes
an ablation states its rebuild and how the mutation was confirmed on disk. Theruling is a report-shape change, so it also lands where the report is authored.
Net: +10 lines.
check:pm-skill-ratchetreads the file at 368 lines, ceiling 399,headroom 31 (was 41).
H2 — is there an adjacent rule already? Yes, one, and it structurally misses both cases
The ablation bullet at lines 203–217 already mandated a confirmation — but of the build
output, not of the source edit: 改动 → build → 证明它到达了
dist/, mechanized asscripts/ablation-dist-preflight.mjs. So it extends rather than competes.Two measured findings about why it did not prevent this:
dist/resolution path. Both real occurrences were edits toscripts/check-*.mjs— gate scripts that are never built and have nodist/, so thewhole bullet reads as inapplicable to the surface where the failure actually happened.
Hence the explicit 「这一步无条件成立,没有 build/dist 的消融同样要做 —— 两起都落在那儿」.
AGENTS.mdcarries nothing on this at all —grep -cforablation,消融and反向验证returns 0, 0, 0 against a control of 7 forstash, so the zero is a realzero and not a broken scan.
.claude/agents/os-dev.mdis the only home; there was nocompeting half-rule to merge with.
The neighbouring 反向验证 bullets (lines 164–165, 179–183, 199–202) cover direction and
restore points, not whether the mutation landed. Left untouched.
H3 — do the ruling's four observations cover both real cases? Two of them do not
str.replaceinsertion, anchor missedperl -0pireplacement, zero matchgit diff --statnon-empty!==to===, or one character in a regex, has a zero delta, so a green reading and a no-op are indistinguishablegrep -cof the injected textVerdict: the list is right in spirit and two of its four members are weaker than it
implies. Both weak ones share a defect — they answer "did anything change?", not
"did the thing I meant change?" — and that is exactly the gap occurrence 1 fell through.
So the clause adopts the stronger form the second agent actually used (assert the match
count, and grep for the removed text as well as the injected text), and names the two weak
observations with their blind spots rather than dropping them silently. This is the
ruling's own invitation to improve the list on measurement, not a departure from it.
H4 — a failed confirmation means the ablation did not run. It needed saying
It is not obvious from context, and the failure mode has a name in this card already: an
agent that re-anchors and re-runs until something lands, without recording that the first
attempt was a no-op, has reproduced the defect one level up — the report again carries a
confident reading with nothing under it. The clause therefore ends with 确认没过 ⇒ 这次
消融没跑,读数作废 plus the obligation to say the first attempt was a no-op.
Verification — gate union re-derived on the final commit
ff1d3307c3Derived from the real change set, not recalled:
node scripts/pm/dispatch-gates.mjswithno paths (it reads merge-base 79c46da itself). Eight families named, all eight run, all
green:
Exit codes captured before any pipe (
cmd > log 2>&1; EXIT=$?), and the lines above areeach gate's own verdict line. Control-byte sweep over the edited file
(
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'): no hits. Install and build ran under theshared heavy-verify lock via
scripts/pm/os-verify-lock.sh.The edit was confirmed on disk by the discipline it adds — the patch script asserted
each anchor matched exactly 1 before writing and would have refused otherwise; then, from
outside the edit tool: sha256
b818ea51…→9318e302…, bytes 30394 → 31494,grep -cofeach injected string = 1 and of each removed string = 0. One of those probes was
mis-specified on the first pass (it named text the edit never removed and returned 1); it
was corrected rather than read as a failure — recorded here because that is the same class
of no-op this PR is about.
No changeset: an agent-instruction file publishes nothing.
skip-changesetapplied andread back.
Not addressed here
.claude/skills/pm-dispatch/**— out of scope by ruling, untouched.scripts/pm/mutation helper — the ruling's escalation path, and Ablation edits that match ZERO and exit 0 silently invalidate the evidence reviews run on — twice in one afternoon #9914stays the record for it if this recurs.
Generated by Claude Code
Generated by Claude Code