Skip to content

rule: refresh-before-decide extends to working-tree reads — 1008Z empirical anchor caught phantom PR #5128 drift#5134

Merged
AceHack merged 1 commit into
mainfrom
otto-cli/refresh-extends-working-tree-reads-1008z-2026-05-26
May 26, 2026
Merged

rule: refresh-before-decide extends to working-tree reads — 1008Z empirical anchor caught phantom PR #5128 drift#5134
AceHack merged 1 commit into
mainfrom
otto-cli/refresh-extends-working-tree-reads-1008z-2026-05-26

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented May 26, 2026

Summary

Extends .claude/rules/refresh-before-decide.md with a new section naming the post-fetch working-tree read trap: git fetch origin main updates refs/remotes/origin/main but 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/main at 10:08Z (local 2774fef5a vs origin 1641da6d2); reading tools/alignment/filter_gate_log.ts + .test.ts via the working tree made PR #5128 (merged 08:22Z, 1h 46min earlier) look unfixed. The refresh-before-decide discipline caught the staleness via git rev-parse HEAD vs git rev-parse origin/main mismatch before any phantom-drift substrate landed.

Three mitigation patterns

  1. Isolated worktree off origin/main (default for agent ticks): git worktree add --detach <path> origin/main — composes with agent-worktree-hygiene --detach discipline (never hold main ref in agent worktrees).
  2. git show origin/main:<path> — cheapest option 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 (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 at otto-channels-reference-card.md ID-allocation section ("do NOT use find docs/backlog -name 'B-*.md' on the local worktree...") and refresh-world-model-poll-pr-gate.md ("Prefer origin/main over FETCH_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 inside refresh-before-decide.md so 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 entries
  • docs/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 signal

Test plan

Composes with

🤖 Generated with Claude Code

… 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>
Copilot AI review requested due to automatic review settings May 26, 2026 10:15
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@AceHack AceHack enabled auto-merge (squash) May 26, 2026 10:15
@AceHack AceHack merged commit cd98323 into main May 26, 2026
28 of 29 checks passed
@AceHack AceHack deleted the otto-cli/refresh-extends-working-tree-reads-1008z-2026-05-26 branch May 26, 2026 10:17
@AceHack AceHack review requested due to automatic review settings May 26, 2026 10:36
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant