Repository navigation
feat(usage): parse real Claude JSON receipts - #299
Conversation
Test-First: src-tauri/src/store/development_claude_usage.rs::real_claude_2_1_287_json_maps_observed_token_counters Test-First: src-tauri/src/store/development_claude_usage.rs::claude_json_without_usage_is_not_reported_instead_of_zero Test-First: src-tauri/src/store/development_claude_usage.rs::negative_or_missing_claude_counters_are_rejected Test-First: src-tauri/src/store/development_claude_usage.rs::claude_error_run_is_rejected_instead_of_zero Co-Authored-By: Codex GPT-5 <noreply@openai.com>
Test-First: src-tauri/src/store/development_claude_usage.rs::real_claude_2_1_287_json_maps_observed_token_counters Test-First: src-tauri/src/store/development_claude_usage.rs::claude_json_without_usage_is_not_reported_instead_of_zero Test-First: src-tauri/src/store/development_claude_usage.rs::negative_or_missing_claude_counters_are_rejected Test-First: src-tauri/src/store/development_claude_usage.rs::claude_error_run_is_rejected_instead_of_zero Co-Authored-By: Codex GPT-5 <noreply@openai.com>
No-Test: append-only session handoff Co-Authored-By: Codex GPT-5 <noreply@openai.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c914b586d0
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let Some(usage) = result.get("usage").filter(|value| value.is_object()) else { | ||
| return UsageReceipt::NotReported { |
There was a problem hiding this comment.
Reject malformed usage payloads
When a successful Claude response contains usage: null, an array, or a string because of schema drift or capture corruption, this filter follows the same branch as an absent field and returns NotReported. That state omits the capture digest and claims the result simply lacked usage, making malformed provider data indistinguishable from a legitimate missing report; distinguish an absent key from a present non-object value and reject the latter, with regression cases for these sibling forms.
AGENTS.md reference: AGENTS.md:L87-L89
Useful? React with 👍 / 👎.
| - Uncommitted: keine | ||
|
|
||
| ## 2026-10-04 16:36 — codex (codex/hq2-05b-p2-claude-probe, srv-hq2-05b-p2-claude-probe) | ||
| - Zusammenfassung: HQ2-05b package 2: real Claude 2.1.287 JSON probe, scrubbed fixture and pure fail-closed UsageReceipt parser; red-first commits ee4a010/5a3a94c; prepush and push hook green; draft PR #299; Tier B review and later route/store wiring pending. |
There was a problem hiding this comment.
Classify the store change as Tier A
This package changes files under src-tauri/src/store/, which the repository rules explicitly include in a serial seam, but this journal entry schedules only a Tier B review. That classification obtains one reviewer instead of the two cross-vendor reviewers required for seam changes, so reclassify the package as Tier A and record both review dispositions before accepting it.
AGENTS.md reference: AGENTS.md:L26-L32
Useful? React with 👍 / 👎.
| for field in [ | ||
| "input_tokens", | ||
| "cache_creation_input_tokens", | ||
| "cache_read_input_tokens", | ||
| "output_tokens", |
There was a problem hiding this comment.
Account for non-executor usage iterations
When a Claude run invokes the Advisor tool, the top-level usage counters cover executor iterations only, while the advisor's tokens are reported separately in usage.iterations[] entries of type advisor_message, as documented in the Anthropic Advisor usage contract. This loop always sums only the four top-level counters and marks the receipt measured, so such a run silently settles fewer tokens than it consumed and can incorrectly leave budget available; either account for the complete iteration breakdown without double-counting or reject unsupported iteration types until they can be measured.
Useful? React with 👍 / 👎.
|
Queued — the merge queue status continues in this comment ↓. |
|
@Mergifyio queue |
Merge Queue Status
This pull request spent 1 hour 1 minute 47 seconds in the queue, including 11 minutes 20 seconds running CI. Required conditions to merge
|
Claude Code liefert bei einem kleinen echten Lauf getrennte Token-Zähler und nennt das verwendete Modell. Der neue Parser übernimmt diese Zähler nur aus einem vollständigen erfolgreichen JSON-Ergebnis und erfindet bei Fehlern keine Null. Die Laufzeit-Anbindung an Route und Store bleibt bewusst einem späteren seriellen Paket vorbehalten.
Report
What changed
--output-format jsonrun. Session/result IDs and monetary values are redacted; no personal paths or account data are present.UsageReceipttype without route, capture, or store settlement wiring.2 + 1857 + 535 + 4to2398tokens.usagebecomes explicitnot_reported; missing, negative, non-integer, oversized, malformed, error, and nonzero-exit captures becomerejected, never zero.codex-exec-json-v1while this parser reportsclaude-print-json-v1.total_cost_usd, per-modelcostUSD, andmodelUsage. They are not guessed. The cost fields were present, but their values are redacted and they are not treated as subscription billing.Live probe
claude -p --output-format json --tools "" --strict-mcp-config --mcp-config '{"mcpServers":{}}' --no-session-persistence --safe-mode --model sonnet 'Reply with exactly OK.'claude --version, exit 0).claude-sonnet-5-5(modelUsagekey andcanonicalModel).input_tokens,output_tokens,cache_creation_input_tokens,cache_read_input_tokens; cost fields were also present.stream-jsonwas not probed: this parser consumes the single final result produced by--output-format json, and no Claude stream transport is wired in this package.Evidence
70308347998146bfa87478c03715041d575d409c(git fetch origin main; branch HEAD andorigin/mainmatched, exit 0).npm run dev:start-check— exit 0; 14.2 GB free RAM, 0 cargo builds. Provider-limit file was not supplied, as reported by the command.cargo test --manifest-path src-tauri/Cargo.toml store::development_budget::claude_usage::tests:: -- --nocaptureatee4a010— exit 101; four compiling tests failed against the explicit stub.cargo test --manifest-path src-tauri/Cargo.toml --bin projecta ...invocations forclaude_usage,usage_receipt, andcodex_usage— exit 0; 4 + 8 + 5 tests passed.bash scripts/ci/gates.sh lane prepushatc914b586d007e0f03cefa2ec6d0bdfa0bb642826— exit 0; log/tmp/prepush-hq2-05b-p2-claude-probe-final.log. Frontend 460/460, HQ 510/510, Rust 1709/1709; Clippy and red-first plan green.git push origin codex/hq2-05b-p2-claude-probe— exit 0; its pre-push gate also exited 0.git ls-remote origin refs/heads/codex/hq2-05b-p2-claude-probe— exit 0, remote SHAc914b586d007e0f03cefa2ec6d0bdfa0bb642826.c914b586d007e0f03cefa2ec6d0bdfa0bb642826.bash scripts/ci/secret-scan.shbefore each commit — exit 0.NICHT ABGEDECKT
#[cfg(windows)]tests or Windows Clippy arms; the real Windows lane first runs in the Mergify merge queue.stream-jsonevent parsing is not covered because it is not the transport under test.UsageReceipt; they remain intentionally unmapped. No subscription invoice or billed amount was verified.Review
Review: done, Tier A review requested by coordinator (candidate
c914b586d007e0f03cefa2ec6d0bdfa0bb642826).Review disposition
git diff origin/main...HEADin full. Findings: none survived. Checked and cleared: every non-success path (exit code, empty, >1 MiB, malformed/trailing JSON,is_error, missingtype/subtype) returnsRejected, never zero (development_claude_usage.rs:15-39); counters are separate Claude categories so summing cache tokens is correct (unlike Codex, where cached is a subset,development_codex_usage.rs:108);checked_addplus 1e9 cap (:56-66).glm-5.2:cloud, via.pa/review_transport.py, exit 0). Findings: none; verdict approve.UsageReceipttype and mirrors the existingcodex_usagemodule layout; no second pattern for store/lock access, IPC or events.Open points