CLAUDE LABJP
VERSION — v2.1.227 landed on August 10 with no new features, just fixes around plan detection and CI behaviorAUTO — Two days remain until August 14, when auto mode becomes the default in Claude Code for Pro, Max, and TeamCI — Bash commands no longer fail across the board under claude-code-action with allowed_non_write_users on GitHub-hosted runnersBILLING — Sessions started with an expired token could misread your plan and nudge Max users toward usage credits; that is now fixedSUNSET — The legacy Workbench and the experimental prompt tool APIs retire on August 17, five days outPRICE — Sonnet 5 promo pricing at $2/$10 per Mtok runs through August 31, moving to $3/$15 on September 1VERSION — v2.1.227 landed on August 10 with no new features, just fixes around plan detection and CI behaviorAUTO — Two days remain until August 14, when auto mode becomes the default in Claude Code for Pro, Max, and TeamCI — Bash commands no longer fail across the board under claude-code-action with allowed_non_write_users on GitHub-hosted runnersBILLING — Sessions started with an expired token could misread your plan and nudge Max users toward usage credits; that is now fixedSUNSET — The legacy Workbench and the experimental prompt tool APIs retire on August 17, five days outPRICE — Sonnet 5 promo pricing at $2/$10 per Mtok runs through August 31, moving to $3/$15 on September 1
Articles/Claude Code
Claude Code/2026-06-24Advanced

I Watched an Agent Try to Fix a File It Had Already Fixed — Stale Shallow Clones and Refreshing Before You Decide

An unattended agent tried to re-fix a file it had already fixed. The cause was a days-old shallow clone it kept reading. Here is how to detect that staleness numerically and re-clone only before decisions.

Claude Code216git17automation101cloneidempotency6

Premium Article

I was reading the logs of a pipeline that runs unattended when I stopped. The agent was trying, with exactly the same intent, to fix something it had already fixed the day before. A diff was being produced, yet nothing new landed on the remote. Nothing failed, either. It was simply redoing work that had already been put to bed.

The cause was unglamorous. A shallow clone I kept under /tmp to make runs faster had quietly gone stale over several days. The agent read that old tree, concluded "this still needs fixing," and calmly started a second pass.

As an indie developer who touches several repositories on a fixed schedule every day, I have learned that this "silently aging clone" is a nastier opponent than it looks. Today I want to use that single incident to lay out a design that catches staleness as a number and re-clones only right before a decision.

It Tried to Fix a Place It Had Already Fixed

That day the agent was reusing the persistent clone, as usual. git pull --rebase had run, and the log showed no errors. Even so, the artifact it was about to generate was nearly identical to one published the day before.

A quick check on disk made the cause obvious. The persistent clone held 668 articles; re-fetching the remote showed 671. Three new pieces — added earlier by a different session — had never made it into the local tree. The HEAD commits disagreed, too. The agent never knew that "three of the 671 are new," so it kept judging from a 668-article world where the work "did not yet exist."

I had trusted pull completely at first, so for a while I looked in the wrong place. I suspected write permissions, then the network, and only at the end came back to the obvious truth: the tree I was reading was old.

"Can't Write" and "Is Old" Are Completely Different Failures

When you triage this kind of bug, the first thing worth separating is the failure class. They look alike, but the fixes are nothing alike.

SymptomTypical causeWhat actually helps
Push adds nothing (commit reports success)git identity unset, leftover index.lock, empty commitSet user.email/name before commit; judge success by comparing local==remote SHA
Permission denied on writeWorking dir owned by another user, disk fullFall back to a writable path, free up space
A diff exists, yet the verdict is "nothing to do"The clone you are reading is staleMeasure how far behind the remote you are before deciding, and re-clone if needed

This incident is the bottom row. The write path was healthy and permissions were fine. What was broken was the freshness of the read. No amount of "push says success but nothing landed" handling, or owner-mismatch fallback, reaches this failure. That is exactly why it deserves to be treated as its own distinct fault.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
How to compare local HEAD against remote HEAD with git ls-remote and report exactly how many commits behind you are before pushing
Separating a write-failure from a stale-read failure, and adding a re-clone check that targets only the second one
Building an idempotent unattended pipeline that confirms the artifact already exists before generating, so it stops duplicating work
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Claude Code2026-08-10
The Same rm -rf Was Recoverable in Ten Places and Unrecoverable in Five — Measuring Reversibility Before Auto Mode Becomes the Default
Auto mode becomes the default on Pro, Max and Team from August 14. It stops on operations judged irreversible, destructive, or outward-facing — but reversibility turned out to be a property of state, not of commands. Here is the probe and the measurements.
Claude Code2026-08-09
One Transient 401 Replaced My Long-Lived Token — Giving Credentials a Provenance Field
A shared credential file can lose its long-lived token to a single transient 401. I injected exactly one 401 into a 24-worker fleet, measured the blast radius, and compared a provenance guard against full isolation.
Claude Code2026-08-05
Passing the Request, Not the Secret — Where Sandbox Credential Masking Works and Where Substitution Breaks
Claude Code's sandbox credential masking lets processes read sentinel values while a proxy swaps in the real secret at send time. I rebuilt it as a minimal proxy and measured which auth schemes survive the swap, which break, and what happens when the secret rides in the body.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →