Skip to content

Add focused daily spend ledger - #2615

Closed
sahilaidev wants to merge 2 commits into
steipete:mainfrom
sahilaidev:agent/daily-spend-ledger-focused
Closed

Add focused daily spend ledger#2615
sahilaidev wants to merge 2 commits into
steipete:mainfrom
sahilaidev:agent/daily-spend-ledger-focused

Conversation

@sahilaidev

@sahilaidev sahilaidev commented Aug 3, 2026

Copy link
Copy Markdown

Summary

This is the focused follow-up requested in #2485: the daily spend ledger only.

  • add a read-only daily ledger below the existing spend chart
  • aggregate spend, tracked tokens, and requests per provider and day
  • fill covered days with zero usage instead of dropping them
  • restrict combined rows to the exact common coverage window across providers
  • keep unavailable cost, request, or token data explicit rather than presenting partial totals

This PR does not add currency conversion, exchange-rate polling, preference changes, packaging changes, or fork customization. It uses the app-wide currency presentation already present upstream.

Aggregation semantics

Request totals are derived from complete daily rows when a snapshot does not provide last30DaysRequests, which covers sources such as Codex and OpenCode Go. If a covered row omits its request count, arithmetic overflows, or a provided aggregate contradicts the daily rows, request totals fail closed to unavailable.

The ledger uses the intersection of every provider's established coverage. It renders every day in that intersection, including zero-usage days, and renders no combined ledger when provider coverage is disjoint. Sources without a proven aggregate cost remain unavailable instead of becoming zero-spend rows. The existing chart remains unchanged and the ledger is read-only, avoiding selection snapping from chart-only days outside common ledger coverage.

Review fixes

  • require every ledger source to have a proven summary cost before emitting daily rows
  • include last30DaysRequests in the snapshot revision so cached/provider-derived aggregate changes rebuild the ledger
  • cover both paths with focused regressions, including a same-publication-revision controller reload

Verification

  • make check
    • 22 localization catalogs checked
    • SwiftFormat clean
    • SwiftLint: 0 violations
    • packaging, documentation, repository-size, and shell checks passed
  • focused post-fix suites: 32 tests passed
    • SpendDashboardDailyLedgerTests: 7 tests
    • SpendDashboardControllerTests and revision coverage: 25 tests across 3 suites
  • make test: 810/810 selections passed in 68 groups
    • no failures, retries, or timeouts
  • rebased onto current upstream/main before final verification

Runtime proof

The original implementation was verified in a signed local macOS build with 30 days of Codex history. After the review fixes, the production SwiftUI ledger component was rendered again with synthetic Claude and OpenAI data so no personal spend history is exposed.

Synthetic daily spend ledger showing provider icons, tracked tokens, requests, and estimated spend

The synthetic capture shows combined-provider totals, single-provider days, token and request columns, and the app's native dark Settings presentation.

@sahilaidev
sahilaidev marked this pull request as ready for review August 3, 2026 18:13
@clawsweeper clawsweeper Bot added 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. P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. labels Aug 3, 2026

@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: 96157c4fc5

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

calendar: Calendar) -> [DailySummary]
{
guard !summaries.isEmpty,
summaries.allSatisfy({ !$0.hasInvalidCostHistory }),

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 proven cost totals before emitting ledger rows

When a snapshot establishes history coverage but has both an empty daily array and a nil last30DaysCostUSD—as an empty scanner result can—hasInvalidCostHistory remains false even though InputSummary.totalCost is nil. This guard therefore accepts the source, and dailyProviderRow fills every covered day with 0, causing the new ledger to report daily $0 values while the aggregate and chart correctly report spend as unavailable; require complete cost proof, such as a non-nil summary total, before constructing the ledger.

Useful? React with 👍 / 👎.

Comment on lines +578 to +579
guard let aggregate = input.snapshot.last30DaysRequests else { return true }
return Self.nonnegative(aggregate) == dailyTotal

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 Include the request aggregate in source revisions

The ledger's request completeness now depends on last30DaysRequests, but SpendDashboardSource.snapshotRevision fingerprints the token/cost aggregates and daily request counts without fingerprinting this aggregate. If a provider-derived or cached snapshot is installed without advancing its publication revision and only this aggregate changes, the pane's configuration remains equal and the controller does not rebuild, leaving request totals available when they should fail closed (or vice versa); add last30DaysRequests to the snapshot revision alongside the other aggregates.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. label Aug 3, 2026
@clawsweeper

clawsweeper Bot commented Aug 3, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed August 3, 2026, 3:00 PM ET / 19:00 UTC.

ClawSweeper review

What this changes

This PR adds a read-only per-day ledger beneath the existing Usage & Spend chart, showing each day’s provider activity, tracked tokens, request totals, and estimated spend.

Merge readiness

Blocked until real behavior proof is added - 11 items remain

Keep open: the same two P2 correctness defects remain at the reviewed head, and the claimed local runtime verification has no inspectable after-fix evidence.

Priority: P2
Reviewed head: 96157c4fc5f4b1c371b07f9cbd525d6dea0d69d3
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The branch is focused and tested, but two correctness blockers and missing inspectable runtime proof prevent merge readiness.
Proof confidence 🦪 silver shellfish (2/6) Needs real behavior proof before merge: The PR describes a signed local run but attaches no inspectable screenshot, recording, terminal output, or redacted log; add a synthetic or redacted native-app capture after the repairs, removing personal spend and other private data. 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 🦪 silver shellfish (2/6) 2 actionable review findings remain.

Verification

Check Result Evidence
Real behavior Needs proof Needs real behavior proof before merge: The PR describes a signed local run but attaches no inspectable screenshot, recording, terminal output, or redacted log; add a synthetic or redacted native-app capture after the repairs, removing personal spend and other private data. 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 Incomplete-cost source can become a zero-spend ledger: The new ledger only rejects summaries flagged with invalid daily cost history. A covered snapshot with no daily rows and no aggregate cost has totalCost == nil without setting that flag, so dailyProviderRow emits zero rows even though the existing aggregate remains unavailable.
Request availability is not included in dashboard invalidation: The new request-completeness path depends on last30DaysRequests, but current-main snapshot revision encoding fingerprints token and cost aggregates plus daily request rows, not the request aggregate itself. A changed aggregate can therefore leave an already-rendered ledger stale.
Prior blockers remain at the same PR head: The latest completed ClawSweeper cycle raised these two exact P2 findings against 96157c4; the supplied PR context and local commit inspection still identify that SHA as the current head.
Findings 2 actionable findings [P2] Require proven cost totals before emitting ledger rows
[P2] Fingerprint the request aggregate used by the ledger
Security None None.

How this fits together

CodexBar collects provider usage snapshots and builds a shared spend-dashboard model for the Settings UI. The proposed ledger consumes those snapshots alongside the existing chart, so its totals must preserve the dashboard’s established completeness and refresh semantics.

flowchart LR
    A[Provider usage snapshots] --> B[Coverage and completeness checks]
    B --> C[Spend dashboard model]
    C --> D[Existing spend chart]
    C --> E[Daily ledger aggregation]
    E --> F[Settings spend dashboard]
    A --> G[Snapshot revision fingerprint]
    G --> C
Loading

Decision needed

Question Recommendation
Should CodexBar add a daily spend ledger as a permanent new Settings dashboard surface after its correctness and proof blockers are resolved? Sponsor the daily ledger: Approve the product direction, then require the two correctness repairs and inspectable synthetic or redacted runtime proof before merge.

Why: The repository vision requires sign-off for new features, and this PR introduces a persistent new UI capability rather than a repair to an existing dashboard contract.

Before merge

  • Add real behavior proof - Needs real behavior proof before merge: The PR describes a signed local run but attaches no inspectable screenshot, recording, terminal output, or redacted log; add a synthetic or redacted native-app capture after the repairs, removing personal spend and other private data. 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.
  • Require proven cost totals before emitting ledger rows (P2) - The guard accepts a covered source whose daily data is empty and whose aggregate cost is unavailable, because hasInvalidCostHistory stays false. dailyProviderRow then fills the coverage window with zero-cost rows even though the existing dashboard correctly reports total spend as unavailable; require a proven summary cost before constructing ledger rows and add this regression.
  • Fingerprint the request aggregate used by the ledger (P2) - The ledger now uses last30DaysRequests to decide whether request totals are available, but the dashboard configuration fingerprint in SpendDashboardController does not include that value. If only the aggregate changes, the controller can retain stale ledger request totals; add it to the revision encoding and cover the refresh path.
  • Resolve merge risk (P1) - An unavailable provider cost history can be rendered as a sequence of $0 ledger rows, which misstates spend rather than preserving the dashboard’s unavailable state.
  • Resolve merge risk (P1) - A refresh that changes only last30DaysRequests can leave the ledger showing obsolete request availability or totals.
  • Resolve merge risk (P1) - No attached redacted or synthetic capture shows the new native Settings UI after the fix, so the stated signed-build verification cannot be independently reviewed.
  • Complete next step (P2) - A maintainer must first sponsor this new dashboard surface under VISION.md; the contributor must also resolve the two concrete P2 defects and provide real native-app evidence before merge.
  • Improve patch quality - Fix the unavailable-cost and request-fingerprint defects with focused regressions.
  • Improve patch quality - Attach a redacted or synthetic native-app capture showing daily rows and a refresh result.
  • Improve patch quality - Obtain maintainer sign-off for the new ledger feature; after adding proof, update the PR body or ask a maintainer to comment @clawsweeper re-review if needed.

Findings

  • [P2] Require proven cost totals before emitting ledger rows — Sources/CodexBar/SpendDashboardModel.swift:587-588
  • [P2] Fingerprint the request aggregate used by the ledger — Sources/CodexBar/SpendDashboardModel.swift:305
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Change size production +274/-4, tests +199 The feature adds a substantial model and Settings UI surface, so correctness and native behavior proof matter before accepting the ongoing maintenance cost.
Files affected 3 files affected The patch is focused on one model, one Settings view, and dedicated ledger tests.

Merge-risk options

Maintainer options:

  1. Repair ledger completeness and refresh semantics (recommended)
    Require unavailable cost histories to suppress ledger rows and add the request aggregate to the dashboard revision fingerprint, with regressions for both cases.
  2. Pause the new ledger surface
    If maintainers do not want to own a new permanent spend-dashboard view, close the feature rather than merge an additional supported UI path.

Technical review

Best possible solution:

If the feature is sponsored, preserve unavailable costs as unavailable, fingerprint every aggregate used by ledger completeness, add focused regressions, and attach a redacted or synthetic native-app capture that visibly demonstrates refreshed ledger rows.

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

Yes, by source: create an established-coverage snapshot with empty daily data and no aggregate cost, then build the dashboard model; the proposed ledger accepts it and emits zero-cost rows while the aggregate stays unavailable. A second source path changes only last30DaysRequests and leaves the current revision fingerprint unchanged.

Is this the best way to solve the issue?

No. The scoped model/UI approach is plausible, but it is not ready until it preserves unavailable-cost semantics, invalidates on all request inputs it consumes, and has inspectable runtime proof; the new feature also needs the repository’s required sign-off.

Full review comments:

  • [P2] Require proven cost totals before emitting ledger rows — Sources/CodexBar/SpendDashboardModel.swift:587-588
    The guard accepts a covered source whose daily data is empty and whose aggregate cost is unavailable, because hasInvalidCostHistory stays false. dailyProviderRow then fills the coverage window with zero-cost rows even though the existing dashboard correctly reports total spend as unavailable; require a proven summary cost before constructing ledger rows and add this regression.
    Confidence: 0.98
  • [P2] Fingerprint the request aggregate used by the ledger — Sources/CodexBar/SpendDashboardModel.swift:305
    The ledger now uses last30DaysRequests to decide whether request totals are available, but the dashboard configuration fingerprint in SpendDashboardController does not include that value. If only the aggregate changes, the controller can retain stale ledger request totals; add it to the revision encoding and cover the refresh path.
    Confidence: 0.97

Overall correctness: patch is incorrect
Overall confidence: 0.97

AGENTS.md: found and applied where relevant.

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

Labels

Label changes:

  • add P2: The PR adds a limited-scope dashboard feature but currently has two concrete correctness defects that can misrepresent provider usage data.
  • remove P3: Current review triage priority is P2, so this older priority label is no longer current.

Label justifications:

  • P2: The PR adds a limited-scope dashboard feature but currently has two concrete correctness defects that can misrepresent provider usage data.
  • merge-risk: 🚨 other: Merging can present unavailable or stale spend/request data as valid ledger totals, a user-visible financial-reporting risk not covered by the named risk classes.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR describes a signed local run but attaches no inspectable screenshot, recording, terminal output, or redacted log; add a synthetic or redacted native-app capture after the repairs, removing personal spend and other private data. 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:

  • Incomplete-cost source can become a zero-spend ledger: The new ledger only rejects summaries flagged with invalid daily cost history. A covered snapshot with no daily rows and no aggregate cost has totalCost == nil without setting that flag, so dailyProviderRow emits zero rows even though the existing aggregate remains unavailable. (Sources/CodexBar/SpendDashboardModel.swift:587, 96157c4fc5f4)
  • Request availability is not included in dashboard invalidation: The new request-completeness path depends on last30DaysRequests, but current-main snapshot revision encoding fingerprints token and cost aggregates plus daily request rows, not the request aggregate itself. A changed aggregate can therefore leave an already-rendered ledger stale. (Sources/CodexBar/SpendDashboardController.swift:389, e12a824fdb49)
  • Prior blockers remain at the same PR head: The latest completed ClawSweeper cycle raised these two exact P2 findings against 96157c4; the supplied PR context and local commit inspection still identify that SHA as the current head. (Sources/CodexBar/SpendDashboardModel.swift:305, 96157c4fc5f4)
  • Feature direction needs sign-off: The repository VISION.md classifies new features as requiring sign-off; this adds a new Settings dashboard surface rather than repairing established behavior. (VISION.md:7, e12a824fdb49)
  • Current-main feature ownership: Blame attributes the current dashboard’s snapshot-revision path to Peter Steinberger at the shallow current-main boundary, and repository history records the unified dashboard introduction in commit 0397529ae6e5d86df78cca7c18362fb720572c50. (Sources/CodexBar/SpendDashboardController.swift:383, 6a16c23313a7)
  • Not implemented on current main or the latest release: The PR head is not an ancestor of current main; the latest release is v0.47.0 at 6a16c233, so this proposed ledger is neither merged nor released. (Sources/CodexBar/SpendDashboardModel.swift:261, e12a824fdb49)

Likely related people:

  • Peter Steinberger: Current-main blame places the dashboard snapshot-revision encoder at Peter’s shallow-boundary commit, and the current release tree owns the surrounding spend dashboard implementation. (role: recent dashboard and refresh-path contributor; confidence: medium; commits: 6a16c23313a7; files: Sources/CodexBar/SpendDashboardController.swift, Sources/CodexBar/SpendDashboardModel.swift, Sources/CodexBar/PreferencesSpendDashboardPane.swift)
  • Alec Gutman, Chip: Repository add-history identifies this author on the commit that introduced the unified usage and spend dashboard surface that the ledger extends. (role: unified dashboard introducer; confidence: medium; commits: 0397529ae6e5; files: Sources/CodexBar/SpendDashboardModel.swift, Sources/CodexBar/SpendDashboardController.swift, Sources/CodexBar/PreferencesSpendDashboardPane.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-03T18:29:27.166Z sha 96157c4 :: needs real behavior proof before merge. :: [P2] Require proven cost totals before emitting ledger rows | [P2] Fingerprint the request aggregate used by the ledger

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. and removed P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. labels Aug 3, 2026
@sahilaidev
sahilaidev force-pushed the agent/daily-spend-ledger-focused branch from 96157c4 to e897510 Compare August 3, 2026 23:41
@sahilaidev

Copy link
Copy Markdown
Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 3, 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 repository_dispatch).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

@sahilaidev
sahilaidev force-pushed the agent/daily-spend-ledger-focused branch from e897510 to 8403735 Compare August 4, 2026 02:32
@sahilaidev

Copy link
Copy Markdown
Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 4, 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 repository_dispatch).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

@clawsweeper

clawsweeper Bot commented Aug 4, 2026

Copy link
Copy Markdown

ClawSweeper status: review started.

I am starting a fresh review of this pull request: Add focused daily spend ledger This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@sahilaidev sahilaidev closed this Aug 4, 2026
@sahilaidev
sahilaidev deleted the agent/daily-spend-ledger-focused branch August 4, 2026 03:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant