Skip to content

feat(spend): cache-first and 5m TTL for dashboard - #3107

Open
Yuxin-Qiao wants to merge 2 commits into
steipete:mainfrom
Yuxin-Qiao:feat/spend-cache-ttl
Open

feat(spend): cache-first and 5m TTL for dashboard#3107
Yuxin-Qiao wants to merge 2 commits into
steipete:mainfrom
Yuxin-Qiao:feat/spend-cache-ttl

Conversation

@Yuxin-Qiao

@Yuxin-Qiao Yuxin-Qiao commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Clean rebuild of PR #3107 on current upstream/main (26132179a), kept to the spend dashboard cache-first/5-minute TTL feature.

  • Read retained spend and OpenCodex usage caches first, then refresh after the five-minute TTL.
  • Preserve aggregate hydration, retention, pricing-era coverage, and non-destructive schema migration.
  • Keep bounded OpenCodex history reads and race-safe refresh fallbacks.
  • Remove the unrelated SakanaUsageFetcherTests.swift change from the earlier polluted branch.

Review fixes

  • Preserve current-format empty-cache metadata (pricingSegments: []) while keeping legacy missing metadata distinguishable.
  • Preserve explicit unpricedTokens evidence during aggregate hydration.
  • Add current main's base-3 parser hash (c6c46a376ba16304) to the compatible migration hashes so existing caches migrate in place.
  • Bind OpenCodex unavailable-log cache fallback to the requested log path (cached.parseCursor.path == logURL.path), returning empty when switching to an unavailable different home.

Validation

  • swift test --filter 'CodexBarTests.OpenCodexUsageStore(IncrementalTests|WindowTests)' — 30 tests passed.
  • make check — passed; SwiftFormat clean and SwiftLint found 0 violations in 1,999 files.
  • Latest commit: fd4dc8853 (fix(opencodex): bind retained cache fallback to requested log path).
  • No provider credentials, Keychain reads, or live dashboard accounts were accessed; real dashboard interaction proof remains a separate pending contributor requirement.

@clawsweeper

clawsweeper Bot commented Aug 20, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

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

@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: 1f4bbb2cc7

ℹ️ 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".

Comment on lines +73 to +77
if !force,
let lastAt = self.lastSpendDashboardTokenFetchAt[provider.instanceID],
let lastScope = self.lastSpendDashboardTokenFetchScope[provider.instanceID],
lastScope == costScopeSignature,
self.spendDashboardTokenSnapshotPublicationForCurrentConfig(for: provider) != nil,

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 Route a non-forced request through the TTL check

This TTL cannot fire through production code: the sole caller in SpendDashboardSource.makeRequest always passes force: true, while .refreshMissing invokes that caller only when no current publication exists—even though this condition requires one. Consequently, the new five-minute guard cannot suppress any dashboard token scan; the caller needs to preserve the build mode's forced/non-forced semantics or perform the TTL decision before the missing-publication predicate.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Aug 20, 2026
@clawsweeper

clawsweeper Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed August 26, 2026, 11:30 AM ET / 15:30 UTC.

ClawSweeper review

What this changes

This PR makes the Spend dashboard load retained Codex and OpenCodex usage caches first, refresh stale data after five minutes, and migrate compatible local cache schemas.

Merge readiness

Blocked until real behavior proof is added - 3 items remain

Keep open: current main does not contain the cache-first/TTL behavior, and the latest head resolves the prior requested-log fallback issue without a remaining source-level finding. Real after-fix Spend dashboard proof is still required before merge.

Priority: P2
Reviewed head: fd4dc885334076cb1c24ad8b927da2214ee567d0

Review scores

Measure Result What it means
Overall readiness 🧂 unranked krab (1/6) The source changes and focused regression coverage are credible, but required real dashboard proof is absent.
Proof confidence 🧂 unranked krab (1/6) Needs real behavior proof before merge: No after-fix Spend dashboard interaction, recording, live output, or redacted runtime log is posted; focused tests and CI are supplemental. Please redact account names, paths, API keys, and other private data; updating the PR body should trigger re-review, or ask a maintainer to comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Needs proof Needs real behavior proof before merge: No after-fix Spend dashboard interaction, recording, live output, or redacted runtime log is posted; focused tests and CI are supplemental. Please redact account names, paths, API keys, and other private data; updating the PR body should trigger re-review, or ask a maintainer to comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 6 items Current main lacks the requested behavior: Current main has only the single-argument refresh decision and no cache-first pane refresh helper; the PR adds stale-aware refresh handling.
Latest fallback repair is present: The unavailable-log fallback now returns retained entries only when the stored cursor belongs to the requested log path.
Upgrade path is explicitly handled: Compatible base-schema-3 parser hashes include the immediate current-main producer so its warmed cache can migrate in place.
Findings None None.
Security None None.

Live Verification

Command: swift run CodexBarCLI --help

Result: FAIL (failed) — execution before step 1 run: sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.24.0.tgz

sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.24.0.tgz

Assertions:

  • FAIL expect_output: USAGE:

How this fits together

The Spend dashboard combines provider token snapshots with locally cached Codex and OpenCodex usage to show cost and activity. This PR changes the cache-read, migration, and refresh decisions before that data reaches the dashboard pane.

flowchart LR
  A[Usage logs] --> B[Local usage caches]
  B --> C[Cache migration and windowed reads]
  C --> D[Dashboard loader]
  E[Provider snapshots] --> D
  D --> F[Spend dashboard model]
  F --> G[Preferences pane]
Loading

Before merge

  • Add real behavior proof - Needs real behavior proof before merge: No after-fix Spend dashboard interaction, recording, live output, or redacted runtime log is posted; focused tests and CI are supplemental. Please redact account names, paths, API keys, and other private data; updating the PR body should trigger re-review, or ask a maintainer to comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Resolve merge risk (P1) - The persisted-cache migration and cache-first presentation have not been demonstrated in a freshly built dashboard, leaving real upgrade and visible refresh behavior unverified outside fixtures.
  • Complete next step (P2) - The remaining merge gate is contributor-supplied real behavior proof, not a narrow automated repair.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Changed surface 31 files, +2,267 / -184 lines The PR spans dashboard scheduling, two local cache formats, migration, and regression coverage.
Production versus tests production +877 / -127; tests +1,390 / -57 The substantial persistence and controller changes are paired with focused regression coverage.

Merge-risk options

Maintainer options:

  1. Add real dashboard proof (recommended)
    Show the freshly built Spend dashboard using a retained cache and then refreshing after the TTL, with account and path data redacted.

Technical review

Best possible solution:

Provide a redacted fresh-bundle dashboard demonstration that shows retained data appearing first and a subsequent refresh after the TTL without losing migrated history.

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

Not applicable: this PR introduces cache-first and TTL behavior rather than reporting a standalone current-main bug.

Is this the best way to solve the issue?

Yes for the source-level implementation: the requested-log-path check preserves same-path retained-cache recovery while rejecting cross-home reuse; real dashboard evidence remains necessary to validate the complete user flow.

AGENTS.md: found and applied where relevant.

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

Labels

Label justifications:

  • P2: This affects dashboard freshness and local cost reporting but is not evidenced as an urgent outage.
  • merge-risk: 🚨 compatibility: The branch changes retained cache schemas and migration behavior for existing dashboard users.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: No after-fix Spend dashboard interaction, recording, live output, or redacted runtime log is posted; focused tests and CI are supplemental. Please redact account names, paths, API keys, and other private data; updating the PR body should trigger re-review, or ask a maintainer to comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

Likely related people:

  • Yuxin-Qiao: Authored the related merged Spend dashboard and Codex parser work as well as this branch. (role: merged feature contributor; confidence: high; commits: 1cf98b330a79, 6538ac34597e, d92783689570; files: Sources/CodexBar/SpendDashboardController.swift, Sources/CodexBarCore/Vendored/OpenCodexUsage/OpenCodexUsageStore.swift)
  • steipete: Reviewed the reconciliation with merged Spend and scanner work and directed the branch rebase. (role: repository owner and reviewer; confidence: high; commits: cf79d1310493; files: Sources/CodexBar/SpendDashboardController.swift, Sources/CodexBarCore/CostUsageFetcher.swift)

Rank-up moves

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

  • Post redacted after-fix evidence from a fresh build showing cache-first dashboard data and TTL refresh behavior.

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 (30 earlier review cycles; latest 8 shown)
  • reviewed 2026-08-25T11:13:59.146Z sha 4e8391e :: needs real behavior proof before merge. :: [P2] Filter full-reload results by the report window | [P2] Create the timestamp index required by the v2 cache | [P2] Retain request boundaries for aggregate cached pricing
  • reviewed 2026-08-25T12:31:08.683Z sha 0f545a6 :: needs real behavior proof before merge. :: [P2] Push the history window into the SQLite cache query
  • reviewed 2026-08-25T18:08:01.828Z sha 4914746 :: needs real behavior proof before merge. :: [P2] Stamp the TTL after the token fetch completes | [P2] Thread the report cutoff through reload races | [P2] Migrate v1 caches before using read-only fallback | [P2] Retain pricing-era granularity in aggregate rows
  • reviewed 2026-08-25T23:16:37.178Z sha da069eb :: needs real behavior proof before merge. :: [P2] Persist an empty pricing-segment marker
  • reviewed 2026-08-26T01:53:33.732Z sha cccccb5 :: needs real behavior proof before merge. :: [P2] Preserve explicit unpriced evidence in cached segments
  • reviewed 2026-08-26T02:57:14.914Z sha 25e9187 :: needs real behavior proof before merge. :: [P1] Migrate the immediate base-schema-3 cache producer
  • reviewed 2026-08-26T03:27:09.994Z sha 1c94b36 :: needs real behavior proof before merge. :: [P2] Load cached OpenCodex data before requiring the source log
  • reviewed 2026-08-26T12:09:00.944Z sha 10d078b :: needs real behavior proof before merge. :: [P2] Bind retained cache fallback to the requested log

@steipete

Copy link
Copy Markdown
Owner

CI failure is a real compile error:

Sources/CodexBar/SpendDashboardController.swift:1086:23: error: referencing operator function '==' on 'Equatable' requires that 'SpendDashboardController.LoadPhase' conform to 'Equatable'

LoadPhase needs Equatable (or match with a case/if case pattern instead of ==). Please fix and re-push.

@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-cache-ttl branch from 4582171 to d3596a6 Compare August 21, 2026 09:57

@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: d3596a6a84

ℹ️ 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".

let shouldPrimeCachedCodex: Bool = self.cachedLoader != nil
&& !Set(Self.codexOwnershipByID(configuration.codexAccountIdentities).keys)
.isSubset(of: Set(self.loadedInputs.map(\.id)))
&& (phase == .ordinary || self.loadedInputs.isEmpty)

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 Pattern-match the load phase instead of comparing it

LoadPhase does not conform to Equatable, and its reconciling(ForcedOutcome) payload prevents synthesized conformance, so phase == .ordinary produces a “binary operator '==' cannot be applied” compiler error and blocks every build. Preserve the prior if case .ordinary = phase pattern or introduce an explicit case-checking property; the repository-required test run would have caught this before handoff.

AGENTS.md reference: AGENTS.md:L23-L24

Useful? React with 👍 / 👎.

@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: ac856d5c36

ℹ️ 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".

let identity = "\(logURL.path)|\(size)|\(mtime)"

if let cached = self.readCachedEntries(identity: identity), !cached.isEmpty {
if let cached = self.readCachedEntries(identity: identity, since: since) {

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 Apply the report cutoff on cache misses

When usage.jsonl has changed since the previous read—as it normally does whenever a new request is appended—the identity check here misses and loadEntries reparses, deduplicates, sorts, and returns the entire lifetime log without applying since. Consequently, the new window only limits SQLite cache-hit reads, while active users continue hitting the unbounded latency and memory path this change is meant to avoid; apply the cutoff in the parser/miss path as well, while retaining the full cache if needed.

Useful? React with 👍 / 👎.

@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: 73bc2a1a34

ℹ️ 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".

Comment on lines +246 to +248
for baseline in providerBaselines where mode.shouldRefresh(
hasPublication: baseline.publication != nil,
isDashboardTokenStale: store.spendDashboardTokenFetchIsStale(for: baseline.provider))

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 Trigger the TTL check when reopening the pane

When the pane is reopened after five minutes without a configuration change, SpendDashboardPane.onAppear calls update(configuration:), but the equality guard in SpendDashboardController.update returns before building a request, so the stale predicate added here is never evaluated. Fresh evidence in the current tree is that the patch now correctly passes the non-forced mode to the loader, while the unchanged controller guard still prevents that path from running on an ordinary reopen. The cached snapshot can therefore remain beyond the advertised TTL until a configuration/date change or manual refresh triggers another load.

Useful? React with 👍 / 👎.

@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

let parsed = try OpenCodexUsageParser.parse(fileURL: logURL, fileManager: fileManager)
var unique: [String: OpenCodexUsageEntry] = [:]
for entry in parsed {
unique[entry.requestID] = entry

P2 Badge Apply the cutoff before parsing cache misses

When usage.jsonl changes, this cache-miss path still parses the entire lifetime file, materializes every entry in unique, sorts the full collection, and rewrites all entries before the since filter runs. Thus active logs remain subject to unbounded peak memory and refresh latency even though the returned array is windowed. Fresh evidence in the current tree is that the follow-up only filters deduped after these full-history operations; pass the cutoff into parsing or otherwise avoid materializing old entries on the report path.

ℹ️ 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".

@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: b577455ac9

ℹ️ 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".

Comment on lines +324 to +326
let rowsByPath = mode == .scanReady
? Dictionary(grouping: snapshot.usageRows, by: \.path)
: [:]

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 Preserve row metadata in aggregate report hydration

When cached Codex usage contains reasoning tokens or usage preceding a historical pricing cutoff, .aggregateReport discards the persisted rows and reconstructs them from day/model aggregates. Those synthesized rows omit both reasoning and timestampUnixMs, while buildCodexReportFromCache derives displayed reasoning totals and date-sensitive pricing from those fields. Consequently, the cache-first snapshot can report zero reasoning and price historical usage at current rates; retain the required metadata in the aggregate representation or decode the rows needed for an equivalent report.

Useful? React with 👍 / 👎.

Comment on lines +35 to +38
guard self.tokenSnapshotPublicationForCurrentProviderConfig(for: provider) != nil,
let legacyLast = self.lastTokenFetchAt[provider.instanceID]
else { return true }
return Date().timeIntervalSince(legacyLast) >= 5 * 60

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 Require full dashboard coverage before adopting legacy freshness

When the regular token pipeline has just published its default 30-day snapshot before the first dashboard open, this branch treats it as fresh solely from its timestamp even though the dashboard requests scanDays == 365. capturedTokenPublication then falls back to that legacy snapshot and skips the independent dashboard fetch, so the dashboard's 365-day/All view is populated with only 30 days of history until another refresh is triggered. Reuse legacy freshness only when its history coverage and scope satisfy the dashboard request.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. label Aug 21, 2026
@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-cache-ttl branch from b577455 to d0c3479 Compare August 21, 2026 23:34

@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: d0c347973b

ℹ️ 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".

|| snapshot.metadata.timeZoneIdentifier == calendar.timeZone.identifier
else { return CostUsageCache() }
return Self.cache(from: snapshot)
return Self.cache(from: snapshot, mode: mode)

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 row tables in aggregate cache reads

When the Codex cache approaches its 25,000-row or 256 MB budget, .aggregateReport still calls readSnapshot(), whose implementation reads and copies every usage_rows.payload blob and every token snapshot before cache(from:mode:) discards those arrays. As a result, the new dashboard path avoids JSON decoding but still incurs full-cache SQLite I/O and memory allocation on first paint; use a mode-specific snapshot reader that does not query these tables.

Useful? React with 👍 / 👎.

@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-cache-ttl branch from d0c3479 to d8c5ae9 Compare August 21, 2026 23:42

@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: d8c5ae9269

ℹ️ 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".

Comment on lines 50 to 51
if let cached = self.readCachedEntries(identity: identity, since: since) {
return cached

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 Fall back when the cache read fails

When the matching SQLite cache cannot be read completely—for example, sqlite3_step returns SQLITE_BUSY/SQLITE_ERROR, or every cached payload fails decoding—readCachedEntries currently returns an empty array, and this newly unconditional cache-hit branch accepts it instead of reparsing the valid JSONL source. The OpenCodex source is then published as confirmed empty and remains so until the log identity changes; distinguish a successfully completed zero-row query from read/decoding failures and return nil for the latter.

Useful? React with 👍 / 👎.

@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-cache-ttl branch from 77b21f3 to 9cb04e2 Compare August 22, 2026 02:47

@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: 9cb04e241b

ℹ️ 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".

Comment on lines +82 to +83
WHERE timestamp >= ?
ORDER BY timestamp, request_id

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 Index the timestamp used by windowed cache reads

When an existing OpenCodex cache contains a large lifetime history, this query still performs a full scan of entries and sorts the matches because the schema only indexes the request_id primary key, not timestamp. Thus every dashboard cache hit remains proportional to the entire cache rather than the 365-day window this change is intended to load; add a (timestamp, request_id) index and ensure existing schema-version-1 databases receive it.

Useful? React with 👍 / 👎.

@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: 328a4360d6

ℹ️ 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".

Comment on lines +64 to +68
let snapshot = self.readSnapshot(skipRowTables: mode == .aggregateReport)
guard snapshot.metadata.timeZoneIdentifier == nil
|| snapshot.metadata.timeZoneIdentifier == calendar.timeZone.identifier
else { return CostUsageCache() }
return Self.cache(from: snapshot)
return Self.cache(from: snapshot, mode: mode)

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 Keep aggregate-hydrated pricing rows trustworthy

When cache-first hydration must rebuild a report from aggregates rather than use an exact previous report, the synthesized token-bearing rows have no eventIndex, so codexRowCostBreakdown marks them unstable and rowCostIsTrusted is always false. Standard usage then falls back to aggregate pricing that excludes the newly separated reasoning tokens, while priority evidence disables that fallback entirely and produces a nil cost. Fresh evidence is that the current patch now synthesizes reasoning/timestamp metadata, but this aggregate-mode path still discards its row-level pricing, so cached spend remains lower or unavailable until the live scan finishes.

Useful? React with 👍 / 👎.

Comment on lines +173 to +174
Self.bindAggregateValues(aggregate, to: insert, startingAt: 4)
Self.bind(aggregate.earliestTimestampUnixMs, to: insert, at: 20)

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 Bind timestamps to the actual SQL placeholders

For every persisted file aggregate, this statement has only 18 parameters: the 14 values bound starting at index 4 end at 17, making earliest_timestamp_ms parameter 18 rather than 20. SQLite therefore returns SQLITE_RANGE for this ignored bind and inserts NULL for the timestamp; the global aggregate insert repeats the same off-by-two error at index 19 instead of 17. Fresh evidence is that the patch added timestamp persistence to preserve date-sensitive pricing, but cached historical rows still lose that metadata and resolve without their original pricing date.

Useful? React with 👍 / 👎.

@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-cache-ttl branch from 328a436 to e4466e0 Compare August 22, 2026 09:08

@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: 63e8df340e

ℹ️ 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".

Comment on lines +79 to +80
$0 + ($1.inputTokens ?? 0) + ($1.cacheReadTokens ?? 0)
+ max(0, ($1.outputTokens ?? 0) - ($1.reasoningTokens ?? 0))

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 Stop subtracting reasoning from exclusive output

For this fixture, stored.data already exposes output exclusive of reasoning because the changed scanner stores deltaOutput - deltaReasoningTokens; expectedUnits was likewise updated to count exclusive output. Subtracting reasoningTokens here a second time therefore undercounts every reasoning-bearing entry and makes the final storedUnits == expectedUnits assertion fail. The repository-required full test run would expose this regression.

AGENTS.md reference: AGENTS.md:L23-L23

Useful? React with 👍 / 👎.

Comment on lines +35 to +36
if self.spendDashboardTokenSnapshotPublicationForCurrentConfig(for: provider) != nil {
return false

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 Persist the timestamp after a completed dashboard fetch

After the first successful or confirmed-empty dashboard scan, this branch treats the current publication as fresh whenever lastSpendDashboardTokenFetchAt is absent, but this change also removes the only production assignment to that dictionary and no success path replaces it. With an unchanged provider scope, the five-minute comparison is consequently never reached and ordinary pane reopens reuse the publication indefinitely; record the completion time when publishing a successful or empty result while leaving failures timestamp-free.

Useful? React with 👍 / 👎.

@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: 4381ec51ae

ℹ️ 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".

Comment on lines +382 to +384
let rowsByPath = mode == .scanReady
? Dictionary(grouping: snapshot.usageRows, by: \.path)
: [:]

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 Preserve request boundaries in aggregate hydration

When a cached day/model contains multiple standard requests, this aggregate-only path discards their individual rows and later synthesizes one row containing the entire daily input. Long-context pricing is request-scoped, so two 150k-token requests below a 200k threshold become one 300k-token row; because that synthetic row has no eventIndex, makeCodexBilledDayEntry rejects its row cost and codexAggregateCostUSD returns nil once the aggregate exceeds the threshold. The cache-first dashboard therefore loses an otherwise computable cost until the live scan finishes; retain per-request threshold evidence or a trustworthy persisted computed cost.

Useful? React with 👍 / 👎.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 22, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@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: 5fdf6d7d05

ℹ️ 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".

// back at the output rate (see `codexResolvedCostUSD`), keeping USD unchanged while
// making token buckets additive.
let deltaReasoningTokens = deltaReasoning ?? 0
let outputExcludingReasoning = max(0, deltaOutput - deltaReasoningTokens)

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 Preserve reasoning after making stored output exclusive

When reasoning exceeds the non-reasoning output remainder, this representation change truncates reasoning in project/model analytics. For example, an event with 100 output and 60 reasoning now stores (output: 40, reasoning: 60); CodexLocalProjectUsageIndexer forwards those values to CodexModelsUsageFragment, whose initializer in CodexModelsAnalyticsModels.swift clamps reasoning to outputTokens, reducing it to 40. Update that downstream invariant for the new exclusive-output representation so analytics retain the actual reasoning count.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added the rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. label Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review b8315b5

@clawsweeper

clawsweeper Bot commented Aug 25, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@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: da069eb4ae

ℹ️ 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".

private static func pricingSegments(
from rows: [CostUsageScanner.CodexUsageRow]) -> [StoredCodexPricingSegment]?
{
guard !rows.isEmpty else { return nil }

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 Persist an empty pricing-segment marker

When a current scanned session has codexRows = []—for example, a valid rollout with no token-count events—persistFile records hasRows: true, but this guard serializes pricingSegments as nil. aggregateReportNeedsLegacyRows then misclassifies the file as a base-schema-3 cache and reruns readSnapshot(skipRowTables: false), decoding every usage-row and token-snapshot payload in the database on each cache-first dashboard load. Fresh evidence after the earlier row-table skip fix is this nil/empty collision; persist [] for current empty row sets or otherwise distinguish them from legacy metadata.

Useful? React with 👍 / 👎.

@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-cache-ttl branch from da069eb to cccccb5 Compare August 26, 2026 01:06

Copy link
Copy Markdown
Contributor Author

Clean rebuild evidence for current head cccccb5a61209e4d298b93176192eeba21c4a3cc:

  • rebased on current main 26132179a
  • old unrelated SakanaUsageFetcherTests.swift change removed
  • current empty-cache marker fix is included, with aggregate-mode regression
  • make check passed (SwiftFormat 0 files; SwiftLint 0 violations)
  • focused swift test --filter 'CostUsageStoreAggregateModeTests|CostUsageStoreTests|ProviderArchitectureGatekeeperTests' passed: 124 tests in 3 suites
  • no provider credentials or Keychain reads used

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 26, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@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: cccccb5a61

ℹ️ 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".

Comment on lines +1136 to +1140
let requestEvidence = value.allRowsHaveKnownCost
|| value.requests.count < 2
|| value.input <= CostUsagePricing.codexPricingEvidenceThresholdTokens
? []
: value.requests

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 Retain explicit unpriced evidence in every segment

When a persisted row has unpricedTokens > 0 but its segment contains one request or no more than 200k input tokens, this stores an empty requestEvidence array; the synthesized segment row then has no unpricedTokens, so codexIncompletePricingEvidenceGroups no longer suppresses aggregate pricing. For partially unpriced rows whose model is otherwise resolvable, the cache-first dashboard can therefore display a complete estimated cost until the live scan replaces it; preserve the flag at segment level or retain request evidence whenever any row is explicitly unpriced.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Aug 26, 2026
@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-cache-ttl branch from 6faf0be to 25e9187 Compare August 26, 2026 02:12

Copy link
Copy Markdown
Contributor Author

Clean rebuild follow-up for current head 25e9187bac670b2aa1f286e4102b383ab8320081:

  • rebased on current main 26132179a
  • squashed the feature into one clean commit
  • removed unrelated SakanaUsageFetcherTests.swift changes
  • preserves the explicit empty-cache marker for current empty caches
  • preserves unpricedTokens evidence through aggregate segment hydration
  • added the aggregate-hydration cache-parity regression
  • make check passed (SwiftFormat 0 files; SwiftLint 0 violations)
  • focused swift test --filter 'CostUsageStoreAggregateModeTests|CostUsageStoreTests|ProviderArchitectureGatekeeperTests' passed: 125 tests in 3 suites
  • local sharded run: 931/933 selections passed; the two remaining CostUsagePricingTests expectation mismatches are outside this PR's changed files
  • no provider credentials or Keychain reads used

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 26, 2026

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@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: 25e9187bac

ℹ️ 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".

Comment on lines +99 to +103
static let compatibleLegacyBaseParserHashes: Set<String> = compatiblePredecessorParserHashes.union([
"3d0a976f7698a916", // Latest base-3 producer before the aggregate timestamp migration.
"dd19ffa2dcfa8d47", // Base-3 producer immediately before the spend-cache branch.
"1f23f8ea684bf2f2", // Earlier base-3 producer with the same aggregate table shape.
])

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 Include the immediate base-3 parser hash in migration

When upgrading a cache written by this commit's direct parent, the database contains base schema 3 with parser hash c6c46a376ba16304 (the parent value in CodexParserHash.generated.swift), but that hash is absent from this compatibility set. canMigrateLegacyBase therefore rejects the database as incompatible, and rebuildDatabase deletes it instead of running the new in-place migration, so existing users lose the warmed cache and must rescan their full Codex history before the cache-first dashboard is restored. Add the direct predecessor hash and cover that exact upgrade path rather than only synthetic older hashes.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Final-head re-review request for 25e9187bac670b2aa1f286e4102b383ab8320081:

  • clean single-commit rebuild; unrelated SakanaUsageFetcherTests.swift removed
  • prior explicit-unpricedTokens cache finding fixed with aggregate-hydration parity regression
  • CI run 32921837632 is fully green; PR is CLEAN/MERGEABLE
  • current review artifact found no new code issue; only real dashboard proof remains
  • the external proof runner could not start the guarded dashboard command because Corepack attempted to download pnpm 11.24.0

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 26, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Aug 26, 2026
@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-cache-ttl branch from 25e9187 to 1c94b36 Compare August 26, 2026 03:23
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

P1 fix for current head 1c94b36193da1d99055ba25c6d257c135edbe581:

  • added current main base-3 parser hash c6c46a376ba16304 to compatibleLegacyBaseParserHashes so an existing CostUsage database at 26132179a migrates in place instead of being rebuilt
  • added base schema upgrade migrates current main base-3 cache without rebuilding regression (mirrors the existing 3d0a976... migration test)
  • swiftlint --strict now 0 violations after line-length fix
  • clean diff remains 31 files; new head is single commit
  • previous CI 32921837632 was fully green; new CI is https://github.com/steipete/CodexBar/actions/runs/32926253312

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 26, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

Pushed fix 10d078b64 for the remaining OpenCodex fallback finding.

When the source log is temporarily unavailable, OpenCodexUsageStore.loadEntries now reads the retained cache before returning an empty source. The new regression missing source log uses retained cache without reparsing verifies the cached row is returned and no log bytes are read.

Validation on the pushed head:

  • swift test --filter 'CodexBarTests.OpenCodexUsageStore(IncrementalTests|WindowTests)' — 29 tests passed
  • make check — passed; SwiftLint 0 violations

This is isolated-fixture evidence only; no provider credentials or Keychain reads were used. Real dashboard interaction proof is still pending.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 26, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@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: 10d078b64b

ℹ️ 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".

// A retained cache is still useful while the append-only source log is
// temporarily unavailable (for example during rotation or a sync gap).
// Read it before treating the missing log as an empty source.
return self.readCachedState(since: since)?.entries ?? []

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 Validate the cached cursor path before fallback

When OPENCODEX_HOME changes between launches and the new home's usage.jsonl is missing, this fallback reads the process-wide OpenCodex cache without checking that parseCursor.path matches logURL.path. The dashboard will therefore attribute and display usage retained from the previous OpenCodex home instead of reporting the newly selected source as unavailable; only reuse the cache when its cursor belongs to the requested log path.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Aug 26, 2026
@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-cache-ttl branch from 10d078b to fd4dc88 Compare August 26, 2026 15:07
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

Pushed fix fd4dc8853 to bind the retained OpenCodex cache fallback to the requested log path.

Changes:

  • OpenCodexUsageStore.loadEntries checks cached.parseCursor.path == logURL.path before returning the retained cache on missing log files, preventing cross-home cache reuse when switching homes.
  • Added regression missing source log for different path returns empty without returning unrelated cache verifying that requesting an unavailable different home log returns empty without reading cached entries.
  • Regression missing source log uses retained cache without reparsing verifies the same-path temporary log absence still uses the retained cache.

Validation on the pushed head:

  • swift test --filter 'CodexBarTests.OpenCodexUsageStore(IncrementalTests|WindowTests)' — 30 tests passed
  • make check — passed; SwiftLint 0 violations

This is isolated-fixture evidence only; no provider credentials or Keychain reads were used. Real dashboard interaction proof remains pending.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 26, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

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

Labels

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: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants