Skip to content

Persist verified Claude session accounting checkpoints across process restarts #1961

Closed

Description

@currentbits

Proposed implementation, not built. Follow-up to completed investigation #1960; separate from #1945 / merged #1956 interrupted-turn accounting and Codex reconciliation. #1435 already fixes warm-process subtraction.

Confirmed fixture behavior on main 24119d5: completed native session turn costs .01; fresh process resumes saved session totals and reports .03 for a .02 new turn; warm follow-up reports .04 for .01. Real runner + Store reload records .05 instead of .04 and 26 inputs instead of 16. Old-model rows duplicate. Five isolated probes, exact native 2.1.283 static inspection and current primary docs support this compatibility failure. No live account billing regression was measured.

Minimal design:

  • Add a separate versioned Claude accounting checkpoint for the current native session. Key it by provider/account reference, execution target/config-home identity and session ID, plus explicit reset/fork provenance. A bounded record on the current thread is enough. Do not reuse Codex sessionUsageBaseline or build historical transcript aggregation.
  • Retain raw provider-reported total_cost_usd and sparse modelUsage snapshots separately from ledger deltas, with verified protocol scope and existing accounted/unknown observation reconciliation state. Never synthesize a baseline from thread lifetime totals, costByModel, model picker aliases, prices or transcripts.
  • Hydrate a fresh handle only when the checkpoint matches AND restoration of the same provider accounting epoch is established. Keep warm-process subtraction and old pre-2.1.277 process-reset semantics. Modern versions can also resume without a saved cost-state: version >=2.1.277 and next total magnitude are NOT sufficient proof. Verify a no-generation start-snapshot/reset capability or explicit launch provenance before trusting subtraction; this investigation does not establish a current Solenta handshake.
  • With no trustworthy migrated/imported/ambiguous resume baseline, retain raw session totals and mark cumulative-derived current-turn deltas unavailable; keep directly observed current-turn fields. Do not charge historical totals, silently call unknown cost zero, infer missing dollars, relabel unknown models or repair history. Later known warm deltas remain usable.
  • Persist checkpoint and corresponding ledger changes consistently in the same Store persistence unit, guarded by current run/session ownership. Normalize finite nonnegative numbers and sparse fields on load. Old stores migrate to no checkpoint. Preserve observed exact model IDs and provider-reported SDK totals.

Acceptance / migration and reload coverage:

  • Convert the investigation's known-fault assertions into expected-correct tests: after resume .03 / 14 total inputs; after warm follow-up .04 / 16. Assert thread, daily spend and original per-model ledgers; no old-model growth on resumed day.
  • Save/reload checkpoint across two app lifetimes; cover process replacement due to model/effort changes, repeated result replay and stale-run events. Keep exact model IDs independent of picker labels. Keep SDK payloads intact.
  • Old Store with existing usage and no checkpoint, malformed/sparse checkpoints, unknown model identity and already-accounted partial observations retain uncertainty/history without reconstruction.
  • Cover legacy/reset next-process totals below AND above the previous total, modern transcripts without saved cost-state, unknown version, new sessions, provider/account/remote-target changes, source-session forks and same-session explicit resets. No scope inference from amount magnitude alone.
  • Verify consistent checkpoint+ledger save/reload around process death. Do not claim recovery for unreported missing amounts.

Artifacts: research_notes/claude-resume-accounting/{README.md,fixtures.json,repro.cjs} on thread 1d6f2140-e5ee-4ba2-9f6b-97b4e1def5c6. Run with SOLENTA_AUDIT_ROOT pointing to a built isolated main checkout. All provider frames are synthetic or checked-in captured fixtures; no paid turns, real credentials or user setting changes allowed.

Primary docs: https://code.claude.com/docs/en/agent-sdk/cost-tracking#accumulate-costs-across-multiple-calls . Exact 2.1.283 native executable inspected SHA-256 d8cb1e5c79684cc12a8bfc813e3a2073406921b6245744b3009be3ab5651d21e. Internal 2.1.318 model_usage_since_last_result is optional and absent from 2.1.283 schema; do not assume it as a portable contract.

Activity

  1. currentbits commented on Nov 9, 2026

    @currentbits
    OwnerAuthor

    Coordinating #1980 (idle-child retention from #1959/PR #1966): using a locally generated process epoch with idempotent persisted contributions/source evidence. Will not hydrate a new process's native baselines from previous epochs or infer native session continuity. #1961's verified fresh-process handshake/provenance remains separate. Checkpoint + aggregates must share the authoritative Store envelope; thread side-file projection will be generation-safe.

  2. currentbits commented on Nov 9, 2026

    @currentbits
    OwnerAuthor

    Retention implementation (#1980) now stores versioned claudeProcessUsage entries keyed by a local process epoch: nativeSessionId, per-day contribution rows, numeric source identities/maxima and raw native model/USD reports with observation boundaries. Checkpoints, spend, model/day totals, thread totals and thread-day projections share the authoritative Store envelope (inline usage thread ledger for checkpoint-enabled stores). Fresh processes do not hydrate these counters; #1961's verified restoration/reset provenance remains required. All validation used fake CLIs and temporary stores.

  3. added and removed on Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions