Fix Codex usage history indexing and catch-up completion - #2849
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs maintainer review before merge. Reviewed August 13, 2026, 5:17 PM ET / 21:17 UTC. ClawSweeper reviewWhat this changesThe PR bounds large Codex Usage & Spend history scans, preserves persisted catch-up state across relaunches and appends, and prevents catch-up task restart races. Regression provenancePossible regression — probable (reproduction; reviewed change). No predecessor PR is attributed. Merge readinessThe PR remains worth maintaining: it has real after-fix evidence and the repository owner has explicitly left the compatibility-sensitive persisted-cache design pending sign-off. Local read-only inspection could not run because the review sandbox failed during command startup, so this verdict relies on the supplied PR discussion and diff context. Priority: P1 Review scores
Verification
How this fits togetherCodexBar scans local Codex session JSONL history into a persisted Cost Usage cache used by the primary Usage view and Spend Dashboard. Background catch-up workers advance that cache in bounded passes and publish progress or completion to those views. flowchart LR
A[Local Codex session files] --> B[Bounded file discovery]
B --> C[Catch-up scan queue]
C --> D[Persisted Cost Usage cache]
D --> E[Background catch-up worker]
E --> F[Usage and Spend Dashboard]
E --> G[Completion and progress state]
Decision needed
Why: The repository owner explicitly states that this data-ownership design remains intentionally unmerged pending owner sign-off; automated review cannot choose the permanent persisted-state contract. Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Obtain owner approval for the queue-owned persisted migration model, rebase the branch onto current main, and validate both a fresh history and a v0.49.2-to-current cache upgrade before merge. Do we have a high-confidence way to reproduce the issue? Yes, source-level regression paths and a redacted multi-gigabyte real-history log are supplied, but this reviewer could not execute local inspection because the sandbox command startup failed. Is this the best way to solve the issue? Unclear: the bounded scanning approach is supported by targeted proof, but the owner must decide whether its queue-only persisted migration ownership model is the desired permanent contract. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against daf02ae7a7a4. LabelsLabel 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 (10 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:
|
…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:
|
Co-authored-by: thomaschow19 <29773444+thomaschow19@users.noreply.github.com>
Co-authored-by: pavbar <pavlo@barzdun.com>
|
Merged via #2918, which contains every commit of this PR verbatim (your head Closing this PR since the same commits are now on main — full authorship credit is preserved in history and the changelog. Thank you for the substantial indexing/durability work, @Quicksaver — it's the backbone of the fix. |
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.