Stale local clones never updated: preflight false-negatives (CLAUDE.md) + work runs on ancient code #226

Closed
opened 2026-06-24 19:35:18 +00:00 by igor · 1 comment
Collaborator

Symptom

Filed an Agent issue on joshtronic/porksicle.com (#43). The agent blocked it with "CLAUDE.md is missing at the repo root" — but CLAUDE.md is present on origin/master (and has been since early in the project).

Root cause: stale local clone, never updated

The agent's clone at ~/.local/state/agent/repos/joshtronic/porksicle.com is pinned at the initial commit (c059255 "Initial commit") and was never fetched/reset since it was first cloned. CLAUDE.md (and ~everything else — the repo is ~100 commits past c059255) is absent in that snapshot.

The visible bug is an API-vs-clone inconsistency:

  • Validation (architecture step 4) checks the live repo via the Forgejo APICLAUDE.md present → passes, so the issue is discovered + claimed.
  • Preflight (bin/tick.sh ~L3416, [ ! -f "$REPO_PATH/CLAUDE.md" ]) checks the stale local clone → file absent → blocks with the misleading message.

Deeper problem: even if CLAUDE.md weren't the tripwire, the worktree (step 14) is cut from the stale clone, so the agent would work on a months-old codebase. Architecture step 12 only clones if missing and never updates an existing clone.

Fix

Before preflight/work — in the claim/clone step (around where default_branch / R_BASE is resolved, tick.sh ~L3293) or just before the worktree — sync the clone to the remote default-branch tip, e.g.:

git -C "$CLONE" fetch --prune origin
git -C "$CLONE" reset --hard "origin/$DEFAULT_BRANCH"

(or a fast-forward). That fixes both the false CLAUDE.md negative and the work-on-stale-code problem, for every repo, not just this one.

Impact / repro

Any repo whose local clone predates its current HEAD. joshtronic/porksicle.com#43 is blocked by this right now. Workaround to unstick a specific repo: git -C <clone> fetch origin && git -C <clone> reset --hard origin/<default_branch>.

## Symptom Filed an `Agent` issue on `joshtronic/porksicle.com` (#43). The agent blocked it with *"CLAUDE.md is missing at the repo root"* — but `CLAUDE.md` **is** present on `origin/master` (and has been since early in the project). ## Root cause: stale local clone, never updated The agent's clone at `~/.local/state/agent/repos/joshtronic/porksicle.com` is pinned at the **initial commit** (`c059255` "Initial commit") and was never fetched/reset since it was first cloned. `CLAUDE.md` (and ~everything else — the repo is ~100 commits past `c059255`) is absent in that snapshot. The visible bug is an **API-vs-clone inconsistency**: - **Validation** (architecture step 4) checks the *live* repo via the Forgejo **API** → `CLAUDE.md` present → **passes**, so the issue is discovered + claimed. - **Preflight** (`bin/tick.sh` ~L3416, `[ ! -f "$REPO_PATH/CLAUDE.md" ]`) checks the **stale local clone** → file absent → **blocks** with the misleading message. Deeper problem: even if CLAUDE.md weren't the tripwire, the worktree (step 14) is cut from the stale clone, so the agent would **work on a months-old codebase**. Architecture step 12 only clones *if missing* and never updates an existing clone. ## Fix Before preflight/work — in the claim/clone step (around where `default_branch` / `R_BASE` is resolved, tick.sh ~L3293) or just before the worktree — sync the clone to the remote default-branch tip, e.g.: ``` git -C "$CLONE" fetch --prune origin git -C "$CLONE" reset --hard "origin/$DEFAULT_BRANCH" ``` (or a fast-forward). That fixes both the false CLAUDE.md negative and the work-on-stale-code problem, for every repo, not just this one. ## Impact / repro Any repo whose local clone predates its current HEAD. `joshtronic/porksicle.com#43` is blocked by this right now. Workaround to unstick a specific repo: `git -C <clone> fetch origin && git -C <clone> reset --hard origin/<default_branch>`.
Author
Collaborator

Resolved by #227 (merged) -- same bug, independently diagnosed. The API-vs-clone inconsistency you pinned down is exactly right, and porksicle.com#43 was the live casualty.

Preflight false-negative: fixed. #227 changes preflight to read CLAUDE.md from origin/$PR_BASE (the ref the worktree is actually carved from) via a fetch + git cat-file -e, instead of the stale clone working tree. Verified on the real clones: porksicle.com and devopsafterdark.com flip BLOCK -> PASS, while a genuinely-missing repo (flipflopfrenzy.com) correctly stays blocked.

On the "deeper problem" (work runs on ancient code): that part is actually not a bug. Every worktree -- issue work (tick.sh L3441), maintenance (L1281), PR review (L2824) -- is cut from origin/<ref> (git worktree add ... "origin/${PR_BASE}"), never from the clone's working tree. The fetch refreshes that ref, so work always runs on current code. The stale clone checkout was only ever read by that one preflight -f test.

On the proposed git reset --hard origin/$DEFAULT_BRANCH: went surgical ("read origin/ref") instead, because the clone is a deliberate fetch-only anchor (see CLAUDE.md gotchas) -- every surface carves a disposable worktree off origin/<ref> and nothing should mutate the clone's working tree (a reset --hard would fight the worktree model). Reading the ref we already use keeps that invariant.

Closing as fixed by #227. Good catch -- we landed on the same bug from opposite ends.

Resolved by #227 (merged) -- same bug, independently diagnosed. The API-vs-clone inconsistency you pinned down is exactly right, and `porksicle.com#43` was the live casualty. **Preflight false-negative: fixed.** #227 changes preflight to read `CLAUDE.md` from `origin/$PR_BASE` (the ref the worktree is actually carved from) via a fetch + `git cat-file -e`, instead of the stale clone working tree. Verified on the real clones: `porksicle.com` and `devopsafterdark.com` flip BLOCK -> PASS, while a genuinely-missing repo (`flipflopfrenzy.com`) correctly stays blocked. **On the "deeper problem" (work runs on ancient code):** that part is actually not a bug. Every worktree -- issue work (`tick.sh` L3441), maintenance (L1281), PR review (L2824) -- is cut from `origin/<ref>` (`git worktree add ... "origin/${PR_BASE}"`), never from the clone's working tree. The fetch refreshes that ref, so work always runs on current code. The stale clone checkout was only ever read by that one preflight `-f` test. **On the proposed `git reset --hard origin/$DEFAULT_BRANCH`:** went surgical ("read origin/ref") instead, because the clone is a deliberate fetch-only anchor (see CLAUDE.md gotchas) -- every surface carves a disposable worktree off `origin/<ref>` and nothing should mutate the clone's working tree (a `reset --hard` would fight the worktree model). Reading the ref we already use keeps that invariant. Closing as fixed by #227. Good catch -- we landed on the same bug from opposite ends.
igor closed this issue 2026-06-24 19:45:12 +00:00
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
joshtronic/igor#226
No description provided.