Found by the dev on #8131 (PR #8277) while running a counterfactual lap. Filed unassigned, no domain:*, for triage to grade. ⛔ Not a code defect — a trap in the workflow AGENTS.md itself prescribes, which is why it is worth writing down rather than remembering.
The mechanism
Reverse verification requires standing up "what would main do?" against the working tree. The natural way to stage that is:
git checkout origin/main -- <paths> # bring in main's version
# ...run the counterfactual...
cp /somewhere/mine <paths> # restore my version
git checkout <ref> -- <path> writes to the index as well as the working tree. Restoring with cp (or any plain file write) touches only the working tree. So afterwards:
- the index holds
main's version — i.e. the fix stripped out; - the working tree holds the correct version;
git diff HEAD reads clean, because it compares HEAD against the index;- tests pass, because vitest reads the working tree.
Commit at that moment and the commit is built from the index: a PR that silently reverts its own fix, with a green local suite and a diff that looked right when checked the usual way. On #8277 the index at that moment held 157 deletions.
Caught before committing via git status --porcelain showing MM (staged and unstaged modifications on the same path) and git show :<path> to read the index copy directly.
Why it deserves a durable note rather than an agent's memory
- The prescribed workflow walks straight into it. Reverse verification — revert the fix, measure red, restore — is required on essentially every card in this repo, so the exposure is repo-wide and recurring, not incidental to one task.
- Every habitual check passes.
git diff HEAD clean, tests green, working tree visibly correct. The one command that reveals it (git show :<path>, or noticing MM) is not part of anyone's routine. - The failure mode is maximally expensive: a merged PR whose body accurately describes a fix it does not contain, with pins that "passed". It would be found later as a mystery regression, with the PR that caused it looking innocent.
This is the same family as the git stash prohibition already in AGENTS.md / CLAUDE.md — a git operation whose blast radius is wider than it reads — and it belongs beside it.
Suggested shape (⛔ not a ruling)
A short note in AGENTS.md's reverse-verification section, next to the stash warning: git checkout <ref> -- <path> stages; restore with git checkout HEAD -- <path> (which restores both index and tree) or git restore --source=HEAD --staged --worktree <path>, and verify with git status --porcelain before committing — ⛔ never trust git diff HEAD alone after a checkout-from-ref.
The mechanically stronger option, if wanted: a pre-commit or PR-time guard that refuses a commit whose index diverges from the working tree on files the PR claims to change. That is a bigger idea and belongs to whoever owns the gate farm, not to this card.
Related
The dev's own recommendation was option B (a small docs card). Recording it as a finding rather than acting: AGENTS.md is repo governance text, and I am an execution seat.
Found by the dev on #8131 (PR #8277) while running a counterfactual lap. Filed unassigned, no
domain:*, for triage to grade. ⛔ Not a code defect — a trap in the workflow AGENTS.md itself prescribes, which is why it is worth writing down rather than remembering.The mechanism
Reverse verification requires standing up "what would
maindo?" against the working tree. The natural way to stage that is:git checkout <ref> -- <path>writes to the index as well as the working tree. Restoring withcp(or any plain file write) touches only the working tree. So afterwards:main's version — i.e. the fix stripped out;git diff HEADreads clean, because it compares HEAD against the index;Commit at that moment and the commit is built from the index: a PR that silently reverts its own fix, with a green local suite and a diff that looked right when checked the usual way. On #8277 the index at that moment held 157 deletions.
Caught before committing via
git status --porcelainshowingMM(staged and unstaged modifications on the same path) andgit show :<path>to read the index copy directly.Why it deserves a durable note rather than an agent's memory
git diff HEADclean, tests green, working tree visibly correct. The one command that reveals it (git show :<path>, or noticingMM) is not part of anyone's routine.This is the same family as the
git stashprohibition already in AGENTS.md / CLAUDE.md — a git operation whose blast radius is wider than it reads — and it belongs beside it.Suggested shape (⛔ not a ruling)
A short note in AGENTS.md's reverse-verification section, next to the stash warning:
git checkout <ref> -- <path>stages; restore withgit checkout HEAD -- <path>(which restores both index and tree) orgit restore --source=HEAD --staged --worktree <path>, and verify withgit status --porcelainbefore committing — ⛔ never trustgit diff HEADalone after a checkout-from-ref.The mechanically stronger option, if wanted: a pre-commit or PR-time guard that refuses a commit whose index diverges from the working tree on files the PR claims to change. That is a bigger idea and belongs to whoever owns the gate farm, not to this card.
Related
The dev's own recommendation was option B (a small docs card). Recording it as a finding rather than acting: AGENTS.md is repo governance text, and I am an execution seat.