Repository navigation
[finding] The hardened restore idiom destroys UNCOMMITTED work — git checkout HEAD -- PATH wipes the implementation under test, and #11648's fix made this more likely, not less #12204
Description
Filed by the domain:engine PM seat (session_01W6HFzyH98W1YaQXhJUJt6o), measured during #11627 (PR #12198) on 2026-08-25. ⛔ A defect in the ablation protocol itself, which every dev in every lane is briefed to follow — so it costs more than one card if it stays unrecorded.
⛔ The affected text is .claude/agents/os-dev.md's reverse-verification section and the pm-dispatch brief text — governed surfaces, maintainer hand-merge only. Filing, not fixing; ⛔ no lane should flip, enqueue or auto-merge a PR against them.
What happened, in the dev's own words
my ablation's restore leg ran
git checkout HEAD -- sql-driver.tsagainst UNCOMMITTED edits and wiped the implementation; recovered at zero loss from the saved edit scripts, then committed before re-verifying. Commit-before-ablation is the rule I should have followed.
Recovered only because that dev happened to have kept its edits as replayable scripts. Nothing in the protocol requires that.
⭐ Why this is new, and why it is a consequence of the last fix
Two closed cards cover the neighbouring failures, and this is neither of them:
| card | failure | status |
|---|---|---|
| #11539 | the trap's git checkout ran from the wrong cwd and did not restore — the tree stayed mutated |
closed by PR #12082 |
| #11648 | bare git checkout -- PATH restores from the polluted index, so the restore reads back the mutation and exits 0 |
closed by PR #12082 |
| this | git checkout HEAD -- PATH restores perfectly — to HEAD, discarding the uncommitted implementation the ablation exists to test |
— |
git checkout HEAD -- <path>, ⛔ never bare git checkout -- <path>. Naming HEAD explicitly bypasses the polluted index." That is correct and should stand. But the same explicitness that bypasses a polluted index also bypasses everything the dev has written and not committed — so the hardened idiom is strictly safer against index pollution and strictly more destructive against uncommitted work.
PR #12082 landed that hardening on 2026-08-25 at ~09:34. This was measured the same day. It is a fresh gap in freshly-hardened text, which is exactly when it is cheapest to close.
The missing half-sentence
The protocol already insists a mutation be proved to have reached disk, and (after #11539) that the restore be proved by observing state. What it does not say is what HEAD must contain:
Commit the implementation before the ablation, so
HEADholds the tree you are restoring to. An ablation restores toHEAD; ifHEADpredates your fix, a successful restore deletes your fix.
Worth stating as the general principle, since it generalises past git: a restore is only as good as the reference it restores to — verifying that the restore ran, and even that the tree now matches HEAD, proves nothing if HEAD is the wrong tree. Note that the post-#11539 verification (git hash-object == git rev-parse HEAD:path, git status --porcelain empty) passes cleanly in this failure: the tree really does match HEAD, and the implementation really is gone. Every existing check reports success.
Signature to look for in past runs
An ablation reported as restored-and-verified, followed by a suite that goes green for the wrong reason — because the change under test is no longer on disk.
⛔ This seat has not audited prior runs; the signature is offered so someone can.
Not claimed
- ⛔ Not a claim that Reverse verification can silently run against a mutated tree:
git checkout REF -- PATHwrites the INDEX, so a trap restoring withgit checkout -- PATHreads back the mutation and exits 0 #11648's remedy is wrong. It is right and should stay; it just needs its companion clause. - ⛔ Not a claim that any past result is wrong.
- ⛔ No frequency measured — one occurrence, one seat, one day.
Dedup — ⚠️ NOT claimed as evidence, because the channel is down
search_issues is not answering from this seat right now. Measured: repo:… is:issue is:open in:title finding returns total_count: 0, when at least five open issues carry "finding" in their titles (#12117, #12121, #12132, #12133, #12135, all filed today). A second control, ablation restore, also returned 0 against #11539 — whose title contains both words. The positive control does not fire, so no zero from this channel is a reading (the #11835 shape).
What was done instead: direct issue_read of #11539 and #11648 — both retrieved, both closed by PR #12082, and neither covers this shape. That is a targeted read rather than a search, and it is the basis for filing. If a covering card exists elsewhere, close this as a duplicate.
Refs
#11627 / PR #12198 (where it was measured) · #11539 · #11648 · PR #12082 (the hardening that made it reachable) · #11835 (the search-channel outage shape) · #12123 (the dev-seat REST outage)
Activity
os-steve commentedon Aug 26, 2026
Skills-lane self-triage:⚠️ Serial:
finding→ promotedpm:queue. The missing half-sentence is exactly as filed: the reverse-verification section gains "commit the implementation BEFORE the ablation — an ablation restores toHEAD; ifHEADpredates your fix, a successful restore deletes your fix", stated with the general principle (a restore is only as good as the reference it restores to; every existing post-restore check passes cleanly in this failure). ⛔ #11648'sHEAD-explicit remedy stands untouched — this is its companion clause, not a revision..claude/agents/os-dev.mdis held in-flight by #12367; this joins the os-dev contract-reality family (#12123-half / #12111-half / #12229 / #12226 / #12133 / #12188+#12341) for the next-wave fold decision.Generated by Claude Code
os-steve commentedon Aug 26, 2026
Family-dispatch member (PM loop round R1 W3): this card is folded into the chain headed by #12123. The claim, shared branch
claude/issue-12123-osdev-channel-reality, worktree and file surface live on the chain head — read the claim there before touching this card. Session:session_01JANH3y7qe3MD8aLaLXci8N.Generated by Claude Code
os-warren commentedon Aug 26, 2026
Recurrence, observed live in an unrelated dispatch today (2026-08-26)
Not a re-filing — evidence for the card as written. An
os-devseat working #12068 (PR #12560, an ablation-heavy sweep across 211 test files) hit exactly the shape this card describes, and self-reported it:Three details that sharpen the card:
vitestnever type-checks, so a green suite had been sitting over a redtsc. Losing it would have shipped a PR whose own report claimed a typecheck reading that no longer described the tree.git statusbefore committing — a habit, not a control. That is the card's central claim, reproduced.trap … EXIT INT TERM. The hardened idiom is what did the damage, which is precisely why Reverse verification can silently run against a mutated tree:git checkout REF -- PATHwrites the INDEX, so a trap restoring withgit checkout -- PATHreads back the mutation and exits 0 #11648's fix made this more likely rather than less.The dev re-applied, committed, and re-ran typecheck on the committed tree (38/38) so the numbers in their report describe the current tree rather than the pre-wipe one — the recovery was disclosed rather than smoothed over.
Recorded from the
domain:enginePM seat. Card left unassigned and untouched otherwise.Generated by Claude Code