fix(usage): count compressed Codex rollouts#25453

merged2
main
maria/takeover-pr-22590
opened7d agobyMmaria
View on GitHubTwo-way sync enabledPR last imported 3d ago

Problem

Codex usage skips .jsonl.zst rollouts, so compressed sessions disappear from totals.

Change

Discover compressed JSONL and stream Node's native zstd decoder into the existing parser. Keep unchanged-file caching; reread changed compressed snapshots from the start because decoded offsets cannot resume compressed bytes. The original implementation already fits this scope, so its three-file patch is preserved without additional machinery.

Scope and approval

This is an obvious focused bug fix under CONTRIBUTING.md: the existing usage capability omits the compressed form of the same Codex transcripts it already counts. It adds no workflow, provider configuration, accounting contract or UI. Maria explicitly requested this takeover of GitHub #22590; no completed human accounting approval is claimed. Human approval remains required before merge.

Verification

Passed through Blacksmith: all 95 tests across the transcript reader, UsageService, Codex usage parser and scan cache. All six compressed regressions fail against current main. vp run check:changed passed format, lint, both knip checks, GraphQL, affected typechecks and 59 adjacent tests. Two independent GPT-6.1-Sol code reviews approved the identical source tree without findings.

Real Linux Chrome with the running dev server and matching synthetic Codex-format files: main reports 270 tokens / 1 session; this patch reports 600 tokens / 2 sessions. The plain-file control remains included. No UI code or wire contracts change; web, desktop and mobile consume the same server totals.

Unverified: real Codex-produced compressed files, installed Electron/mobile clients, macOS/Windows and remote/relay/tunnel execution. Node's existing truncated/concatenated zstd-frame limitations remain. This is a focused bug fix; human accounting approval remains required.

Evidence

Before, current main with plain and compressed fixtures:

before: compressed session omitted, 270 tokens and one session

After, the same files with this fix:

after: compressed session counted, 600 tokens and two sessions

Takeover

Replaces #22590, with thanks to @Trench-Monster for the original implementation.

Built with GPT-6.1-Sol in the Codex harness on T3 Code.

Checks

21 successful · 18 skipped
All checks passed
e7d118a

Added 1 commit

  • fix(usage): count compressed Codex rollouts19878a3
Synced from GitHub

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — This focused fix adds native zstd support for compressed Codex transcripts and preserves cache behavior while leaving plain transcript handling unchanged. Because it changes token, cost, and session accounting totals, the accounting-sensitive impact warrants human review.

No code changes detected at e7d118a. Prior analysis still applies.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire5.0 KiB5.0 KiB−6 B (−0.1%)6.8 KiB✅
CodexThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
CodexLive turn WebSocket wire1.3 KiB1.2 KiB−6 B (−0.5%)2.0 KiB✅
CodexLive turn WebSocket decoded21.6 KiB21.6 KiB0 B (0.0%)24.4 KiB✅
CodexLive turn messages220 (0.0%)8✅
ClaudeTotal thread wire5.0 KiB5.1 KiB+35 B (+0.7%)6.8 KiB✅
ClaudeThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
ClaudeLive turn WebSocket wire1.2 KiB1.3 KiB+35 B (+2.8%)2.0 KiB✅
ClaudeLive turn WebSocket decoded21.9 KiB21.9 KiB+41 B (+0.2%)24.4 KiB✅
ClaudeLive turn messages12+1 (+100.0%)8✅

Baseline: f58fad0 · PR result: e7d118a · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Synced from GitHub

Review in Change Stack →

Walkthrough

Transcript discovery now includes .jsonl.zst files. The reader decompresses them and reads from the beginning rather than resuming by byte offset. Tests cover discovery, parsing, corrupt input, duplicate rollout handling, updated totals, and repeated reads after a service restart.

Changes: Compressed transcript usage

Layer / File(s)Summary
Discover and read compressed transcripts
apps/server/src/usage/usageTranscriptReader.ts, apps/server/src/usage/usageTranscriptReader.test.ts
Discovery includes compressed JSONL files. The reader decompresses them and disables byte-offset resume for compressed input. Tests cover discovery, parsing modes, malformed records, tails, and corrupt input.
Verify usage aggregation
apps/server/src/usage/UsageService.test.ts
Tests check usage totals across plain and compressed rollouts, duplicate handling, updated compressed data, repeated reads, and service restart results.

Priority: External image Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

mermaid
1sequenceDiagram
2 participant UsageService
3 participant listTranscriptFiles
4 participant readTranscriptRecords
5 participant ZstdDecompress
6 UsageService->>listTranscriptFiles: Discover transcript files
7 UsageService->>readTranscriptRecords: Read compressed transcript
8 readTranscriptRecords->>ZstdDecompress: Decompress Zstandard stream
9 ZstdDecompress-->>readTranscriptRecords: Return decompressed records

Possibly related issues

  • pingdotgg/t3code#21755: This PR addresses compressed rollout discovery and decoding in usage totals. The issue describes the same format gap in the separate session import pipeline.

Possibly related PRs

  • pingdotgg/t3code#20276: Changes the usage aggregation and scan-cache path that this PR tests with compressed records.
  • pingdotgg/t3code#21666: Changes Codex transcript discovery, which determines which rollouts enter usage totals.
  • pingdotgg/t3code#21664: Changes Codex usage compatibility rules in the accounting flow that processes compressed rollouts.

Suggested reviewers: juliusmarminge, tris203

Merge Risk: External image Minimal · up to e7d11

No merge-blocking issue was identified. Human accounting approval remains outstanding.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title is concise, specific, and accurately describes the primary change: counting compressed Codex rollouts.
Description checkPassedThe description includes the required Problem, Change, Scope and approval, and Verification sections. It explains the focused bug fix, testing results, evidence, limitations, and remaining human appro…
Linked Issues checkPassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes checkPassedCheck skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description includes the required Problem, Change, Scope and approval, and Verification sections. It explains the focused bug fix, testing results, evidence, limitations, and remaining human approval requirement.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

Verified as-is at 19878a3a5f6a3b83b033ba08c546d31644d49281 on this Linux Boat VM. No source changes or pushes were needed.

  • Installed and ran github/main (f17c9d202b38ea9a009a2d6dc3932e212bad4c24) in ../main, then stopped it before running the exact PR head. Only one dev server ran at a time, with isolated app state and an isolated Codex home.
  • Used the repo Playwright dependency and /usr/bin/google-chrome to add the real repository through the app, create threads, select Codex gpt-6.1-sol, and complete real turns through the local proxy. No synthetic transcript records, mocks, fixtures, or demo provider were used.
  • Created two real Codex rollouts. Both plain files counted as 38,682 tokens / 2 sessions. Compressed the first completed rollout using native zstd, verified a byte-identical round trip, and removed its plain copy. With these same files, a cold usage scan on main counted only 19,341 tokens / 1 session. The PR counted 38,682 tokens / 2 sessions, including the compressed rollout. Screenshots below use matching transcript data and the same viewport and usage settings.
  • Main retains previously scanned deleted transcripts, so its warm cache initially masked the bug. To reproduce first discovery, stopped main, moved only its isolated usage cache aside, and restarted it. No app database records were edited.
  • On the PR, a new real turn added a third session. Restoring the first rollout alongside its compressed copy did not double count it: 57,613 tokens / 3 sessions. A follow-up real turn appended to the third plain rollout; Refresh usage showed 76,579 tokens / 3 sessions / 4 usage records, matching the actual rollout token events. Repeated refreshes and a dev-server restart preserved those totals.
  • The existing reader, UsageService, Codex parser, and scan-cache tests passed through Blacksmith: 4 files / 95 tests. CI has 0 failing or pending checks (21 successful, 7 skipped, 1 neutral). No new test files were added.

Short runtime transcript, from real client WebSocket usage responses:

text
1main cold: scannedFiles=1 distinctSessions=1 input=19332 output=9 total=19341
2PR cold: scannedFiles=2 distinctSessions=2 input=38664 output=18 total=38682
3PR + duplicate + follow-up:
4 scannedFiles=4 distinctSessions=3 records=4
5 uncachedInput=30075 cachedInput=46464 output=40 total=76579
6PR restart: identical token totals, records=4, distinctSessions=3

Before, main omits the compressed real rollout:

main: one session and 19.3k tokens with the compressed rollout omitted

After, the exact PR head counts the same plain and compressed rollouts:

pr: two sessions and 38.7k tokens with the compressed rollout included

Real Codex follow-up, completion, and Usage refresh with both copies of the first rollout present:

real gpt-6.1-sol turn and refreshed usage showing 76.6k tokens across three sessions

The screenshots were inspected at full size. The recording has its startup frames trimmed; uploaded playback and seeking were checked in T3.

Not verified

  • Codex automatically producing or archiving .jsonl.zst files. The records came from real app-driven Codex turns; I manually compressed a completed rollout without changing its contents.
  • Native Electron, iOS, Android, macOS/Windows, and remote/relay/tunnel clients. This VM exercised the local Linux web client and its real server/provider path.
  • Account limits: the local proxy returned JSON-RPC -32600 for limits on main. Token/cost history worked. No claim is made about limits support.
  • Provider-native pricing accuracy or external billing reconciliation. This verifies transcript inclusion and token accounting against actual rollout events.

Added 1 commit

  • merge: sync main into compressed Codex rollout fixe7d118a

Note

Written by gpt-6.1-sol on behalf of Maria

Merged github/main (f58fad041621) into the existing head without rebasing. Head: e7d118a10770b159a874e4c5800dae7f39e29060. The only conflict was adjacent tests in UsageService.test.ts; both compressed-rollout and host-identity coverage are preserved. The patch against main remains three files, +187/-7.

Blacksmith passed vp run check:changed: format, lint, both knip checks, GraphQL, affected typechecks, and 62 tests. The nearby Codex parser and scan-cache suites passed another 36 tests. Two independent read-only reviewers approved this SHA without findings. No actionable existing bot findings required replies.

No provider/client browser scenario was rerun for this merge-only update. The earlier real-provider evidence above applies to the original head; it is not new-head runtime verification. CI for the new head is pending. Human accounting approval remains outstanding.