Skip to content

Fix Codex cost catch-up cluster: bounded indexing, configured Finish-now window, semantic progress - #2918

Merged
steipete merged 39 commits into
mainfrom
fix/codex-catchup-cluster
Aug 13, 2026
Merged

Fix Codex cost catch-up cluster: bounded indexing, configured Finish-now window, semantic progress#2918
steipete merged 39 commits into
mainfrom
fix/codex-catchup-cluster

Conversation

@steipete

Copy link
Copy Markdown
Owner

Summary

One coherent landing for the Codex cost-history catch-up cluster. This branch contains PR #2849 (rebased onto current main via merge, all conflicts resolved) plus the two remaining root-cause fixes folded in with contributor credit.

Fixes #2861
Refs #2815
Supersedes #2849, #2864, #2844

Root causes fixed

  1. Unbounded/non-durable indexing on large corpora ([Codex cost] Large active rollout remains incomplete in 0.48.1; consider ccusage fallback/reference #2815, Fix Codex usage history indexing and catch-up completion #2849): discovery, candidate selection, cache reconciliation, and progress accounting could each perform corpus-sized work per bounded pass; completion state was not durable across relaunches (APFS device-component drift, stale lookback queues, worker lifecycle races). Adopted wholesale from @Quicksaver's Fix Codex usage history indexing and catch-up completion #2849, preserved as its full commit history.
  2. Finish now hard-coded 30 days ([Codex cost] “Finish now” accelerates only 30 days instead of the configured history window #2861): the Spend Dashboard accelerator passed SpendDashboardSource.scanDays into its catch-up context instead of the configured history window. Now uses max(30, configured days), includes the window in the scope signature and context-currency check so changing the setting replaces a stale catch-up context. Adopted from @thomaschow19's Fix Finish now history catch-up #2864 (Co-authored-by on the commit).
  3. Semantic progress misclassified as a stall ([Codex cost] “Finish now” accelerates only 30 days instead of the configured history window #2861, [Codex cost] Large active rollout remains incomplete in 0.48.1; consider ccusage fallback/reference #2815): the progress key hashed only per-file parse state, so passes that advanced discovery, active lookback, or buffered fork-retry cursors were stopped as noProgress; conversely a live session appending to an already-complete file counted as endless "progress" (the battery-drain report in [Codex cost] Large active rollout remains incomplete in 0.48.1; consider ccusage fallback/reference #2815). The key now covers every persisted cursor that keeps catchUpPending true (including the new Fix Codex usage history indexing and catch-up completion #2849 lookback/inventory cursors), deliberately ignores byte growth on complete files, and both schedulers use seen-key sets so revisiting any earlier state stops cleanly. Adopted from @pavbar's fix: detect semantic Codex cost catch-up progress #2844 (Co-authored-by on the commit).

Merge-resolution notes (vs #2849 as filed)

  • Restored Equatable on the cost-cache model types (Fix Codex usage history indexing and catch-up completion #2849 had dropped it; main's identical-content fast save Skip identical cost cache database rewrites #2852 requires it), covering all new persisted fields.
  • Preserved main's skipIdenticalContent save semantics and catchUpRequired propagation inside the extracted saveCodexCache helper.
  • Kept main's general compatiblePredecessorParserHashes adoption mechanism (superseding the PR's narrower single-upgrade struct) and added the current released hash 47144baa8daccf52 as a compatible predecessor, since this branch changes only scheduling/discovery/persistence bookkeeping. Parser hash regenerated to e2899fcb0234e5c1.

What remains for #2815

The native defects are addressed: bounded passes stay bounded, semantic progress is recognized, completion is durable, and growing active tails no longer keep accelerated catch-up alive forever (complete-file appends are excluded from the progress key, so the scheduler backs off). Two follow-ups from the #2815 thread remain open and are NOT in this branch: honoring the in-app Background-work low-power preference in the catch-up policy (it currently checks only the macOS system Low Power Mode), and surfacing per-file stall reasons in the UI. With the native path repaired, the opt-in ccusage fallback (#2817) is no longer needed as a correctness escape hatch; if still wanted, it is a separate product decision (bundled-executable provenance/signing) best kept as a test oracle instead.

Recommended disposition of sibling PRs

Validation

  • make check: SwiftFormat clean, parser hash current, SwiftLint 0 violations.
  • Full make test: 850/850 selections, 71/71 groups, zero retries/failures/timeouts.
  • Focused suites (no-parallel): CostUsageStoreTests, CostUsagePerformanceGateTests, CostUsageBoundedProgressTests, CostUsageCatchUpCompletionTests, CostUsageCacheWideMigrationTests, CostUsageCatchUpProgressTests, UsageStoreCodexCostCatchUpTests, UsageStoreSpendDashboardCodexCostCatchUpTests, ProviderArchitectureGatekeeperTests — 200/200.
  • New regressions: configured-window Finish now (123/248/365 plus 30-day floor and context replacement), semantic-cursor progress (discovery/lookback/buffered-retry/inventory advances change the key; complete-file appends do not), cyclic-state stop for both schedulers.
  • Codex autoreview: clean, no accepted/actionable findings.

Thanks @Quicksaver for the substantial indexing/durability work, @thomaschow19 for the Finish-now report and fix, @pavbar for the semantic-progress design, and @Yoroin, @xiehaibin18, @Astro-Han for the detailed privacy-safe diagnostics on #2815.

Quicksaver and others added 30 commits August 10, 2026 23:52
- Clear queued restarts before an active pass returns from Stop
- Cover the primary worker cancellation race with a regression
- Cap unique candidate inspections before cache eligibility checks\n- Preserve discovered URL identities for queued lookback files\n- Prove bounded selection across consecutive large-corpus passes
- Limit persisted lookback validation to 512 paths per invocation\n- Defer exact inventory proof until no bounded work remains\n- Prove load and save traversal against a 988-path queue
- Page active window directories within the catch-up limit
- Persist discovery cursors and defer exact inventory proof
- Cover oversized histories and relaunch rehydration
…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
@clawsweeper

clawsweeper Bot commented Aug 13, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Aug 13, 2026
@clawsweeper

clawsweeper Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codex review: needs changes before merge. Reviewed August 13, 2026, 5:33 PM ET / 21:33 UTC.

ClawSweeper review

What this changes

The PR bounds and persists Codex cost-history catch-up, makes Finish now use the configured history window, and tracks semantic scan progress.

Regression provenance

Possible regression — probable (reviewed change; failure trace). No predecessor PR is attributed.

Merge readiness

⚠️ Ready for maintainer review - 2 items remain

Keep open: this owner-authored consolidation has three unresolved current review comments covering relaunch progress, deleted queued files, and root replacement during paged catch-up. Likely related people: steipete and Quicksaver (medium confidence).

Priority: P2
Reviewed head: 220c9a4f62555620ebfb98c4cdd2d0c3b20cc6ec

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The PR has substantial stated regression coverage, but the supplied current review comments identify concrete correctness blockers.
Proof confidence 🌊 off-meta tidepool Not applicable: This is an owner-authored PR, so the external-contributor real-behavior-proof gate does not apply.
Patch quality 🦐 gold shrimp (3/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Not applicable Not applicable: This is an owner-authored PR, so the external-contributor real-behavior-proof gate does not apply.
Evidence reviewed 2 items Current review comments: The supplied PR context contains one P1 and two P2 current comments describing relaunch cursor stalling, deleted queued paths, and stale old-root data during paged discovery.
Inspection limitation: The local read-only inspection command failed before producing repository output: bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted; no local source or history inspection is claimed.
Findings None None.
Security None None.

How this fits together

CodexBar scans local Codex session files into a persisted cost cache for Usage & Spend and the Spend Dashboard. Catch-up workers advance bounded scan state and publish coverage and progress to those views.

flowchart LR
A[Codex session files] --> B[Bounded history scanner]
B --> C[Persisted cost cache]
C --> D[Catch-up status]
D --> E[Primary catch-up worker]
D --> F[Spend Dashboard worker]
E --> G[Usage and Spend UI]
F --> G
Loading

Before merge

  • Resolve merge risk (P1) - A relaunch can leave a large paged catch-up pending without an active worker if its persisted directory cursor does not advance.
  • Resolve merge risk (P1) - Deleted queued sessions and a changed Codex root can pause catch-up or temporarily retain usage from the former root.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch surface 21 files; production +1,664, tests +2,389, docs +3 This is a broad persisted-cache and scheduler change, making boundary regressions especially important before merge.

Merge-risk options

Maintainer options:

  1. Repair persisted queue transitions (recommended)
    Fix resumed directory cursor advancement, safely discard missing queued paths, and remove old-root data before merging.
  2. Pause the consolidated landing
    Keep this PR open until the persisted catch-up transitions receive a verified repair.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Add focused regressions for resumed directory pages, deleted queued session paths, and root replacement during pending catch-up.

Technical review

Best possible solution:

Repair the three queued-state and paged-discovery paths with focused regressions, then refresh merge review.

Do we have a high-confidence way to reproduce the issue?

Yes, from the supplied current review comments: resume a persisted cursor beyond one directory page, remove a queued session, or replace the session root while catch-up is pending. Local reproduction could not be verified because repository inspection was unavailable.

Is this the best way to solve the issue?

No; the branch needs the three concrete persisted-queue and paged-discovery repairs identified in the supplied current review comments.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 283bd99e18c7.

Labels

Label justifications:

  • P2: The PR repairs user-visible local history catch-up with limited but meaningful Usage & Spend impact.
  • merge-risk: 🚨 compatibility: Persisted cache metadata and root-change handling can retain stale usage across upgrades or configuration changes.
  • merge-risk: 🚨 availability: The current review comments describe pending catch-up work that can stop without a worker after relaunch or a queued-file failure.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🌊 off-meta tidepool and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: This is an owner-authored PR, so the external-contributor real-behavior-proof gate does not apply.

Evidence

Acceptance criteria:

  • [P1] swift test --filter CostUsageBoundedProgressTests.
  • [P1] swift test --filter CostUsageCatchUpCompletionTests.
  • [P1] swift test --filter CostUsageCatchUpProgressTests.
  • [P1] swift test --filter UsageStoreCodexCostCatchUpTests.
  • [P1] swift test --filter UsageStoreSpendDashboardCodexCostCatchUpTests.

What I checked:

  • Current review comments: The supplied PR context contains one P1 and two P2 current comments describing relaunch cursor stalling, deleted queued paths, and stale old-root data during paged discovery. (220c9a4f6255)
  • Inspection limitation: The local read-only inspection command failed before producing repository output: bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted; no local source or history inspection is claimed.

Likely related people:

  • steipete: The supplied PR history attributes the integration, configured-window fix, and semantic-progress fix to steipete. (role: recent area contributor; confidence: medium; commits: 95ec2495df75, 2c55f0dcb901, 220c9a4f6255; files: Sources/CodexBar/UsageStore+CodexCostCatchUp.swift, Sources/CodexBar/UsageStore+SpendDashboardCodexCostCatchUp.swift)
  • Quicksaver: The supplied commit history attributes the scanner, durable completion, and reconciliation work to Quicksaver. (role: introduced bounded-indexing work; confidence: medium; commits: f50968f92a72, 5cdc0171ea0c, 6cf344300ed3; files: Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift, Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore+CodexCache.swift)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Repair the three current queue and discovery concerns with focused regressions.
  • Request a fresh review after updating the branch.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (1 earlier review cycle)
  • reviewed 2026-08-13T21:27:40.631Z sha 01f7261 :: needs maintainer review before merge. :: none

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 01f72618cd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +2492 to +2495
return CodexDirectoryPage(
files: files,
nextOffset: max(resumeOffset, cursor.logicalOffset),
visits: visits)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Advance persisted directory pages after relaunch

When the process relaunches with a persisted resumeOffset greater than visitLimit, the new DIR cursor starts at logical 0 and this returns the old resumeOffset until enough in-memory reads catch up. That post-relaunch pass persists no cursor change and no files, so the UsageStore seen-progress check pauses as noProgress after one pass; large (>512 entry) catch-ups can be left pending with no active worker for the remaining entries.

Useful? React with 👍 / 👎.

Comment on lines +2990 to +2995
for path in normalizedPrefix {
let fileURL = URL(fileURLWithPath: path)
let pathKey = Self.codexPathKey(fileURL)
guard seenPaths.insert(pathKey).inserted else { continue }
fileURLsByPathKey[pathKey] = fileURL
files.append(fileURL)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip missing queued paths before parsing

When a path in pendingFilePaths was deleted or archived after it was queued, this now appends it to the scan list instead of filtering it out. scanCodexFile eventually opens that URL with FileHandle(forReadingFrom:), so a single missing queued JSONL throws and pauses the whole catch-up rather than dropping the stale cache entry; this is likely with rotating or removed Codex session files.

Useful? React with 👍 / 👎.

Comment on lines 5526 to +5528
let shouldDropAllUnscannedFiles = options.forceRescan || plan.rootsChanged || cache.files.isEmpty
|| plan.needsProjectMetadataMigration
for key in cache.files.keys where !filePathsInScan.contains(key) {
guard let old = cache.files[key] else { continue }
let shouldDrop = shouldDropAllUnscannedFiles ||
old.touchesCodexScanWindow(sinceKey: range.scanSinceKey, untilKey: range.scanUntilKey)
guard shouldDrop else { continue }
Self.applyFileDays(cache: &cache, fileDays: old.days, sign: -1)
cache.files.removeValue(forKey: key)
}
if !shouldPageDiscovery {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Drop old-root rows during paged root changes

When the Codex sessions root changes while codexScanCatchUpPending is already true, shouldPageDiscovery is true, so this guard skips the removal loop even though shouldDropAllUnscannedFiles includes plan.rootsChanged. The save below then records the new roots fingerprint while retaining old-root cache.files and day aggregates, causing usage from the previous Codex home/profile to be reported until a later exact proof pass finally drops it.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Codex cost] “Finish now” accelerates only 30 days instead of the configured history window

2 participants