spec: AI credit usage in status bar (#10449)#10454
spec: AI credit usage in status bar (#10449)#10454lonexreb wants to merge 4 commits intowarpdotdev:masterfrom
Conversation
|
I'm starting a first review of this spec-only pull request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This spec proposes an opt-in status-bar segment for AI credit usage and covers display, settings, refresh, scope, click behavior, acceptance criteria, and tests. The main behavior is understandable, but several requirements are still ambiguous enough to produce inconsistent or inefficient implementations.
Concerns
- The spec does not define a concrete mapping from the existing Billing & Usage state model to status-bar display states for unlimited, usage-based, add-on, enterprise, delinquent, restricted, and missing-allowance cases.
- The refresh/subscription contract can still permit one polling loop per visible segment across tabs or windows, which conflicts with the stated no-extra-pipeline intent.
- The implementation pointers do not match the local code structure, making the spec not ready for implementation handoff.
Security
- The workspace-scope behavior needs to explicitly inherit Billing & Usage authorization and redaction rules before exposing credit usage in always-visible chrome.
- The telemetry
surfacefield should be constrained so it does not accidentally add usage totals, scope names, or workspace identifiers beyond existing billing instrumentation.
Verdict
Found: 0 critical, 4 important, 1 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| the existing status-bar warning token). | ||
| - `≥95%` used → red / danger foreground (uses the existing | ||
| status-bar danger token). | ||
| - "Unlimited" plan: when the billing source returns |
There was a problem hiding this comment.
plan == "unlimited" or equivalent is not a concrete contract for existing billing states such as usage-based pricing, add-on credits, enterprise limited reporting, delinquent/restricted workspaces, or missing allowances. Add a mapping from Billing & Usage state to display, threshold, and hidden behavior.
| for the active conversation. The segment subscribes to the same | ||
| agent-turn completion signal already used by the conversation | ||
| list. | ||
| - Background refresh: when the segment is visible, refresh on a |
There was a problem hiding this comment.
|
|
||
| ### B3. Scope (workspace selector) | ||
|
|
||
| - The segment follows the current workspace-billing-context |
There was a problem hiding this comment.
|
|
||
| ## Implementation Pointers | ||
|
|
||
| - `app/src/status_bar/*.rs` — add a new segment struct/component |
There was a problem hiding this comment.
app/src/status_bar/*.rs is absent, and Billing & Usage currently relies on settings/workspace/AI request usage models rather than an app/src/billing usage client. Update the pointers to the actual status-bar and billing-usage models before marking this ready to implement.
|
|
||
| - No new telemetry events. The billing fetch reuses the existing | ||
| Billing-pane fetch path and its existing instrumentation. | ||
| - One existing event SHOULD gain a `surface` field if it does not |
There was a problem hiding this comment.
💡 [SUGGESTION] [SECURITY] Define surface as a fixed low-cardinality enum and state that telemetry must not include used/allowance values, scope names, or workspace identifiers beyond what the existing billing event already records.
|
Round-1 fixes for oz-for-oss review: (1) added Display State Matrix covering unlimited, usage-based, add-on, enterprise, delinquent, restricted, missing-allowance; (2) Subscription Model now requires a single shared, ref-counted subscription to the existing Billing & Usage state stream — segments are downstream observers, never poll independently; (3) Implementation Pointers updated to verified paths in the codebase; (4) Authorization & Redaction subsection inherits billing-pane authz, hides segment when permission absent, never crosses workspace scope; (5) telemetry constrained to click events only — no usage totals, scope names, or workspace identifiers in payload. |
|
/oz-review |
|
I'm re-reviewing this spec-only pull request in response to a review request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This spec proposes an opt-in AI credit usage status-bar segment and covers the main behavior, settings, telemetry, authorization, and testing surfaces.
Concerns
- The display contract has conflicting requirements for missing usage/allowance data.
- Add-on credit rendering is underspecified when multiple pools exist.
- The required shared Billing & Usage state stream is not tied to a concrete existing model or refresh owner, which risks an implementation that invents a new pipeline while trying to avoid one.
- The Open Questions section still leaves behavior that is already referenced by acceptance criteria unresolved.
Security
- The synced setting controls always-visible billing data; the spec should justify global sync or make the privacy behavior explicit.
Verdict
Found: 0 critical, 4 important, 1 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| - "Unlimited" plan: when the billing source returns | ||
| `plan == "unlimited"` (or equivalent), display `∞` glyph and | ||
| use default foreground regardless of `used`. | ||
| - Indeterminate state (used or allowance is null/missing while |
There was a problem hiding this comment.
—/—, but B1a later says known used plus missing allowance renders <used>/—; split these cases explicitly so implementers do not choose different fallbacks.
| |---|---|---|---|---| | ||
| | Unlimited plan | `∞` glyph (or "Unlimited" if locale lacks the glyph) | Default fg; thresholds NOT applied | "Unlimited plan · current monthly billing usage: $X" if a USD figure is exposed by the existing billing source, else "Unlimited plan" | Open Settings → Billing & Usage | | ||
| | Usage-based / metered | `<used>/<allowance>` (integers) | <80% default · 80–94% warning · ≥95% danger | "<scope> · Monthly allowance · resets <date>" | Open Settings → Billing & Usage | | ||
| | Add-on credits on top of base allowance | `<used>/<base>+<addon>` (e.g. `89/2500+500`) | Thresholds computed against `(base + addon_total)` | "<scope> · Base 2500 (resets <date>) · Add-on 500 (expires <date>) · Add-on 250 (expires <date>)" | Open Settings → Billing & Usage | |
There was a problem hiding this comment.
+<addon> is the total granted, total remaining, currently available after expiration, or multiple per-pool values, and align the example with the tooltip's two add-ons.
|
|
||
| ### B2. Refresh & caching (subscription model) | ||
|
|
||
| - Source of truth: the same Billing & Usage state stream that |
There was a problem hiding this comment.
| - Key: `status_bar.show_ai_credits` | ||
| - Type: `bool` | ||
| - Default: `false` (opt-in) | ||
| - Sync: `SyncToCloud::Globally(RespectUserSyncSetting::Yes)`, |
There was a problem hiding this comment.
💡 [SUGGESTION] [SECURITY] Because this setting exposes billing usage in always-visible chrome, document why global sync is safe or make the setting device-local/private so enabling it on one synced device does not unexpectedly surface credit usage on another.
| — no `used`, `allowance`, `scope_name`, `workspace_id`, | ||
| `plan_tier`, or `reset_at` fields. | ||
|
|
||
| ## Open Questions |
There was a problem hiding this comment.
|
Round-2 fixes: (1) data-state display table is now the single source of truth — covers loading/success/allowance-missing/used-missing/both-missing/stale/failed/unauthorized states with consistent display+color+tooltip per state; (2) multiple add-on pools render |
|
/oz-review |
|
I'm re-reviewing this spec-only pull request in response to a review request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This spec proposes an opt-in AI credit usage segment in the status bar and covers display states, settings, authorization, telemetry, and test expectations.
Concerns
- The failure-state timing is internally contradictory: the behavior contract says 30s should show a stale state and only ≥5 min hides the segment, while acceptance criteria and tests require hiding after 30s.
- Refresh/subscription ownership is ambiguous: the spec says the chip is a passive observer and adds no refresh trigger, but also says it subscribes to agent-turn completion and requires exactly one billing-state subscription.
- Tooltip rendering for add-on pools exposes add-on names, amounts, and expirations without the same redaction/user-visible-data constraint applied to workspace identifiers.
- Telemetry requirements conflict between an exact single click event and later fetch instrumentation that the segment observer contributes to.
Security
- Add-on grant tooltip data needs an explicit redaction/display-name rule before implementation because it places billing details into status-bar chrome/tooltips that can appear in screenshares or recordings.
Verdict
Found: 1 critical, 4 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| - A3. Clicking the segment opens Settings → Billing & Usage. | ||
| - A4. Switching workspace billing scope updates the segment to | ||
| the new scope's used/allowance within 2s. | ||
| - A5. Simulated 30s of consecutive fetch failures hides the |
There was a problem hiding this comment.
🚨 [CRITICAL] A5 contradicts B1a.i/B2: those sections say 30s shows stale and only ≥5 min hides. Choose one failure window and align A5/T4 so implementation/tests do not encode a different state machine.
| invariant is structural, not advisory: spawning N status-bar | ||
| chips (in N windows / panes) attaches N subscribers to the SAME | ||
| singleton — there is no additional fetch loop per chip. | ||
| - Cache TTL: ≤2s after the most-recent agent-turn-completion |
There was a problem hiding this comment.
| exact glyph/text and color token specified, including | ||
| delinquent, restricted, missing-allowance, enterprise-no-limit, | ||
| and add-on credit cases. | ||
| - A10. Single shared subscription: with N status-bar segments |
There was a problem hiding this comment.
| - Threshold computation: against `(base + addon_total)`. If | ||
| `addon_total` is 0 (all expired), the segment falls back to | ||
| the base-only `<used>/<allowance>` render. | ||
| - Tooltip lists EACH add-on on its own line, in the form |
There was a problem hiding this comment.
| pane-vs-segment attribution and never carries usage shape. | ||
| - The billing fetch itself reuses the existing Billing-pane fetch | ||
| path and its existing instrumentation. If that path already | ||
| has a `surface` field, the segment's attached observer |
There was a problem hiding this comment.
exactly ONE event/no segment-side telemetry requirement and A12. Either make fetch surface purely Billing-pane-owned instrumentation with no segment-owned emission, or include the allowed surface behavior in A12/non-goals so telemetry tests are implementable.
|
Addressed round-N oz-for-oss review: Critical — Failure-state timing contradiction: Aligned A5 and T4 with the B1a.i data-state table. Behavior is now: ≥30s without a successful update → Stale row (last value with stale dot); ≥5 min consecutive failures → Failed row (segment hidden); successful Refresh/subscription ownership: Clarified that the chip is a passive observer of FETCHES, not of model events. It MAY subscribe to Add-on tooltip redaction (security): Added explicit redaction rule (B1a.iii) — display name only, integer credit amount only, coarse user-facing date for expiry, fallback string 'Add-on credit' when display_name missing, omit row entirely if amount missing, applied identically to hover/keyboard/AT a11y tree, never copied into telemetry. Mirrors the workspace-identifier rule in B3a. Telemetry conflict: Resolved by scoping ALL fetch instrumentation as upstream-owned and out of scope. The segment emits exactly one click event; no observer-side surface value, no contribution to existing fetch events. The 'attached observer contributes Commit: 18ff1b2 |
|
/oz-review |
|
I'm re-reviewing this spec-only pull request in response to a review request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This spec proposes an opt-in status-bar chip for AI credit usage and covers most expected behavior, settings, tests, telemetry, and privacy constraints.
Concerns
- The unlimited-plan row still allows a USD amount in the tooltip, which conflicts with the credit-count scope and creates an always-visible financial-data exposure.
- Refresh ownership is ambiguous for workspace-scope changes: the spec says the segment refetches while also forbidding the segment from triggering fetches.
- The stale/failed state machine is specified in terms of consecutive failures but is tied to
last_update_time, which only records successful updates. - The subscription tests describe a single ref-counted billing subscription, contradicting the model-event observer pattern defined elsewhere in the spec.
Security
- Remove or explicitly gate the unlimited-plan USD tooltip; the current wording surfaces financial data in always-visible chrome outside the sibling USD-spend spec.
Verdict
Found: 0 critical, 4 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
|
|
||
| | Plan / account state | Segment glyph / text | Color tokens | Tooltip | Click action | | ||
| |---|---|---|---|---| | ||
| | Unlimited plan (`is_unlimited == true`) | `∞` glyph (or "Unlimited" if locale lacks the glyph) | Default fg; thresholds NOT applied | "Unlimited plan · current monthly billing usage: $X" if a USD figure is exposed by the existing billing source, else "Unlimited plan" | Open Settings → Billing & Usage | |
There was a problem hiding this comment.
∞ only for unlimited plans. Remove the $X tooltip from this spec or move it behind the sibling USD-spend feature so financial data is not exposed here.
| - Stale display: when `last_update_time` is older than 30s the | ||
| chip switches to the "Stale" row of B1a.i. After ≥5 min of | ||
| consecutive failed/missing updates the chip switches to the | ||
| "Failed" row of B1a.i (segment hidden); display resumes once | ||
| `RequestUsageUpdated` fires successfully. Hide-on-failure is | ||
| computed from `AIRequestUsageModel::last_update_time()`, not | ||
| from a per-segment counter. |
There was a problem hiding this comment.
last_update_time only records the last successful update, so it cannot prove that updates are missing because of consecutive failures or an active retry; idle users could become stale/hidden without any failed fetch. Specify an explicit failure/retry state on AIRequestUsageModel or redefine these states purely by data age.
| - When the user switches workspace scope (e.g. "Personal" → "Acme | ||
| Workspace"), the segment refetches and re-renders within the | ||
| ≤2s debounce window. |
There was a problem hiding this comment.
refresh_request_usage_async. Name the upstream owner that refreshes on scope changes, or change this to say the segment only re-renders after the singleton publishes updated data.
| - T10. Shared subscription ref-count: spawning N≥2 segments | ||
| results in exactly one underlying billing subscription; the | ||
| last segment removed disposes the subscription. Verified by | ||
| asserting the fetch counter increments at the same cadence as | ||
| N=1. |
There was a problem hiding this comment.
Summary
Spec-only PR proposing an opt-in status-bar segment that shows AI
credit consumption for the current billing period (e.g.,
89/2500),mirroring the existing context-remaining segment so users can monitor
remaining credits at a glance without opening Settings.
Resolves intent of #10449.
What's in this PR
specs/GH10449/SPEC.md— full behavior contract, settings surface,acceptance criteria, tests, and open questions.
No code changes. This PR is for spec review only.
Highlights
status_bar.show_ai_credits(defaultfalse) so wedon't surprise existing users with new chrome.
path. Refreshes within ≤2s of agent-turn completion.
≥95%) reuse existing status-bar tokens.
the Billing pane.
hide segment after 30s of consecutive failures.
Related
is the credit-count counterpart, sharing the same
status-bar-segment + billing-fetch architecture so the two can
ship as paired toggles.
Triage request
Requesting
ready-to-implementonce the open questions in the specare resolved (default-on for metered plans, unlimited-plan rendering,
glyph vs word).
Test plan
shared fetch pipeline assumption holds.
ready-to-implement.