Fix Codex usage history indexing and catch-up completion - #2849
Fix Codex usage history indexing and catch-up completion#2849Quicksaver wants to merge 32 commits into
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs maintainer review before merge. Reviewed August 11, 2026, 9:01 AM ET / 13:01 UTC. ClawSweeper reviewWhat this changesThe PR bounds large local Codex usage-history discovery, parsing, and cache recovery while preserving completed catch-up state across relaunches, appends, and the v0.49.2 upgrade. Regression provenancePossible regression — probable (reviewed change; failure trace). No predecessor PR is attributed. Merge readinessKeep this PR open for owner approval of the persisted-cache migration design; the current head has no discrete correctness finding from this review and includes sufficient real-history proof. Priority: P1 Review scores
Verification
How this fits togetherCodexBar scans local Codex session files into a persisted Cost Usage cache that supplies the menu-bar usage view and Spend Dashboard. This change governs how files are discovered, queued, reconciled, and marked complete before those views publish results. flowchart LR
A[Local Codex session files] --> B[Bounded discovery cursor]
B --> C[Catch-up queue]
C --> D[Parser and cache update]
D --> E[Completion and migration validation]
E --> F[Menu-bar usage]
E --> G[Spend Dashboard]
Decision needed
Why: The owner explicitly left this PR unmerged pending sign-off on persisted inventory/storage ownership; regression coverage cannot determine the intended long-term persistence contract. Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Approve the queue-only migration contract if it is the intended durable storage boundary, then merge after required checks pass on the current head. Do we have a high-confidence way to reproduce the issue? Yes—focused regressions and the supplied redacted current-head live logs cover bounded discovery, migration, relaunch, and catch-up completion paths. Is this the best way to solve the issue? Unclear—the bounded queue implementation is well-supported, but the owner must still choose whether its persistence contract is the intended long-term design. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against e5528d452d4f. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (9 earlier review cycles; latest 8 shown)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8a976c44e4
ℹ️ 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".
|
Responding to the request for inspectable real-behavior proof: the PR body now contains this same redacted artifact under Proof. Redacted real-history debug log and persisted-store snapshotProvider/account details, home paths, and spend values were removed. No conversation content was read or included. The two startup markers show relaunches reusing the existing multi-gigabyte cache: only 790,493 bytes and 404,384 bytes were consumed before successful Codex publication, rather than replaying the corpus. The later 4,600,693-byte delta shows appended history being incorporated. The persisted store then records equal processed/total bytes and completed/total files with no pending catch-up. The two line-review findings were also fixed on top of merged upstream behavior:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Resolved the updated ClawSweeper finding in The primary Validation after merging latest
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Fixed the updated candidate-selection finding in The bounded path now stops after inspecting 512 unique candidate path keys, before cache-eligibility checks. Pending lookback paths are consumed directly, and the selector reuses the URL identity already established during discovery so cache accumulation remains stable across passes. Concrete 1,500-file regression proof from This proves that the second pass inspected only 512 candidates (not the full retained queue), scanned 512 files, retained all 512 first-pass cache entries, and advanced the cache to 1,024 files with 476 remaining. Validation:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Fixed the persisted reconciliation finding in Changes:
Concrete 1,500-file regression output: The first line proves that both save and the subsequent load stop after 512 metadata/completion visits even though the retained queue contains 988 paths. The second proves the scanner then remains bounded and advances another 512 files without losing the first-pass cache. Validation:
The full local @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Fixed the latest bounded-pass finding in 40ff7ee. Pending catch-up passes now maintain file progress incrementally and deliberately leave exact byte totals/inventory indeterminate, so they no longer sort or stat the full discovered corpus after the 512-file scan. Exact metadata accounting and sorted inventory persistence run only once bounded work is exhausted. The counted 1,500-file regression proves two consecutive bounded passes advance 512 files each while performing zero whole-corpus progress-accounting visits: @clawsweeper review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
31c1c2b to
11b9cd7
Compare
|
Maintainer migration follow-up is now pushed at exact head The active-lookback queue now owns cache-wide migration continuation without adding persisted schema. A completed 600-file cache with a drained queue is covered across pricing metadata, pricing-key, project-metadata, turn-ID, priority-metadata, and priority-turn migrations: pass one attempts exactly 512 files and persists 88; pass two attempts the remaining 88 and proves a path beyond the first slice was reparsed; bounded passes perform zero whole-inventory progress-accounting visits; exact completion reaches 600/600; the next warm refresh does no reseed or reparse. Separate coverage proves newest-first order both from a drained queue and when a migration interrupts a partially drained queue. Validation at this head: migration suite 3 tests including 6 parameterized owner cases; bounded-progress 10/10; requested focused matrix 151 selections with the global-hook suite isolated; parser hash and The branch preserves the contributor head that advanced during validation, then applies the maintainer queue-only design afterward. It remains intentionally unmerged pending owner sign-off on persisted inventory/storage ownership. @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
- Page active window directories within the catch-up limit - Persist discovery cursors and defer exact inventory proof - Cover oversized histories and relaunch rehydration
|
Addressed the latest finding from #2849 (comment) in 5cdc017. Time-limited Codex catch-up now pages current-window date partitions, flat-root sessions, and the older active-session lookback through one shared 512-entry discovery budget before candidate construction. Per-root day/directory cursors persist in the catch-up state, cached-file reconstruction and recursive legacy discovery are deferred during bounded passes, and the exact full inventory runs only after bounded discovery and queued work are exhausted. Cache-wide migration queues retain ownership of cached paths without duplicating them into discovery. Current-head oversized active-day proof: Validation:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
…exing-performance # Conflicts: # CHANGELOG.md
Migrate v0.49.2 stores without rebuilding completed history Bound device identity validation and defer remaining paths Restore Linux directory cursor builds and lint compliance
…exing-performance
|
Addressed the current durable ClawSweeper requirements at merged head
The temporary proof harness/database were deleted afterward. The earlier redacted real-history evidence in the PR body still demonstrates normal appended history being incorporated; this new run proves the final merged head's upgrade/relaunch bound. Validation on the merged head:
The prior CI failures were checked before this push: Linux could not resolve |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Summary
Fix Codex Usage & Spend indexing for very large local histories. The scanner now keeps bounded passes bounded across discovery, candidate selection, file parsing, and cache reconciliation, while avoiding corpus-wide cache searches for every session file.
The catch-up state is also made durable and self-healing: completed files can leave stale lookback queues, completed caches no longer restart from zero after relaunch, appended sessions resume correctly, and refreshes cannot lose the worker that should process newly discovered tail work.
What Changed
/private/varaliases.Why
A real Codex history of approximately 6.8 GB exposed several compounding failures. Initial indexing became progressively slower as more files entered the cache, eventually appearing stalled after hours. Once the scanner was made faster, it could reach 100% but still fail while finalizing, leaving charts unavailable. Relaunching CodexBar then restarted the multi-gigabyte analysis, and later attempts repeatedly advanced only a small amount before returning to the same error state.
The symptoms were not one isolated failure: they combined unbounded work outside the parser budget, quadratic cache-identity lookup, stale retained-lookback entries, inconsistent persisted completion metadata, filesystem identity drift across relaunches, and a worker lifecycle race.
Evidence
Incident observations
Root-cause findings and corresponding fixes
pendingFilePaths, while candidate filtering excluded complete files. That made the UI reach 100% but prevented finalization forever. Retained paths are now admitted once so completion can acknowledge and remove them.catchUpPendingand zero/partial counters could survive after every current file was complete. Conversely, counting every file retained from a wider history window could falsely satisfy the smaller current-scan count while current files were still absent. The scanner now persists the exact current inventory paths, and cache loading verifies every one against current metadata and indexed-content anchors before clearing pending state. Wider retained files cannot satisfy that proof.st_devcomponent. Treating the full persisteddevice:inodevalue as permanently stable caused completed files to look new after reopening the app. Restore now maps persisted inodes to the current Codex root device and validates mtime, size, and the token-index content anchor before adopting the current identity.awaitingExactInventorysentinel, preserves it across the store round trip, clears it on the following zero-work pass, and includes pending/progress totals in the catch-up status identity so charts publish the completed snapshot.Automated regression evidence
first=512 discovery=512 attempts=512; after resetting the live directory handle, the bounded rehydration pass recordsrelaunched=512 discovery=512 attempts=0; the following slice recordssecond=1024 discovery=512 visits=512 attempts=512 accounting=0.save=512 load=512 pending=921.finalWorkAttempts=88 finalWorkAccounting=0 proofAttempts=0 proofAccounting=600.Validation
CostUsageCatchUpCompletionTests: 5/5 passed, including a 600-file identity-drift corpus (512validated,88deferred), missing-file retention, scan-window queue preservation, and normalized-alias completion.CostUsageBoundedFinalizationTests: 1 test passed, proving exact inventory work is isolated to the zero-work completion pass.UsageStoreCodexCostCatchUpTests: 6 tests passed, including primary active-pass cancellation with a queued restart.UsageStoreSpendDashboardCodexCostCatchUpTests: 6 tests passed, including active-pass cancellation with a queued restart.CostUsagePerformanceGateTests: 27 tests passed; oversized active-day discovery, candidate selection, JSONL scanning, and persisted reconciliation each stopped at 512 visits. Simulated relaunch rehydration performed zero JSONL scan attempts and preserved the 512 already-indexed files before the next slice advanced to 1,024.CostUsageBoundedProgressTests: 10/10 passed after the identity-queue repair, preserving existing append, rewrite, missing-file, cancellation, completion, and migration queue behavior.CostUsageStoreTests: 61/61 passed, including an exact v0.49.2 database upgrade that retains completed rows, installs the current schema/hash, and records zero rebuilds.ProviderArchitectureGatekeeperTests: 38 tests passed after rebasing its exact source anchors onto the latest merged upstream behavior.make checkpassed, including generated-source checks, SwiftFormat, and strict SwiftLint with zero violations.upstream/mainate5528d452merged before final validation, including the macOS 15 Cost Usage store executor-isolation fix.make testreached 45 successful groups before the same unrelated, reproducible locale-sensitiveMiniMaxMenuCardBillingTestsfailure on group 46 and its retry: the test expects comma-grouped1,234/5,678, while this machine's current locale renders non-breaking-space grouping. The failing suite does not touch Codex cost scanning or any file changed by this branch.Proof
After the final fixes, the same approximately 6.83–6.84 GB local Codex dataset used to discover the performance and completion failures was quickly and successfully analyzed in only a few minutes. This validates the complete path against the original incident corpus, not merely a reduced fixture.
Redacted real-history debug log and persisted-store snapshot
The excerpt below is from the real incident dataset. Provider/account details, home paths, and spend values were removed. No conversation content was read or included.
This shows two distinct relaunches reusing the existing multi-gigabyte cache and scanning only 790,493 bytes and 404,384 bytes before successful publication, rather than replaying the corpus. The later 4,600,693-byte delta demonstrates appended history being incorporated. The persisted state then records exact byte/file completion with no pending catch-up.
A later read-only snapshot after normal Codex use showed the same cache still complete while the corpus had grown:
catch_up_pending=0,processed_bytes=6898985724,total_bytes=6898985724,completed_files=10955,total_files=10955.Current-head bounded traversal and completion-proof output
This current-head proof uses generated multi-thousand-file history and contains no provider identity, paths, spend, or conversation content.
The counters demonstrate that each pending phase is independently bounded: directory discovery, candidate selection, scanning, persisted reconciliation, and progress accounting. Relaunch rehydration visits only one bounded page, does not parse JSONL, and the next slice resumes forward progress. Exact whole-inventory accounting occurs only on the separate pass with zero file-scan attempts.
The same behaviors are also captured by synthetic regressions so the proof does not depend solely on one machine's local history.
Redacted current-head v0.49.2 upgrade and bounded identity-drift proof
The final source tree was run against an isolated copy of the real large-history database and read-only session corpus. The copy was relabeled with the exact v0.49.2 parser hash/schema and its stored device components were changed only inside that copy. Paths, identifiers, spend, identity values, and conversation content were neither printed nor retained.
This proves the released database upgrades without deletion, cache load stops identity validation at exactly 512, the next relaunch performs exactly one bounded 512-file discovery/scan slice, and the remaining queue survives in the final-schema store. The temporary harness and database copy were deleted after the aggregate markers were captured; the real cache and roughly 7.1 GiB/12,400-file session corpus remained read-only.
Cache-wide migration queue proof
The latest maintainer follow-up closes a migration-specific hole in the bounded scanner. Pricing/model catalog, project metadata, turn-ID, priority metadata, and priority-turn migrations now reseed the already-discovered normalized path inventory into the existing durable active-lookback queue, even when roots and the scan window are unchanged and the old queue has drained. No new persisted schema is introduced: migration metadata can advance on the first pass because the queue itself owns every remaining revisit, and later passes drain it without reseeding.
The six-owner 600-file regression matrix proves the first bounded migration pass attempts exactly 512 files, retains 88 paths, and performs zero full progress-accounting visits. The second pass attempts exactly those remaining 88 paths and proves a path beyond the first slice was reparsed. The separate exact-validation pass reaches 600/600, and the following ordinary warm refresh performs zero candidate visits, reparses, or progress-accounting visits. Additional 513-file and partially drained 600-file tests prove migration reseeding preserves newest-first order while retaining any out-of-inventory pending work.
Current validation:
make check: passed; SwiftLint reported zero violations.make testreached 45 successful groups before the same unrelated, reproducible locale-sensitiveMiniMaxMenuCardBillingTestsfailure on group 46 and its retry; the remaining 119 tests in that exact post-merge shard passed.