Skip to content

fix(usage): retain complete scans when merging partial history - #954

Merged
rynfar merged 4 commits into
pylonfrom
codex/usage-scan-merge
Oct 1, 2026
Merged

rynfar merged 4 commits into
pylonfrom
codex/usage-scan-merge

Conversation

@rynfar

@rynfar rynfar commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

A newer partial or failed scan of a shared transcript directory can displace an older complete scan, reducing the displayed usage. This prefers complete scans, then partial scans, then failed scans; the newest scan wins within each status. A newer partial scan can add previously unseen day/hour/provider/model cells without replacing or recounting complete cells. Web and mobile recompute ownership within the selected environments.

This adapts the generic merge behavior from frozen T3 source e5a46d6c5d00b89afba5274a94d42428c8d79763 (#10409), checked at final bound 0fcd5f90611451cca842689faea53b5450c022da. Pylon retains its v8 contract, per-source buckets, full host/path/volume identity, unknown-volume separation, legacy attribution warnings, source/session ownership, pricing and mismatch behavior. Single-source legacy readings can supplement; ambiguous legacy multi-home totals keep their existing approximate fallback. Invalid scan timestamps cannot prove newer cells. Session counts retain the largest accepted count because aggregates do not carry session IDs to union. Overlapping partial cells remain excluded even when their totals are larger; the aggregate cannot prove which records overlap.

Verification: 82 focused tests in seven files, including both real client hooks and selection/reselection, existing identity/legacy/future-contract/pricing coverage, complete/partial/failed transitions, supplemental day/hour/model cells, repeated partial scans and invalid times. Nine original new shared regressions fail on base; both new client-hook regressions reproduce 7 instead of 13 on base and pass after. Shared, web and mobile typechecks; scoped lint, formatting and diff checks pass. No wire, persistence, provider-credential or UI layout change; no live account, rendered browser/native pass, release or installation.

Follow-up to upstream catch-up #865. The maintainer Cursor account-history/Keychain deferral remains intact. #953 handles independent presentation hunks; generic source scan warnings remain the next separate follow-up.

Review fixes: ownership is now ranked per provider scan (one environment's non-missing homes for one provider), not per home. A server attributes a record found in several homes to the first one it read, so splitting one scan's homes across environments could count a record twice or turn an exact legacy total approximate. A scan whose homes were all read completely claims them before any scan with a partial or failed home; within a rank the newest scan wins, and unclaimed homes still go to the next scan. A newer scan may add cells only when its owner is a complete scan that owns all of its own homes and every home of the newer scan belongs to that owner or to itself; unseen cells are checked against the owner's cells across all of its homes and taken from the newest scan once. Two new shared regressions (homes split across complete and newer partial scans: 23 instead of 13 on the previous head; legacy complete multi-home total against a newer partial scan: approximate 20 instead of exact 15) fail before the fix and pass after; all 47 tests in the shared merge and web/mobile usage state files pass, plus shared/web/mobile typechecks and scoped lint/format.

Second review round: a scan's rank now uses only homes another scan also reads, so a failed home nobody else reads no longer demotes the scan's shared homes. The regression test gives 15 again; the previous head gave 9. Overlapping but unequal home sets cannot be made exact from aggregates: keeping each scan's unique homes splits it from its shared homes, so a record in both may be counted twice. A scan whose homes end up with more than one owner is now reported in approximateEnvironments rather than silently double counting. This adds a flag to three existing unequal-overlap tests; their totals are unchanged. Two new regressions fail on the previous head and pass now. 49 tests pass across the shared merge and web/mobile usage state files, along with the shared/web/mobile typechecks and scoped lint/format.

Third review round: within a rank, a scan whose homes strictly contain another scan's homes claims first, so nested home sets (desktop {.claude} vs a dev server {.claude, .claude-alt}) have one owner and no approximate flag, whichever scanned last. A newer subset scan still adds new cells through the supplement path, and scans where both sides have a unique home stay flagged. Two older-server tests gained a unique home so they still cover the split path. The web and mobile approximate notices now also mention overlapping history folders. 135 tests pass across the shared merge, the web/mobile usage state, and the web/mobile usage component files, along with the shared/web/mobile typechecks and scoped lint/format.

Implemented and reviewed by GPT-6 in the Codex harness.
Review fixes by Claude Opus 5.5 in Claude Code.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Sep 30, 2026
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 14.0 KiB 14.0 KiB −31 B (−0.2%) 15.1 KiB ✅
Codex Thread snapshot wire 7.3 KiB 7.3 KiB −18 B (−0.2%) 7.3 KiB ✅
Codex Live turn WebSocket wire 6.7 KiB 6.7 KiB −13 B (−0.2%) 7.8 KiB ✅
Codex Live turn WebSocket decoded 58.0 KiB 58.0 KiB −44 B (−0.1%) 66.4 KiB ✅
Codex Live turn messages 9 8 −1 (−11.1%) 21 ✅
Claude Total thread wire 14.0 KiB 14.0 KiB −16 B (−0.1%) 15.1 KiB ✅
Claude Thread snapshot wire 7.3 KiB 7.3 KiB +3 B (+0.0%) 7.3 KiB ✅
Claude Live turn WebSocket wire 6.7 KiB 6.7 KiB −19 B (−0.3%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 58.9 KiB 58.9 KiB 0 B (0.0%) 66.4 KiB ✅
Claude Live turn messages 9 9 0 (0.0%) 21 ✅

Baseline: f677ed4 · PR result: a1986fb · 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: 115.7 KiB
  • Claude decoded thread snapshot: 116.5 KiB

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

@rynfar
rynfar force-pushed the codex/usage-scan-merge branch from a007aa2 to a1986fb Compare October 1, 2026 06:56
@rynfar
rynfar merged commit 10f48ef into pylon Oct 1, 2026
17 checks passed
@rynfar
rynfar deleted the codex/usage-scan-merge branch October 1, 2026 07:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant