Claude Code investigates a billing bug on Tuesday afternoon. It reads the retry handler, follows the error path, inspects the tests, and proposes a six-file change. The plan makes sense, but the reviewer leaves approval until the next morning.

Overnight, another pull request moves the retry policy into shared middleware.

On Wednesday, the original session resumes. Its transcript still contains a confident explanation of the old design. Claude Code follows the approved plan, edits the files it selected yesterday, and adds tests around behavior that no longer lives there.

Nothing in the plan looks stale. The repository moved while the reasoning stayed still.

A plan is a decision made against a particular state. If that state changes, approval of the old plan should not authorize execution against the new one.

Claude Code plan freshness gate

attach repository evidence to the plan

A serious plan should say what Claude Code inspected and which state supported its conclusions. A timestamp alone is weak evidence. A plan from twenty minutes ago can already be stale in a busy repository, while yesterday’s plan may remain valid on an untouched branch.

Repository state is the useful clock.

Start with a record like this:

plan:
  id: billing-retry-fix-20260730-01
  task: BILLING-1842
  based_on:
    commit: 91d26c4
    branch: fix/billing-retry
    inspected_paths:
      - src/billing/retry.ts
      - src/billing/handler.ts
      - tests/billing/retry.test.ts
    dependency_contracts:
      - retry-policy-v3
  created_at: 2026-07-30T15:42:11Z
  expires_if:
    - branch_head_changes
    - inspected_path_changes
    - dependency_contract_changes
    - task_scope_changes

The commit and branch give the plan a clear source revision. The inspected paths show which evidence Claude Code used. For riskier work, record relevant configuration, generated schemas, imported modules, tool versions, permission policy, and the task definition as well.

This record does not prove the plan is complete. Claude Code may miss a dependency while investigating. It does make the reasoning reviewable. A reviewer can see whether the agent examined the authorization middleware, migration file, or deployment configuration that the proposed change depends on.

Approval should name the plan and its basis:

approval:
  plan_id: billing-retry-fix-20260730-01
  commit: 91d26c4
  allowed_paths:
    - src/billing/retry.ts
    - tests/billing/retry.test.ts
  allowed_commands:
    - npm test -- tests/billing/retry.test.ts
  valid_while:
    repository_and_task_state: unchanged

That is narrower than approving a general instruction such as “fix the retry bug.” General approval lets the agent reinterpret the work after its environment changes. A named plan against a named state creates a small contract.

run a freshness check before the first write

The freshness gate belongs immediately before mutation, not only when the session starts. Claude Code may spend fifteen minutes planning while another developer merges a change.

Load the approved plan.
Read the current branch head.
Compare the plan evidence with current repository and task state.

If relevant state is unchanged:
Execute inside the approved boundary.

If relevant state changed:
Expire the approval.
Inspect the changed code.
Produce a revised plan and a focused delta.
Request approval again.

If freshness cannot be proved:
Stop before writing.

The easiest rule is to invalidate the plan whenever the branch head changes. It is conservative and simple to audit. It can also cause needless replanning when someone edits an unrelated README.

A mature workflow can compare only the plan’s evidence boundary: inspected files, imported modules, generated contracts, relevant configuration, test fixtures, and task criteria. Use that narrower rule only when the dependency map is trustworthy. If the agent omitted an important dependency, a targeted check can preserve the original mistake.

For authorization, billing, schemas, migrations, and deployment logic, I would accept more false alarms. Replanning costs less than applying an old assumption to a protected boundary.

This extends the same discipline used for test evidence. A green check belongs to the exact candidate that produced it, as I covered in binding Claude Code evidence to a commit. A plan and its approval need the same attachment to state.

show what changed instead of replacing the plan quietly

When the freshness gate rejects a plan, preserve the original. Then show the reviewer why it expired and how the replacement differs.

freshness_check:
  original_commit: 91d26c4
  current_commit: b37aa10
  result: stale
relevant_changes:
  - path: src/billing/middleware/retry-policy.ts
    reason: retry ownership moved here
plan_delta:
  removed:
    - edit src/billing/handler.ts
  added:
    - inspect shared middleware contract
    - add integration coverage for retry headers
approval_status: required

The reviewer should not have to compare two long plans line by line. The delta should identify the repository change, the assumption it invalidated, and the actions added or removed from the proposal.

Do not let the revised plan inherit the old approval. The reviewer approved a particular route through a particular codebase. Once either changes, the decision needs another look.

A shadow run is useful here. Claude Code can inspect the new state and produce the revised plan without writing files or calling tools that create side effects. Review the delta first, then grant a fresh execution boundary.

treat the session transcript as cached observations

Long Claude Code sessions are useful because they preserve discoveries. They are risky for the same reason. A finding in the transcript can outlive the code, configuration, tool response, or policy it describes.

Statements such as “this handler owns retries” or “the test already covers duplicate delivery” are cached observations. Before one of those statements authorizes a write, recheck its source.

I would force replanning when:

  • the branch head changed after planning
  • an inspected file or imported dependency changed
  • generated code, a schema, or relevant configuration changed
  • the task criteria or allowed scope changed
  • the tool, model, or permission policy changed
  • the session crossed a handoff or a long pause
  • the agent cannot tie an important assumption to current evidence

The last case deserves a hard stop. Claude Code should not preserve momentum by inventing continuity. If it cannot establish which state supported an assumption, it should inspect again.

The free Claude Code production checklist helps define the task boundary, permissions, evidence, stop conditions, and review ownership before a plan can trigger changes.

make plan expiry part of the operating loop

Plan expiry is not a failed run. It means the workflow caught a change in the evidence before Claude Code acted on it. The agent can inspect the delta, revise its proposal, and return a smaller decision to the reviewer.

I wrote Claude Code: Building Production Agents That Actually Scale for engineers building this operating layer around Claude Code. It covers task contracts, scoped permissions, MCP tools, evals, observability, review packets, rollback, and release gates. The Kindle edition is available on Amazon.

When agents can reach protected enterprise systems, plan freshness is also a security concern. Securing Enterprise AI Agents covers identity, bounded authority, MCP governance, approval, revocation, and incident evidence. The Enterprise AI Agents in Production bundle joins the engineering and security models.

My rule is simple. A Claude Code plan carries the state that justified it. When that state changes, the plan becomes history, not permission.