Skip to content

Add menu bar pace layout tokens - #2540

Merged
steipete merged 4 commits into
steipete:mainfrom
kratocz:feat/menu-bar-pace-token
Aug 3, 2026
Merged

Add menu bar pace layout tokens#2540
steipete merged 4 commits into
steipete:mainfrom
kratocz:feat/menu-bar-pace-token

Conversation

@kratocz

@kratocz kratocz commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Session pace, Weekly pace, and Auto pace layout tokens so the menu bar can show the signed pace delta again, which the layout editor has had no token for since it replaced the Percent/Pace/Both display modes.

Runs out does not cover this. It answers when does this window end, and StatusItemController+MenuBarLayout.swift always derives it from the weekly (or automatic) lane. Pace answers how far off the sustainable rate am I right now, and it is meaningful per window.

Sign convention

Positive is deficit, negative is reserve — the same direction MenuBarDisplayText.paceText has always used, so +11% means usage runs 11 points ahead of the even rate and -8% means 8 points behind it, with 0% shown on pace. This mirrors the menu card's "in deficit" / "in reserve" wording in the compact form the status item has room for.

Scope

The Codex review comment on #2534 recommended a session-only token with weekly and automatic deferred. I went with all three windows instead, for two reasons: the token then mirrors the existing percent tokens exactly rather than introducing a second, narrower window vocabulary in the same palette group, and weekly pace is the window I actually needed — a 7-day quota is where being ahead of the rate costs you something, since a 5-hour window refills on its own. That said, the extra windows are two enum cases and two label strings; happy to cut it down to session-only if that is the direction you prefer.

Implementation notes

  • Pace resolution goes through a shared UsageStore.menuBarLayoutPaceText helper, so the status item and the layout editor preview both apply the same historical-dataset and work-day settings the menu card uses. Precomputing upstream matches how runsOut already works — the renderer has no access to the store.
  • Each token reads its own window; Weekly pace never falls back to the session delta.
  • The existing 3% expected-usage floor in weeklyPace still gates the token, so it renders the standard en-dash placeholder early in a window while its siblings keep rendering.
  • Sample values in the palette preview come from the pure UsagePace.weekly calculation, so the preview is deterministic before any snapshot exists.
  • Token labels added to en plus all 22 complete locale catalogs; Scripts/check-app-locales.mjs passes.

Possible follow-up (not in this PR)

MenuBarLayout.migrated maps the legacy .pace display mode to the runsOut token and .both to percent + runsOut. Since runsOut is an ETA rather than a delta, installs that upgraded without ever opening the layout editor silently changed what their status item means. With this token in place that migration could map to .pace(window:) instead. I left it out because it changes behavior for existing installs and seemed like a separate decision from adding the token.

Commands run

  • swift build
  • make test (full sharded suite, exit 0)
  • make check (0 violations)
  • node Scripts/check-app-locales.mjs

Proof

Menu bar rendering from a release build of this branch, stored layout Icon · Weekly % · Separator · Weekly pace, live provider data:

Claude status item rendering W 41% and +13% pace

Three providers side by side, one per pace state:

Three status items showing deficit, reserve, and placeholder pace

Claude renders 41% · +13% (13 points ahead of the even rate), Antigravity W 20% · -22% (in reserve), and Codex W 0% · – — its weekly window had just reset, so pace sits below the existing 3% expected-usage floor and the token renders the en-dash placeholder while its siblings keep rendering.

Review follow-up

The Codex review correctly flagged that the icon observation signature did not cover pace values, so a historicalPaceRevision bump could wake the observer yet skip updateIcons(), leaving a custom pace token stale. Fixed in dece955: the active layout's pace values now contribute to providerStoreIconObservationSignature the same way cost and account tokens already do, gated on the layout actually containing a pace token. The regression test (StatusItemLayoutPaceSignatureTests) renders two snapshots with identical used percents but different resets; it was verified to fail on a5371fa (both signatures identical) and passes with the fix. Focused sweep after the fix: 381 tests across the 31 status-item, layout, and pace suites, plus make check with zero violations.

Note on labels

I saw the clawsweeper:no-new-fix-pr and clawsweeper:needs-product-decision labels on #2534. Opening this anyway as a concrete proposal to react to rather than as something expected to merge as-is — close it without ceremony if the product call goes another way.

Refs #2534

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

ℹ️ 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 +75 to +79
weeklyPace: self.store.menuBarLayoutPaceText(provider: provider, window: windows.weekly, now: now),
automaticPace: self.store.menuBarLayoutPaceText(
provider: provider,
window: windows.automatic,
now: now),

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 custom pace values in the icon signature

When Codex historical data is loaded or revised after this render, historicalPaceRevision wakes the icon observer, but providerStoreIconObservationSignature only hashes the legacy display text plus custom cost/account values. With a custom weekly/auto pace token and the legacy display mode left at its default percent setting, the signature is therefore unchanged and updateIcons() is skipped, leaving the token on its earlier linear/stale value until an unrelated icon-affecting change occurs. Include the active layout's pace values (or its historical revision) in that signature.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in dece955 — the active layout's pace values now contribute to the signature the same way cost and account tokens do, gated on the layout containing a pace token. Regression test in StatusItemLayoutPaceSignatureTests was verified to fail before the fix.

@clawsweeper clawsweeper Bot added 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. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jul 31, 2026
@clawsweeper

clawsweeper Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed August 2, 2026, 6:13 PM ET / 22:13 UTC.

ClawSweeper review

What this changes

Adds signed Session, Weekly, and Auto pace tokens to the menu-bar layout editor, preview, renderer, accessibility output, refresh signature, localized labels, documentation, and regression tests.

Merge readiness

⚠️ Ready for maintainer review - 3 items remain

The branch is a coherent, tested implementation with direct native menu-bar screenshot proof, and the prior refresh defect has been addressed. It should remain open because merging would establish the broader Session/Weekly/Auto pace-token vocabulary while the canonical request still awaits a maintainer product-direction decision.

Priority: P2
Reviewed head: 3c3614c94a80b22b185e963416aa34ca5dc050cd
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) Strong direct visual proof and focused regression coverage support a normal good patch; maintainer product direction, not implementation quality, is the remaining merge gate.
Proof confidence 🦞 diamond lobster (5/6) ✨ media proof bonus Sufficient (screenshot): Two prepared screenshots from a release build directly show the new weekly pace token in deficit, reserve, and unavailable states; private provider details are not exposed in the inspected images.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (screenshot): Two prepared screenshots from a release build directly show the new weekly pace token in deficit, reserve, and unavailable states; private provider details are not exposed in the inspected images.
Evidence reviewed 6 items Current main lacks a pace layout token: The current token enum exposes percentage, reset, run-out, cost, and structure tokens but no signed pace token, so the linked request remains unsolved on main.
Proposed token path is internally consistent: The branch adds the pace enum case, resolves each selected window through UsageStore, supplies the same values to the editor preview and status-item render data, and renders unavailable values with the established placeholder behavior.
Prior stale-refresh finding is covered: Commit c115ae0 adds the active layout’s pace values to the icon observation signature only when pace tokens are present; the new regression test verifies different reset times produce different signatures despite identical percentages.
Findings None None.
Security None None.

How this fits together

CodexBar converts provider usage snapshots and historical pacing data into a configurable macOS menu-bar status item. Layout tokens select which provider-scoped values are resolved for the editor preview and then rendered in the live status item.

flowchart LR
  A[Provider usage snapshots] --> B[Historical pace calculation]
  C[Saved menu-bar layout] --> D[Token selection]
  B --> E[Provider-scoped render data]
  D --> E
  E --> F[Layout editor preview]
  E --> G[Menu-bar status item]
Loading

Decision needed

Question Recommendation
Should CodexBar expose Session, Weekly, and Auto pace tokens together, or should the first release be limited to Session pace? Approve all three pace windows: Merge the proposed family so pace mirrors the established Session/Weekly/Auto percentage-token vocabulary.

Why: The implementation is technically coherent and proof-positive, but the number of supported pace variants is a durable user-facing layout vocabulary decision that code review cannot infer from the existing contract.

Before merge

  • Resolve merge risk (P1) - Merging establishes all three pace-window variants as supported layout vocabulary even though the canonical request at Restore session pace / deficit as a menu-bar layout token #2534 still needs a maintainer product-scope decision.
  • Complete next step (P2) - No mechanical repair remains; a maintainer must choose the permanent pace-token scope before this feature can merge.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch breadth 35 files affected; 355 added, 1 removed The focused feature spans rendering, refresh observation, tests, documentation, and 23 localization catalogs, so scope approval matters more than another mechanical patch pass.

Root-cause cluster

Relationship: fixed_by_candidate
Canonical: #2534
Summary: This PR is the concrete candidate implementation for the open canonical pace-token request, but the issue should remain open until a maintainer chooses scope and a merge occurs.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge-risk options

Maintainer options:

  1. Decide the mitigation before merge
    Explicitly approve the full Session/Weekly/Auto family if matching the existing percentage-token vocabulary is desired, then merge this focused implementation; otherwise ask for a narrow session-only revision before merge.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Technical review

Best possible solution:

Explicitly approve the full Session/Weekly/Auto family if matching the existing percentage-token vocabulary is desired, then merge this focused implementation; otherwise ask for a narrow session-only revision before merge.

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

Not applicable: this PR adds a new layout capability rather than repairing a reported failing current-main runtime path. The provided screenshots nevertheless demonstrate the intended live behavior after the change.

Is this the best way to solve the issue?

Unclear pending product direction: the implementation is a narrow, maintainable way to add pace tokens, but a maintainer must first choose whether all three window variants are the intended supported vocabulary.

AGENTS.md: found and applied where relevant.

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

Labels

Label justifications:

  • P2: This is a useful menu-bar layout enhancement with limited blast radius, not an urgent regression, availability failure, or security issue.
  • 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 (screenshot): Two prepared screenshots from a release build directly show the new weekly pace token in deficit, reserve, and unavailable states; private provider details are not exposed in the inspected images.
  • proof: sufficient: Contributor real behavior proof is sufficient. Two prepared screenshots from a release build directly show the new weekly pace token in deficit, reserve, and unavailable states; private provider details are not exposed in the inspected images.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. Two prepared screenshots from a release build directly show the new weekly pace token in deficit, reserve, and unavailable states; private provider details are not exposed in the inspected images.

Evidence

What I checked:

  • Current main lacks a pace layout token: The current token enum exposes percentage, reset, run-out, cost, and structure tokens but no signed pace token, so the linked request remains unsolved on main. (Sources/CodexBar/MenuBarLayout.swift:10, 5b0b9fa3e37c)
  • Proposed token path is internally consistent: The branch adds the pace enum case, resolves each selected window through UsageStore, supplies the same values to the editor preview and status-item render data, and renders unavailable values with the established placeholder behavior. (Sources/CodexBar/MenuBarLayoutRenderer.swift:24, 3c3614c94a80)
  • Prior stale-refresh finding is covered: Commit c115ae0 adds the active layout’s pace values to the icon observation signature only when pace tokens are present; the new regression test verifies different reset times produce different signatures despite identical percentages. (Tests/CodexBarTests/StatusItemLayoutPaceSignatureTests.swift:10, c115ae0c303e)
  • Live behavior proof inspected: The prepared screenshots directly show a release build rendering weekly pace in deficit (+13%), reserve (-22%), and the unavailable en-dash state after a reset. (3c3614c94a80)
  • Canonical product request remains open: The linked request explicitly asks for a pace token and says all three windows are ideal, but it remains open with labels indicating that maintainer product direction is needed.
  • Current-main ownership and release context: Current layout-token and migration lines blame to Peter Steinberger’s v0.46.0 appcast update commit, while Yuxin Qiao most recently maintained the adjacent layout-render-data path for multi-currency work. The PR head is cleanly based on current main through merge commit 7fccb9a. (Sources/CodexBar/StatusItemController+MenuBarLayout.swift:58, b1170d83963d)

Likely related people:

  • Peter Steinberger: Current-main blame attributes the menu-bar token and legacy migration surface to Peter’s v0.46.0 commit, and Peter created the branch’s current merge-base integration and contributor-credit commit. (role: current layout-token owner and recent integrator; confidence: high; commits: b1170d83963d, 7fccb9a0f94c, 3c3614c94a80; files: Sources/CodexBar/MenuBarLayout.swift, CHANGELOG.md)
  • Yuxin Qiao: Yuxin’s recent multi-currency work modified the status-item layout render-data path that this PR extends with provider-scoped pace values. (role: recent adjacent render-data contributor; confidence: medium; commits: 8909956edbb3, e1e2cc20272a; files: Sources/CodexBar/StatusItemController+MenuBarLayout.swift)

Rank-up moves

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

  • Obtain an explicit maintainer decision on whether all three pace windows should be part of the supported layout vocabulary.

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 (4 earlier review cycles)
  • reviewed 2026-07-31T23:01:29.413Z sha a5371fa :: needs real behavior proof before merge. :: [P2] Refresh custom pace tokens after historical data changes
  • reviewed 2026-08-01T15:38:00.789Z sha dece955 :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-01T22:23:18.038Z sha dece955 :: needs maintainer review before merge. :: none
  • reviewed 2026-08-02T19:40:45.478Z sha c115ae0 :: needs maintainer review before merge. :: none

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

kratocz commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Signature fix pushed in dece955 and runtime proof added to the description — menu bar screenshots from a release build of this branch showing deficit, reserve, and placeholder states. The regression test was verified to fail on a5371fa before the fix.

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. 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 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 1, 2026
kratocz added 2 commits August 2, 2026 21:28
The 0.45 layout editor replaced the old Percent/Pace/Both display modes,
but no token exposes the signed pace delta the Both mode used to render.
`Runs out` is not a substitute: it answers when a window ends, always
estimating from the weekly (or automatic) lane, while pace answers how far
off the sustainable rate usage currently runs.

Add Session/Weekly/Auto pace tokens that mirror the percent tokens' window
selection and reuse the existing `MenuBarDisplayText.paceText` formatting
(`+11%` ahead of the rate, `-8%` behind, `0%` on pace). Each token resolves
pace for its own window, so Weekly pace never borrows the session delta.

Pace needs the store's historical dataset and work-day setting, so it is
resolved upstream like `runsOut` through a shared `menuBarLayoutPaceText`
helper that both the status item and the editor preview call. The existing
3% expected-usage floor in `weeklyPace` still applies, so a token renders
the en-dash placeholder early in a window while its siblings stay visible.

Refs steipete#2534
Pace values change with the historical dataset, the work-day setting,
and the clock, none of which move the percent fields already hashed by
providerStoreIconObservationSignature. A historicalPaceRevision bump
therefore woke the icon observer but produced an unchanged signature,
so updateIcons() was skipped and a custom pace token kept its stale
value until an unrelated icon change forced a redraw.

Contribute the active layout's pace values to the signature the same
way cost and account tokens already do, gated on the layout actually
containing a pace token. The regression test renders two snapshots with
identical used percents but different resets: without this fix both
signatures were identical.

Refs steipete#2534
@kratocz
kratocz force-pushed the feat/menu-bar-pace-token branch from dece955 to c115ae0 Compare August 2, 2026 19:36
@steipete
steipete merged commit f93e3ed into steipete:main Aug 3, 2026
9 checks passed
@kratocz
kratocz deleted the feat/menu-bar-pace-token branch August 3, 2026 01:01
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: 📸 screenshot Contributor real behavior proof includes screenshot evidence. 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