rule: refresh-before-decide extends to working-tree reads — 1008Z empirical anchor caught phantom PR #5128 drift#5134
Merged
AceHack merged 1 commit intoMay 26, 2026
Conversation
… updates refs not files (1008Z empirical anchor caught phantom PR #5128 drift) The failure mode: agent runs `git fetch origin main` (Step-1 refresh) which updates `refs/remotes/origin/main` but does NOT promote local HEAD; subsequent `Read`/`cat`/`grep` against working-tree paths read the LOCAL HEAD's files (stale-against-origin if local hasn't been ff-promoted). If the agent authors substrate at that point, it's against state that may already be resolved on origin/main N commits ahead — phantom "drift" findings that require retraction. Empirical anchor (this commit's authoring session): - 2026-05-26T10:08Z Otto-CLI cold-boot ran `git fetch origin main` (success) in the operator's primary checkout (local HEAD `2774fef5a`) - Read `tools/alignment/filter_gate_log.ts` + `.test.ts` via working tree — both files appeared unfixed despite PR #5128 having landed the fix 1h 46min earlier at 08:22Z - Local primary was 11 commits behind origin/main (`1641da6d2`) - Without `refresh-before-decide` catching the staleness, the next substrate landing would have been a public PR retracting against already-resolved state Three mitigation patterns named in the rule (pick by context): 1. Isolated worktree off `origin/main`: `git worktree add --detach <path> origin/main` (default for ticks; composes with agent-worktree-hygiene `--detach` discipline) 2. `git show origin/main:<path>` for ad-hoc single-file inspection without checkout 3. ff-promote local HEAD — ONLY when the checkout is the agent's own, never the operator's primary Substrate-inventory step performed per verify-existing-substrate- before-authoring (PR #5131 — only visible via `git show origin/main:` because local was stale): existing partial coverage at otto-channels-reference-card.md ID-allocation section names this for `find docs/backlog -name "B-*.md"` queries. This extension generalizes the principle to any working-tree file read post-fetch + lands it on the refresh-before-decide surface where it auto-loads at every cold-boot. Files: - .claude/rules/refresh-before-decide.md (+69 lines: new section "git fetch updates refs but NOT working-tree files (post-fetch read trap)" + 3-pattern mitigation + 2026-05-26T10:08Z anchor + 5 composes_with citations) - docs/hygiene-history/ticks/2026/05/26/1008Z.md (+151 lines: full tick trace including the catch, the verify-before-defer composition, the substrate-inventory step, visibility signal) Composes with: - refresh-before-decide.md (existing 28-line rule extended) - verify-existing-substrate-before-authoring.md (PR #5131) - otto-channels-reference-card.md (ID-allocation narrow precedent) - agent-worktree-hygiene-never-hold-main-never-step-on-operator-cleanup-on-pr-merge.md - refresh-world-model-poll-pr-gate.md (origin/main over FETCH_HEAD) - dep-pin-search-first-authority.md (sibling at version-pin scope) - codeql-no-source-on-docs-only-pr-is-broken-commit-canary.md (verify-before-defer composition 8th-or-9th anchor) - PR #5128 — the fix whose phantom-drift catch this tick prevented Co-Authored-By: Claude <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This was referenced May 26, 2026
This was referenced May 26, 2026
AceHack
added a commit
that referenced
this pull request
May 26, 2026
* docs(archive): preserve discussion for PR #5134 * docs(archive): fix broken .claude/rules/ relative links in PR-5134 archive The archive file lives at `docs/pr-discussions/`; the inline links used `.claude/rules/...` which from that location resolves to `docs/pr-discussions/.claude/rules/...` (does not exist). Repointed all 8 links to `../../.claude/rules/...` so they render correctly on GitHub. Per `.claude/rules/blocked-green-ci-investigate-threads.md` verify-before-fix discipline: direct line inspection confirmed both Copilot findings on PR #5206 (lines 45 + 56 + 6 more) were legitimate; fix applied. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Lior <lior@zeta.dev> Co-authored-by: Otto <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends
.claude/rules/refresh-before-decide.mdwith a new section naming the post-fetch working-tree read trap:git fetch origin mainupdatesrefs/remotes/origin/mainbut does NOT promote local HEAD; subsequent file reads through working-tree paths see STALE files, and substrate authored against that state is a phantom catch.This tick's session IS the empirical anchor: local primary checkout was 11 commits behind
origin/mainat 10:08Z (local2774fef5avs origin1641da6d2); readingtools/alignment/filter_gate_log.ts+.test.tsvia the working tree made PR #5128 (merged 08:22Z, 1h 46min earlier) look unfixed. Therefresh-before-decidediscipline caught the staleness viagit rev-parse HEADvsgit rev-parse origin/mainmismatch before any phantom-drift substrate landed.Three mitigation patterns
origin/main(default for agent ticks):git worktree add --detach <path> origin/main— composes withagent-worktree-hygiene--detachdiscipline (never holdmainref in agent worktrees).git show origin/main:<path>— cheapest option for ad-hoc single-file inspection without checkout.Substrate-inventory step (per verify-existing-substrate-before-authoring)
Searched
.claude/rules/+memory/for:git fetch,FETCH_HEAD,local HEAD stale,ff-only,fast-forward,git show origin/main,stale local. Found existing partial coverage atotto-channels-reference-card.mdID-allocation section ("do NOT usefind docs/backlog -name 'B-*.md'on the local worktree...") andrefresh-world-model-poll-pr-gate.md("Preferorigin/mainoverFETCH_HEAD"). Conclusion: principle exists at NARROW scope (ID-allocation queries / FETCH_HEAD race); the general working-tree-file-read corollary is implicit but not explicit on a cold-boot-loaded rule surface. Disposition: extend (not mint parallel) per the verify-existing-substrate rule — landed insiderefresh-before-decide.mdso it auto-loads at every Otto cold-boot.What changed
.claude/rules/refresh-before-decide.md(+69 lines): new "## `git fetch` updates refs but NOT working-tree files (post-fetch read trap)" section + 3-pattern mitigation + 2026-05-26T10:08Z empirical anchor + citation to existing partial coverage + 5 composes_with entriesdocs/hygiene-history/ticks/2026/05/26/1008Z.md(+151 lines): full tick trace — refresh-found-stale, verify-before-defer composition (9th anchor: 0 stuck procs + 0 peer procs + dotgit-clean → isolated worktree clean), substrate-inventory step, visibility signalTest plan
git worktree add --detach /private/tmp/zeta-otto-cli-refresh-extend-1008z origin/main→ exit=0, HEAD=1641da6d2, ls-tree=61, status=0, noindex.lockzeta-expected-branch.md(git branch --show-currentmatchedZETA_EXPECTED_BRANCH)codeql-no-source-on-docs-only-pr-is-broken-commit-canary.md:ls-tree HEAD~1 = HEAD = 61timeout --kill-after=5s 90sper B-0615 disciplineComposes with
.claude/rules/refresh-before-decide.md— the rule this PR extends.claude/rules/verify-existing-substrate-before-authoring.md— PR rule: verify-existing-substrate-before-authoring — sibling to dep-pin-search-first-authority (3-anchor empirical evidence 2026-05-26) #5131; the substrate-inventory rule used here.claude/rules/agent-worktree-hygiene-never-hold-main-never-step-on-operator-cleanup-on-pr-merge.md—--detach origin/maindiscipline.claude/rules/refresh-world-model-poll-pr-gate.md— "Preferorigin/mainoverFETCH_HEAD" + saturation tiers.claude/rules/otto-channels-reference-card.md— ID-allocation narrow-scope precedent.claude/rules/dep-pin-search-first-authority.md— sibling rule at version-pin scope; same "Otto-defaults-to-plausible-but-unverified" root cause class🤖 Generated with Claude Code