Skip to content

docs(agents): note that checkout-from-ref stages the index (#8280) - #8472

Merged
hotlong merged 2 commits into
mainfrom
claude/issue-8280-agents-checkout-staging-trap
Aug 13, 2026
Merged

docs(agents): note that checkout-from-ref stages the index (#8280)#8472
hotlong merged 2 commits into
mainfrom
claude/issue-8280-agents-checkout-staging-trap

Conversation

@hotlong

@hotlonghotlong commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Fixes#8280

A short note in AGENTS.md's reverse-verification paragraph (Multi-agent working discipline), directly beside the existing git stash prohibition — the same family: a git operation whose blast radius is wider than it reads.

Where it landed

AGENTS.md has no separate "reverse verification" heading. The reverse-verification guidance is the paragraph that closes the stash block ("Doing reverse verification … Commit the fix FIRST"), and its own prescription is git checkout your-branch -- some/path — precisely the form that stages. The note follows it immediately, so the correction sits on the sentence that needs it.

Measured, not quoted

The trap was reproduced in a throwaway probe commit on lychee.toml in this worktree before the note was written (probe reset away afterwards; the branch carries the AGENTS.md change only):

$ git checkout origin/main -- lychee.toml # HEAD holds the fix
$ cp saved-copy lychee.toml # restore the WORKING TREE only
$ git status --porcelain lychee.toml
MM lychee.toml
$ git diff HEAD --stat -- lychee.toml
(empty — clean, exit 0)
$ git diff --cached HEAD --stat -- lychee.toml
lychee.toml | 2 --
$ git show :lychee.toml | tail -1
cache = true # main's copy, fix absent
$ git commit -m "probe" # bare commit builds from the INDEX
lychee.toml | 2 --
1 file changed, 2 deletions(-)

Both prescribed restores were then verified to clear index and tree, each leaving git status --porcelain empty: git checkout HEAD -- lychee.toml and git restore --source=HEAD --staged --worktree lychee.toml.

One correction the measurement forced. The card explains the clean git diff HEAD as "it compares HEAD against the index". It does not — git diff HEAD compares the working tree with HEAD and never consults the index, which is exactly why the cp restore silences it while the index still holds main's content. The note states the mechanism as measured rather than as quoted.

Amendment (second commit, per recorded seat ruling)

Per the seat ruling on this report's open question, a second commit appends one clause naming the measured non-staging way ingit restore --source=REF -- PATH without --staged writes the working tree only, so the foreign copy never reaches the index and the trap cannot arise; prevention at source, beside the cure that was already there. Re-measured with the exact prescribed form on this branch before writing it (HEAD holds the note, origin/main does not):

$ git restore --source=origin/main -- AGENTS.md
$ git status --porcelain AGENTS.md
M AGENTS.md # lone unstaged M, not MM
$ git diff --cached --stat -- AGENTS.md
(empty — index untouched, the note still staged-safe)
$ git checkout HEAD -- AGENTS.md # restore
$ git hash-object AGENTS.md; git rev-parse HEAD:AGENTS.md
cd93beb04eb8acfeb9aa2a5b5546a6bd5211eee8 # byte-identical, both lines
cd93beb04eb8acfeb9aa2a5b5546a6bd5211eee8

Scope

AGENTS.md only, +17 lines across two commits. The stronger index-vs-worktree commit guard named in the card stays out of scope (gate-farm owner's, not this card's). Governance text → conservative ADR-class treatment: draft PR, human merge — deliberately not marked ready, no auto-merge armed.

Gates

Re-run in the foreground on the amended tree (head f1c0aeecea):

  • pnpm check:nul-bytes — green (self-test 75 assertions; 7637 text files scanned, no raw control bytes)
  • pnpm check:doc-authoring — green (self-test + 376 files clean)
  • control-byte self-scan of AGENTS.md (grep -naP over the control ranges) — no hits
  • node scripts/pm/dispatch-gates.mjs AGENTS.md — re-derived against the actual diff: "No check family names the given paths in its own source." Adds nothing to the dispatched set.
  • skip-changeset applied: governance/docs text, releases no package.

Generated by Claude Code

`git checkout <ref> -- <path>` writes the index as well as the working tree,
so restoring the file with `cp` after a reverse-verification lap leaves the
index holding main's content. `git diff HEAD` reads clean and the tests pass
off the working tree, while a bare `git commit` builds from the index and
lands a commit that deletes the fix the PR claims to make.
Verified in a worktree before writing: MM in `git status --porcelain`, clean
`git diff HEAD`, 2 deletions in `git diff --cached`, and a bare commit that
captured the reversion. Both prescribed restores (`git checkout HEAD -- <path>`
and `git restore --source=HEAD --staged --worktree <path>`) clear index and
tree together.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WuTtyckQa1VcXwgd52JpN
@vercel

vercelBot commented Aug 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 13, 2026 2:57pm

Request Review

@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 13, 2026 — with Claude
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 13, 2026
One clause appended to the checkout-from-ref note: `git restore --source=<ref>
-- <path>` without `--staged` writes the working tree only, so the foreign copy
never reaches the index and the trap cannot arise. Prevention at source beside
the existing cure.
Measured with the exact prescribed form on this branch (HEAD holds the note,
origin/main does not): porcelain ' M AGENTS.md', `git diff --cached` empty
(index untouched), and the restore verified by byte-identity of hash-object
against the HEAD blob.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WuTtyckQa1VcXwgd52JpN
@hotlong
hotlong marked this pull request as ready for review August 13, 2026 15:33
@hotlong
hotlong merged commit ff1e9b6 into mainAug 13, 2026
22 checks passed
@hotlong
hotlong deleted the claude/issue-8280-agents-checkout-staging-trap branch August 13, 2026 15:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@hotlong@claude