Skip to content

Stop double-billing Claude session history after a restart - #1997

Merged
currentbits merged 2 commits into
mainfrom
coder/persist-verified-claude-session-accounti-b24666
Nov 11, 2026
Merged

currentbits merged 2 commits into
mainfrom
coder/persist-verified-claude-session-accounti-b24666

Conversation

@currentbits

Copy link
Copy Markdown
Owner

Closes #1961.

After a turn completes and the Claude CLI process is replaced (app restart, idle reap, model/effort change), the resumed process reports the session's restored cumulative total_cost_usd and modelUsage. Solenta subtracted from a zero baseline, so it re-billed history: the #1960 fixture recorded $0.05 / 26 inputs for a session that cost $0.04 / 16.

What changed

  • Checkpoint (electron/claude-usage.js): a versioned per-session record on the thread with the subtraction baseline plus the raw provider-reported totals, scoped by provider/account ref, remote/WSL target and CLAUDE_CONFIG_DIR. Normalized on load (store-migrate.js); old stores get none.
  • Proof before subtraction: the first cumulative result of a fresh --resume process is classified by exact per-model counter identities, never magnitude:
    • restored: some checkpoint model reads exactly checkpoint + this turn's observations, others monotone → subtract the checkpoint;
    • reset: every model reads exactly this turn's observations, or CLI < 2.1.277 → zero baseline (unchanged);
    • unknown (no/mismatched checkpoint, fork, ambiguous) → that turn's cost is marked unavailable (not zero), observed tokens still count, and warm deltas are exact again afterwards.
  • Runner (runner-provider-claude.js): hydrate only when session ID + scope match and it isn't a fork; write the checkpoint in the same tick/save as the ledger rows, and only while this handle still owns the session.

Deviation from the issue: there is no no-generation handshake in Solenta, so exact counter identity on the first result is the proof used instead.

Tests

  • New electron/test/claude-resume-accounting.test.js (16): restore/reset/unknown, legacy reset above and below the old total, partial pre-result usage, malformed checkpoints, replay, captured 2.1.283 frames (classify as reset), and real runner + Store reload across three app lifetimes, model respawn, old store and account-scope mismatch. Resume now records $0.03/14, then $0.04/16, in thread usage, daily spend and per-model cells.
  • claude.test.js / budget-spend.test.js fakes now declare claude_code_version: 2.1.276: a version-less, cost-only resumed result is no longer assumed to be a reset.

🤖 Generated with Claude Code

#1961)

A fresh --resume process restores the session's cumulative totals, and
Solenta billed them again from a zero baseline. Keep a versioned per-session
checkpoint on the thread (scoped by account, target and config home) and
subtract it only when the first resumed result proves restoration through
exact per-model counter identities. Unproven resumes report the turn's cost
unavailable instead of charging history; warm deltas resume afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-11T10:26:48.903815Z 6887c98 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@currentbits
currentbits merged commit c8c8581 into main Nov 11, 2026
14 checks passed
@currentbits
currentbits deleted the coder/persist-verified-claude-session-accounti-b24666 branch November 11, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Persist verified Claude session accounting checkpoints across process restarts

1 participant