Repository navigation
fix(claude): scope message dedupe by session - #1661
Conversation
Fix duplicate Claude Gateway message identifiers without conflating events from separate sessions. Co-authored-by: Fluffy-Bunny-23 <[email protected]>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ccusage-guide | 4cfa019 | Commit Preview URL Branch Preview URL |
Aug 29 2026, 08:16 PM |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan provides up to 10 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughClaude usage deduplication now includes effective session IDs and timestamps. Distinct sessions that reuse message IDs remain separate, while duplicate writes and copied transcripts remain deduplicated. Session metadata propagates through daily usage entries. ChangesClaude session-aware deduplication
Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: ⚪ Minimal · up to The change scopes Claude Gateway message deduplication by session and preserves canonical daily records, with no actionable merge-blocking risk remaining beyond normal checks and review. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Linked Issues checkExplanation The changes satisfy issue Full details: Docstring CoverageExplanation Docstring coverage is 55.17% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 3 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Warning Some tools did not complete. Review the errors below. 🔧 Clippy (1.97.1)Clippy execution failed Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Important
The sidechain replay fallback can now leave valid /btw replays in the output when their timestamps differ from the parent, causing usage to be overcounted.
Reviewed changes
This review covers the Claude regular and daily deduplication changes, session identity propagation, regression tests, and adapter documentation.
- Session-scoped deduplication — Includes the effective serialized or path-derived session ID in regular and daily dedupe keys.
- Timestamp fallback — Uses timestamps for records without
requestIdso gateway records with reused message IDs remain distinct across sessions while same-session writes still collapse. - Daily propagation and indexing — Carries timestamps and session IDs through direct and
AgentProgressrecords and refreshes indexes when a parent replaces a sidechain replay. - Regression coverage and documentation — Adds fixture-backed tests for gateway sessions, copied transcripts, AgentProgress metadata, and parent replacement, plus documents the gateway behavior.
@v0 or keep the SHA fresh with Dependabot | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using GPT Luna (free via Pullfrog for OSS) | 𝕏
| ) -> bool { | ||
| entry.data.message.id.as_deref() == Some(message_id) | ||
| && loaded_entry_session_id(entry) == session_id | ||
| && entry.timestamp == timestamp |
There was a problem hiding this comment.
This adds timestamp equality to the message-only /btw fallback. That fallback handles a parent and sidechain replay with different request IDs; if the replay timestamp differs, the lookup misses and both usage entries survive, overcounting reports. Please keep timestamp in the exact no-request-ID identity, but preserve the previous message/session sidechain fallback across timestamp differences and add a regression for both regular and daily loaders.
Technical details
# Preserve `/btw` replay deduplication across timestamps
## Affected sites
- `rust/adapters/claude/src/lib.rs:258-261` — the message-only sidechain matcher now requires exact `TimestampMs` equality.
- `rust/adapters/claude/src/daily.rs:441-445` — the daily matcher applies the same restriction.
## Required outcome
- Keep session and timestamp scoping for entries with no `requestId`, but do not require timestamps to match when the message-only fallback reconciles a known parent with a sidechain replay carrying a different `requestId`.
- Add regression coverage for the same message and session with different request IDs and timestamps in both loaders.There was a problem hiding this comment.
All reported issues were addressed across 4 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
ccusage
@ccusage/ccusage-darwin-arm64
@ccusage/ccusage-darwin-x64
@ccusage/ccusage-linux-arm64
@ccusage/ccusage-linux-x64
@ccusage/ccusage-win32-x64
commit: |
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. Package runtime diagnosticsCompares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself. Fixtures: Claude
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures. Fixtures: Claude
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
ccusage performance comparisonPR SHA: This compares the PR package against the configured base package on the same CI runner. Package runtime diagnosticsCompares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself. Fixtures: Claude
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures. Fixtures: Claude
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
There was a problem hiding this comment.
ℹ️ No new issues found in this delta. The previously reported regular-loader
/btwreplay concern remains open in the existing review thread.
Reviewed changes
This incremental review covers the daily sidechain replay changes added after 7ac9de3.
- Added session-scoped replay matching — Used a separate message/session replay index so daily parent and sidechain records with different timestamps still collapse without crossing session boundaries.
- Propagated daily identity — Retained parsed timestamps and effective session IDs through direct and
AgentProgressentries. - Refreshed replacement indexes — Reindexed the daily entry after a parent replaced a sidechain replay and added regressions for timestamp differences, distinct sessions, requestless entries, and copied transcripts.
@v0 or keep the SHA fresh with Dependabot | Fix it ➔ | View workflow run | Using GPT Luna (free via Pullfrog for OSS) | 𝕏
ccusage performance comparisonPR SHA: This compares the PR package against the configured base package on the same CI runner. Package runtime diagnosticsCompares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself. Fixtures: Claude
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures. Fixtures: Claude
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. Package runtime diagnosticsCompares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself. Fixtures: Claude
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures. Fixtures: Claude
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
There was a problem hiding this comment.
ℹ️ No new issues found in this delta. The existing regular-loader
/btwreplay concern remains open.
Reviewed changes
This incremental review covers the follow-up changes since the previous Pullfrog review.
- Restored regular requestless dedupe — Removed timestamps from the regular exact dedupe identity so same-session records without
requestIdcontinue to collapse across timestamps. - Separated daily identity — Kept timestamps in daily exact dedupe keys while retaining timestamp-independent, session-scoped sidechain replay matching.
- Added regression coverage and documentation — Covered same-session requestless duplicates and documented the regular-versus-daily behavior.
@v0 or keep the SHA fresh with Dependabot | Fix it ➔ | View workflow run | Using GPT Luna (free via Pullfrog for OSS) | 𝕏
ccusage performance comparisonPR SHA: This compares the PR package against the configured base package on the same CI runner. Package runtime diagnosticsCompares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself. Fixtures: Claude
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures. Fixtures: Claude
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. Package runtime diagnosticsCompares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself. Fixtures: Claude
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures. Fixtures: Claude
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |

Summary
Validation
Fixes #1635
Summary by cubic
Scopes Claude Gateway message deduplication by session so distinct sessions that reuse a message ID are no longer collapsed, fixing cross-session usage undercounting.
requestId, the daily loader also includes the timestamp, while the regular loader still collapses same-session duplicates across timestamps.Written for commit 4cfa019. Summary will update on new commits.
Summary by CodeRabbit