◉CLAUDE LABJP
●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/Claude Code
⟐ Claude Code/2026-07-09Advanced

Is the Draft That Passed the Gate the Same One You Published?

In unattended pipelines, the file your quality gate inspected and the file you actually publish can quietly diverge. Here is a digest-bound gate receipt design, with working code and measured results from 180 days of running it.

claude-code132autonomous-operationsCI/CD19quality-gatesproduction111

✦ Premium Article

One morning, the unattended pipeline I run overnight published something it should have refused to publish.

The execution log showed the quality gate printing a clean pass. A few lines below, git push reported success. Nothing was red. And yet the published text contained exactly the phrasing the gate was written to reject.

I stared at the screen for a while before it landed. The file the gate had read and the file git add had picked up shared a path, but not contents. In the seconds between the gate finishing and the push starting, another process had rewritten it.

No errors. Every step "succeeded." That quiet is the hardest part of running things unattended.

What Slips In Between Checking and Publishing

This is a textbook TOCTOU problem — time-of-check to time-of-use. A filesystem path is a reference, not a value. It does not promise to hold the contents you inspected a moment ago.

In my own pipelines, four distinct paths caused it.

Entry pointWhat happensWhy it hides
Regeneration The agent rewrites the draft to fix a gate violation, then proceeds to push without re-running the gate The old passing result is still sitting in the log
Auto-fix tooling An integrity checker's --fix mode rewrites files and leaves .bak siblings behind git add -A sweeps up files nobody inspected
Stale temp files A write to a fixed-name temp file fails, and last run's contents get read instead The failed write never propagates a non-zero exit
Concurrent processes Another scheduled run touches the same working directory Each run looks successful in isolation

None of these are fixed by making the gate stricter. The problem is not inside the gate. It lives in the gap between the gate and the publish.

The Receipt Idea: Bind the Verdict to the Bytes

The fix I settled on was to stop letting the gate's verdict stand on its own, and instead bind it to a digest of the contents it inspected.

When every gate passes, the pipeline emits a small JSON document containing:

  • The relative path and sha256 digest of each inspected file
  • The name of each gate that ran, plus a digest of the gate script itself
  • The issue time, recorded on both a wall clock and a monotonic clock
  • The pipeline run ID

I call this a receipt. Immediately before publishing, the pipeline reads the receipt and recomputes every digest from disk. If a single byte has moved, nothing gets published.

The key property is that a receipt is issued against contents, not against paths. Paths get rewritten. Digests do not lie.

✦

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
✦Get working code for issuing and verifying a gate receipt that binds pass/fail results to the sha256 digest of every inspected file
✦Understand why batching verification and publishing into one shell invocation erases the observation point, and learn to find the non-zero exits your pipeline is swallowing
✦Learn the four ways a file changes after passing a gate — regeneration, auto-fix, stale temp files, concurrent processes — and how to close each one
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-05-02
Designing Zero-Downtime Database Migrations with Claude Code: A Production Operations Guide
A production guide to designing zero-downtime database migrations with Claude Code. Covers Expand-Contract, NOT NULL additions, renames, backfills, and subagent reviews — practical patterns that survive real production traffic.
⟐ Claude Code2026-04-29
Observability for Claude Code with OpenTelemetry — A Production-Grade Tracing Guide for Agentic Workflows
Trace Claude Code agent runs end to end with OpenTelemetry. Hook integration, per-tool spans, MCP propagation, cost attribution, and sampling patterns that survive thousands of runs per day.
⟐ Claude Code2026-04-24
Debugging Claude Code Hooks in Production — Where to Start When Logs Are Missing
Your Claude Code hooks work locally but go silent in production. Here is the three-layer observability pattern I use on real projects, plus a 60-second minimal reproduction recipe for isolating failures.