Skip to content

fix: preserve zero-usage days in Codex cost chart - #3232

Merged
steipete merged 2 commits into
steipete:mainfrom
findwangdi:fix/codex-inline-chart-calendar-gaps
Aug 29, 2026
Merged

fix: preserve zero-usage days in Codex cost chart#3232
steipete merged 2 commits into
steipete:mainfrom
findwangdi:fix/codex-inline-chart-calendar-gaps

Conversation

@findwangdi

@findwangdi findwangdi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Preserve calendar spacing in the Codex inline cost chart without treating unknown costs as zero. The repair keeps one slot per requested day, uses the same pinned bucket time zone as the scanner, and fits 1–365 days within the existing menu width. Other providers retain their existing sparse-history presentation.

Missing dates become zero only once history coverage is established. Existing unpriced rows remain unknown even after scanning completes. Accessibility labels explicitly say Unknown, and unknown values do not affect the chart scale. The range stays anchored to the snapshot date rather than moving when a stale snapshot is reopened.

The provider owns the calendar-slot capability; the shared renderer only lays out points and optional values. Both the menu and Provider settings pass the bucket calendar. No scanning, stored-history, cache, account ownership, credential, or network behavior changes.

Thanks @findwangdi for the original calendar-gap fix. This maintainer follow-up addresses the coverage, time-zone, and long-history issues from review, with contributor credit preserved.

Verification

  • Baseline on the original PR reproduced five expected regression assertion failures: unpriced dates disappeared and an unscanned date became $0.00.
  • Before-fix production-renderer screenshots at 310 points confirmed that a 365-day history pushed activity bars outside the visible chart.
  • Regression coverage includes unknown/zero/priced values, pinned midnight and both DST transitions, stale snapshot anchoring, provider isolation, account selection, Provider-settings calendar wiring, and width bounds at 1/4/30/90/365 days.
  • Native-log fixtures use the real scanner and fetcher with isolated temporary roots, no pricing refresh, and no Pi merge; they exercise nonempty bounded catch-up followed by completed history. Opt-in screenshots render the actual production view in light/dark, including native-derived 1/4/30/365-day histories and accessibility text. No real accounts, Keychain reads, or app relaunch are involved.
  • swift test --jobs 8 --filter 'InlineCostHistoryCalendarTests|InlineCostHistoryScreenshotTests|InlineCostHistoryDashboardLabelTests|CodexProfileHomeAccountTests|ProviderArchitectureGatekeeperTests': 67 tests passed, plus the opt-in production renderer. The renderer emitted light/dark proof for constructed and native-derived histories and verified actual accessibility labels. Run it with CODEXBAR_INLINE_COST_PROOF_DIR=<output-directory>; ordinary runs skip screenshot generation.
  • make check: passed, including 73 cleanup tests (one platform skip), sharding checks, and strict lint with zero violations in 2,039 files.
  • Independent source review found no actionable production defect; final Codex autoreview completed clean after the renderer caught and we fixed the enclosing chart label overriding individual accessible day labels.
  • Exact-head CI: all green for 5cfcfb8cdefd3fa7c9f3e214ee3165c14e78de36 in run 33231620211, including both macOS test shards, plugin-engine checks, Linux x64/ARM64/musl builds, lint, and the aggregate gate. The musl SDK installer initially crashed before CodexBar compilation; the unchanged-candidate retry passed installation and the complete build. GitGuardian also passed.
  • Local full make test: failed, not counted as green. Groups 1–28 passed; group 29 failed in the unchanged CodexUsageFetcherFallbackTests suite on initialization and elapsed-time assertions, including its automatic retry. A standalone rerun and a checkpoint-validated continuation reproduced those failures, so the remaining local groups were not executed. The same RPC failure was recorded before this PR and then passed unchanged in the prior triage pass. Two captured temporary Python fixture processes were still at dynamic-loader entry, with valid pipes but no interpreter runtime loaded; another sample showed real login-shell PATH capture during fixture setup. This establishes a local startup limitation, not a chart assertion failure. The existing CODEXBAR_TEST_SUITE_TIMEOUT=600 outer watchdog was used; no individual assertion or production timeout was relaxed. Hosted macOS tests provide the completed full-suite proof.
  • Earlier attempts: the first check hit two cleanup-fixture observation deadlines during compilation; the unchanged cleanup suite passed afterward. One focused build was interrupted during prolonged compiler filesystem waits, then retried with --jobs 8 and a task-local TMPDIR. The first actual renderer execution exposed the accessibility-label bug; the final rerun passed. None of those earlier attempts is counted as green.

Production-renderer proof

The before images use the original PR code. Both sides use the same synthetic four-day history: priced August 21, absent August 22, unpriced August 23, and priced August 24. The repair retains the unpriced day's slot instead of compressing the chart. At 365 days the original renderer pushes activity outside the visible width; the repaired renderer retains all slots within 310 points.

Window Original PR Repaired
4 days Before: unpriced date omitted After: unpriced date retains its slot
365 days Before: activity clipped After: all dates fit

The following images come from temporary native Codex JSONL files through the real scanner, fetcher, card model, and renderer. Prices are fixture/bundled list-price estimates, not live billing verification. The unknown model's day stays blank and accessible as Unknown after catch-up.

Native four-day completed history
Native year-long completed history, dark

Final accessible four-day labels from the actual production view:

2026-08-21: $3.00
2026-08-22: $0.00
2026-08-23: Unknown
2026-08-24: $4.00

改动内容与目的:
- 为 token 成本 provider 增加补齐缺失日历日的展示能力,并仅在 Codex 启用。
- 将缺少记录的日期建模为零值点,避免连续日期被压缩;保留已有但无法定价记录的 nil 语义。
- 补充零用量日期、账户切换和架构门禁回归覆盖。
@clawsweeper

clawsweeper Bot commented Aug 27, 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: 72714ea2c7

ℹ️ 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 thread Sources/CodexBar/InlineUsageDashboardContent.swift Outdated

@steipete steipete left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks @findwangdi — preserving calendar spacing in the inline Codex chart is a useful fix. I reviewed all six changed files at 72714ea2c7d2f103acc3834a077247103f00a370 and traced the scanner, publication, settings, and production renderer. Three issues need addressing before this can land:

  1. Incomplete history is not zero usage. The new helper fills dates based only on the provider capability. Initial bounded Codex scans can publish nonempty snapshots with historyCoverageIsEstablished == false, so missing dates may still have unscanned sessions. This confirms the existing automated finding. Only synthesize zero costs when coverage is established; unknown dates must not announce $0.00.
  2. Use the scanner's bucket time zone. UsageStore+TokenCost passes settings.costUsageBucketCalendar to the fetcher, while the new helper defaults to Calendar.current and its caller supplies no calendar. With Los Angeles pinned and the system in Shanghai at August 24, 00:30, a one-day snapshot correctly contains August 23 usage. The helper instead generates August 24, drops the real row, and substitutes zero. Pass the authoritative bucket calendar through presentation and cover midnight/DST boundaries.
  3. Keep long histories within the renderer's width. The supported 365-day setting now produces 365 points even for one activity day. MiniUsageBars still uses an HStack with two-point spacing: the gaps alone require 728 points, exceeding the normal 310-point menu. This existed for dense histories, but the new fill introduces it for sparse histories too. Adapt the layout and verify the actual production view at 1, 30, and 365 days; the precise clipping/appearance has not yet been captured.

The ownership boundary should remain small: calendar position and whether a day's cost is known are separate facts. Existing nil-cost rows still disappear through compactMap; keeping their date slots without inventing a cost would also avoid leaving part of the original compression problem behind. I found no account-isolation change, and this review does not establish a connection to #3209's refresh issue.

This is source review, not independent execution of the PR's claimed checks. Before landing, please add deterministic temporary-log → scanner → snapshot → production-chart coverage for partial/completed scans, zero/unknown costs, pinned calendars, and the long-history layout, plus before/after pictures of the real view. No live account credentials are needed for these fixtures. Maintainer changelog/credit can be added during landing.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal priority bug or improvement with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Aug 27, 2026
@clawsweeper

clawsweeper Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed August 28, 2026, 11:36 PM ET / August 29, 2026, 03:36 UTC.

ClawSweeper review

What this changes

The PR makes Codex inline cost charts preserve each calendar day while showing confirmed zero usage separately from unknown or unpriced history.

Regression provenance

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

Merge readiness

⚠️ Ready for maintainer review - 2 items remain

Keep open for normal merge review: current main does not contain this chart behavior, and the PR’s introduced implementation addresses the prior coverage, time-zone, and width concerns without a definite new defect.

Priority: P2
Reviewed head: 5cfcfb8cdefd3fa7c9f3e214ee3165c14e78de36

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) Strong targeted proof and broad regression coverage support a mergeable implementation, subject to normal pending CI.
Proof confidence 🦞 diamond lobster (5/6) ✨ media proof bonus Sufficient (linked_artifact): The PR body supplies after-fix production-renderer screenshots and an accessible output transcript from the native Codex JSONL scanner through fetcher, card model, and SwiftUI renderer; the introduced source implements that same coverage-aware chart path.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (linked_artifact): The PR body supplies after-fix production-renderer screenshots and an accessible output transcript from the native Codex JSONL scanner through fetcher, card model, and SwiftUI renderer; the introduced source implements that same coverage-aware chart path.
Evidence reviewed 5 items Calendar-slot semantics: The introduced chart-model path builds the requested date range using the selected bucket time zone, preserves an existing entry’s nil cost as unknown, and zero-fills only absent days after history coverage is established.
Scanner calendar contract: The existing cost-bucket helper constructs a Gregorian calendar with the configured IANA time zone, matching the PR’s rendering calendar normalization.
Focused regression coverage: The added tests cover unknown versus zero values, incomplete catch-up, DST and midnight boundaries, provider isolation, and width fitting through 365 days.
Findings None None.
Security None None.

How this fits together

CodexBar scans local Codex usage into daily cost snapshots and renders those snapshots in the menu card and provider settings. The change carries the scanner’s bucket time zone into both chart-model entry points and changes how missing daily slots are displayed.

flowchart LR
A[Local Codex usage history] --> B[Daily cost snapshot]
B --> C[Coverage and bucket time zone]
C --> D[Menu card chart model]
C --> E[Provider settings chart model]
D --> F[Inline cost bars]
E --> F
Loading

Before merge

  • Resolve merge risk (P1) - The supplied attachment URLs could not be independently reopened because GitHub DNS resolution failed in this review environment, although the frozen PR body contains the rendered-output evidence.
  • Complete next step (P2) - No concrete repair is needed; retain this PR for normal required-check completion and maintainer merge review.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production versus test delta production +93/-19, tests +411/-5, docs/changelog +2 The implementation is accompanied by substantially broader regression coverage for the new calendar and accessibility semantics.
Affected surfaces 12 files affected The change reaches both menu and provider-settings model entry points while keeping scanner and persistence code unchanged.

Merge-risk options

  • Exact-head CI remains pending; merge should wait for the normal required checks.

Maintainer options:

  1. Decide the mitigation before merge
    Land the focused Codex-only presentation change once required checks finish, retaining unknown values until scan coverage is established and the shared provider capability boundary.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Technical review

Best possible solution:

Land the focused Codex-only presentation change once required checks finish, retaining unknown values until scan coverage is established and the shared provider capability boundary.

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

Yes. The added focused tests and supplied production-renderer scenario cover a four-day snapshot with priced, missing, and unpriced days plus bounded-scan coverage transitions.

Is this the best way to solve the issue?

Yes. A Codex-only provider capability, with the shared renderer handling optional values, preserves other providers’ sparse-history behavior and matches the existing ownership boundary.

AGENTS.md: found and applied where relevant.

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

Labels

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body supplies after-fix production-renderer screenshots and an accessible output transcript from the native Codex JSONL scanner through fetcher, card model, and SwiftUI renderer; the introduced source implements that same coverage-aware chart path.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (linked_artifact): The PR body supplies after-fix production-renderer screenshots and an accessible output transcript from the native Codex JSONL scanner through fetcher, card model, and SwiftUI renderer; the introduced source implements that same coverage-aware chart path.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.
  • remove rating: 🦪 silver shellfish: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove merge-risk: 🚨 other: Current PR review selected no merge-risk labels.

Label justifications:

  • P2: This is a bounded correction to Codex cost-chart presentation with limited blast radius.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (linked_artifact): The PR body supplies after-fix production-renderer screenshots and an accessible output transcript from the native Codex JSONL scanner through fetcher, card model, and SwiftUI renderer; the introduced source implements that same coverage-aware chart path.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body supplies after-fix production-renderer screenshots and an accessible output transcript from the native Codex JSONL scanner through fetcher, card model, and SwiftUI renderer; the introduced source implements that same coverage-aware chart path.

Evidence

What I checked:

  • Calendar-slot semantics: The introduced chart-model path builds the requested date range using the selected bucket time zone, preserves an existing entry’s nil cost as unknown, and zero-fills only absent days after history coverage is established. (Sources/CodexBar/InlineUsageDashboardContent.swift:192, 5cfcfb8cdefd)
  • Scanner calendar contract: The existing cost-bucket helper constructs a Gregorian calendar with the configured IANA time zone, matching the PR’s rendering calendar normalization. (Sources/CodexBarCore/CostUsageModels.swift:1253, 5cfcfb8cdefd)
  • Focused regression coverage: The added tests cover unknown versus zero values, incomplete catch-up, DST and midnight boundaries, provider isolation, and width fitting through 365 days. (Tests/CodexBarTests/InlineCostHistoryCalendarTests.swift:11, 5cfcfb8cdefd)
  • History and current-main separation: The exact PR head is a maintainer follow-up atop the original contribution; its base is current main and it is not contained by a local release tag, so the requested behavior remains unmerged. (Sources/CodexBar/InlineUsageDashboardContent.swift:192, 5cfcfb8cdefd)
  • After-fix behavior evidence: The frozen PR body supplies before/after production-renderer images, native scanner-to-renderer fixture proof, and the final accessible day labels including a confirmed $0.00 and an Unknown entry. (5cfcfb8cdefd)

Likely related people:

  • steipete: Peter Steinberger authored the current follow-up and the recent cost-summary renderer work in this path. (role: recent area contributor; confidence: high; commits: 5cfcfb8cdefd, 61c7e1ce821a; files: Sources/CodexBar/InlineUsageDashboardContent.swift, Sources/CodexBar/PreferencesProvidersPane.swift, Sources/CodexBar/StatusItemController+MenuCardModel.swift)

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-27T09:19:32.331Z sha 72714ea :: needs real behavior proof before merge. :: [P2] Gate zero-filled dates on established history coverage

Keep unknown costs distinct from zero, thread the bucket calendar through both card surfaces, and bound daily bar geometry. Verify native scan catch-up, accessibility, and production-renderer output.

Co-authored-by: wangdi <di.wang@ipinyou.com>
@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Aug 29, 2026

@steipete steipete left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

The maintainer repair addresses all three concerns from my original review: coverage-aware unknown/zero semantics, the scanner's pinned bucket calendar in both presentation entry points, and bounded layout through 365 days. Actual production rendering also exposed and now verifies the accessibility containment fix.

Reviewed the complete repaired delta, adjacent call sites, native-log regressions, and before/after renderer proof. Focused tests and make check passed; independent source review and Codex autoreview found no actionable defect. The latest automated review covers the repaired head and has no code finding. Its attachment-access limitation does not block this review: I inspected the generated production PNGs locally before uploading them.

The local full matrix remains red in the unchanged RPC fixture suite; the same failure predates this PR. Captured fixture processes stalled at dynamic-loader entry before the Python interpreter started, and the tests also consult the real login shell. This is not counted as a local pass. Both hosted macOS test shards passed on this candidate. No RPC code or timeout has been changed to mask the failure.

Exact-head CI is now fully green in run 33231620211, including the unchanged-candidate musl retry. GitGuardian passed too. This supersedes my original changes-requested review.

Thanks @findwangdi for the original calendar-gap fix. Contributor credit is preserved.

@steipete
steipete merged commit 41c53c3 into steipete:main Aug 29, 2026
15 of 17 checks passed
@steipete

Copy link
Copy Markdown
Owner

Landed as 41c53c3. Thanks @findwangdi — your original calendar-gap fix is preserved with co-author credit and a changelog entry.

The maintainer repair keeps each calendar date separate from whether its cost is known. Unscanned and unpriced days stay Unknown, confirmed missing days become zero only after coverage is established, both presentation entry points use the scanner's bucket time zone, and up to 365 bars fit the menu. Actual rendering also caught and fixed the enclosing accessibility label masking individual days. Scanner, persistence, credentials, and provider account ownership are unchanged.

Verification on the exact PR head, whose tree matches the merged commit:

  • Original-PR regression run reproduced five expected assertion failures. Repaired focused run passed 67 tests across calendar semantics, midnight/DST, stale snapshots, provider/account isolation, settings wiring, and width bounds.
  • Command: swift test --jobs 8 --filter 'InlineCostHistoryCalendarTests|InlineCostHistoryScreenshotTests|InlineCostHistoryDashboardLabelTests|CodexProfileHomeAccountTests|ProviderArchitectureGatekeeperTests', with CODEXBAR_SUPPRESS_TEST_KEYCHAIN_ACCESS=1, CODEXBAR_TEST_CODEX_FILE_ISOLATION=1, and an opt-in CODEXBAR_INLINE_COST_PROOF_DIR output directory. The allow-Keychain and real-Codex-fixture flags were unset.
  • The opt-in production renderer passed separately in that run, producing 30 light/dark images, including temporary native JSONL → scanner → fetcher → model → renderer proof at 1/4/30/365 days. Actual accessibility labels include both $0.00 and Unknown. Before/after images are in the PR description. These are synthetic local fixtures and list-price estimates, not live account or billing verification; no app relaunch or real credential access was used.
  • make check passed, including 73 process-cleanup tests (one platform skip), sharding checks, and strict lint with zero violations. Independent source review and final Codex autoreview found no actionable defect.
  • Exact-head CI run 33231620211 finished fully green: both macOS test shards and plugin-engine checks, Linux x64/ARM64/musl builds, lint, and the aggregate gate. GitGuardian passed. The musl SDK installer initially crashed before compilation; retrying the unchanged candidate passed.

Important local caveat: make test did not finish green. Its first 28 groups passed; group 29 failed in the unchanged RPC fixture suite, including retries and an isolated run. A checkpoint-validated continuation reproduced the failure and did not reach the remaining groups. This same failure predates the chart PR. Samples captured two fixture children stalled at dynamic-loader entry before Python executed, and real login-shell PATH capture in fixture setup. No RPC timeout or assertion was relaxed. The completed hosted macOS suite is the full-suite proof; the failed local runs are not counted as passes.

The checkout is back on main, fast-forwarded, clean, and byte-for-byte tree-equivalent to the tested PR head. No release was published, and no related refresh issue was closed without proof.

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

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants