Claude Code is asked whether a payments release is safe to continue. It reads the deployment API and sees version v42 running. It reads the feature flag service and sees new_settlement_path: true. It reads the schema registry and sees settlement schema v7.

Every response is authentic. Every tool call succeeds. The resulting plan is still wrong.

Between the first and third reads, another deployment moves the service to v43, flips the flag, and begins a schema transition. The agent combines facts from before and after that change. It plans against a production state that never existed at one point in time.

This is a mixed-snapshot failure. More logging will tell you what Claude Code read, but a list of responses does not prove those responses belong together. Before the agent can use several external reads to justify a consequential action, the runtime needs a coherence rule and a read-set receipt.

Coherent read-set gate for Claude Code

Give each read a source version

A timestamp alone is weak evidence. Clocks drift, caches delay responses, and two services may publish at different speeds. Ask each source for a version that changes when the relevant state changes.

mcp_read:
  evidence_id: ev-deploy-104
  source: deployment-api
  query: service=payments-api environment=production-eu
  observed:
    release: v42
    commit: 8bc911d
  source_version: deploy-seq-9912
  observed_at: 2026-08-21T09:42:03.114Z
  cache_status: origin

The version does not have to use one global sequence. A deployment service might expose a release generation, a feature flag service an ETag, and a schema registry a subject version. What matters is whether the runtime can tell that a source changed during the read window.

If a source cannot expose a stable version, mark that limitation. Do not quietly turn 200 OK into evidence of freshness.

Open a consistency boundary before collecting evidence

For systems that support snapshot tokens or revision reads, request a boundary first and pass it into every compatible tool call.

read_boundary:
  boundary_id: rb-771
  opened_at: 2026-08-21T09:42:03.000Z
  environment: production-eu
  required_sources:
    - deployment-api
    - feature-flags
    - schema-registry
  max_collection_time_ms: 2500
  change_topics:
    - payments-api.release
    - new_settlement_path
    - settlement-event.schema

The boundary says which facts must agree and how long the runtime may spend collecting them. The change_topics list keeps the rule narrow. A documentation edit elsewhere should not invalidate a release check. A new payments deployment should.

Some platforms can provide a shared transaction or control-plane revision. Use it when available. If the services have independent revisions, subscribe to their change journals or perform a validation read after collection.

Close the read set with a validation pass

Suppose the runtime collects these three records:

collected_reads:
  - source: deployment-api
    evidence_id: ev-deploy-104
    version: deploy-seq-9912
    value: release-v42
  - source: feature-flags
    evidence_id: ev-flag-338
    version: flag-etag-a61
    value: new_settlement_path=true
  - source: schema-registry
    evidence_id: ev-schema-552
    version: subject-version-7
    value: settlement-event-v7

Before Claude Code plans a write, recheck the relevant versions or ask a control plane whether any named topic changed after rb-771 opened.

boundary_validation:
  boundary_id: rb-771
  checked_at: 2026-08-21T09:42:04.602Z
  changes_detected:
    - topic: payments-api.release
      previous: deploy-seq-9912
      current: deploy-seq-9913
    - topic: new_settlement_path
      previous: flag-etag-a61
      current: flag-etag-a62
  decision: reject_mixed_snapshot
  next_action: recollect_all_required_sources

Do not refresh only the two changed reads. The schema result may have been collected during the transition, and keeping it would create another mixture. Discard the full set and collect it again under a new boundary.

This resembles optimistic concurrency control. The reads are tentative until validation proves that none of the state they depend on changed during collection.

Write a coherent read-set receipt

The review packet should include one record that tells a reviewer whether the evidence was safe to combine.

coherent_read_set_receipt:
  receipt_id: crs-20260821-18
  run_id: claude-run-5508
  purpose: assess-payments-release
  boundary_id: rb-772
  opened_at: 2026-08-21T09:42:05.010Z
  closed_at: 2026-08-21T09:42:05.891Z
  evidence:
    - id: ev-deploy-105
      source_version: deploy-seq-9913
    - id: ev-flag-339
      source_version: flag-etag-a62
    - id: ev-schema-553
      source_version: subject-version-8
  validation:
    changed_topics: []
    cache_entries: 0
    collection_time_ms: 881
  decision: coherent
  valid_until: 2026-08-21T09:42:20.891Z

Bind the plan to receipt_id, then check the receipt again before any consequential tool call. Coherence at planning time does not grant permanent authority. If the environment changes or the receipt expires while the plan waits for approval, collect fresh evidence and re-plan.

This receipt belongs beside the evidence-linked tool trace and the final effect receipt. One explains why the action was proposed. The other proves what happened afterward.

Test transitions, caches, and partial refreshes

A clean run where nothing changes proves very little. Build eval fixtures around the awkward timing windows:

coherent_read_set_evals:
  - case: deployment_changes_between_first_and_last_read
    expect: reject_and_recollect_full_set
  - case: one_source_returns_cached_response
    expect: reject_cache_without_acceptable_freshness_proof
  - case: flag_changes_then_changes_back
    expect: reject_if_change_journal_crossed_boundary
  - case: validation_times_out
    expect: stop_without_consequential_action
  - case: only_changed_sources_are_refreshed
    expect: reject_partial_refresh
  - case: receipt_expires_during_human_review
    expect: recollect_and_replan_before_dispatch
  - case: unrelated_service_changes
    expect: preserve_receipt_when_dependencies_are_unchanged

The change-then-change-back case matters. Comparing final values alone can miss a transition that made an intermediate read unsafe. A journal sequence or generation counter catches it.

Run these fixtures with delay and cache injection at the MCP boundary. A unit test that hands the agent three static JSON objects cannot reproduce the race.

Stop before the plan hardens into action

Mixed snapshots are dangerous because the transcript looks unusually convincing. It contains real values from real systems, complete with timestamps and successful status codes. The error sits in the relationship between those values.

Record source versions, declare which reads must agree, validate the boundary, and issue one expiring receipt for the set. If coherence cannot be proved, Claude Code should stop and collect again. A plausible plan built from an impossible state is not production evidence.

Claude Code: Building Production Agents That Actually Work contains practical patterns for MCP boundaries, production evidence, replay, evals, rollback, and review packets around coding agents.