From 52f64efebaae18450f2501f433cf48cca04b5995 Mon Sep 17 00:00:00 2001
From: Tyler
Date: Sun, 16 Aug 2026 06:05:53 +0000
Subject: [PATCH 1/6] Stop painting Cursor unavailable Plan as 0% on glance
(SBS-876)
---
CHANGELOG.md | 2 +-
.../src-tauri/src/taskbar_widget.rs | 103 +++++++++++++--
.../src/components/PlanStatusCard.test.tsx | 34 +++++
.../src/components/PlanStatusCard.tsx | 16 ++-
.../src/components/ProviderGrid.tsx | 15 ++-
apps/desktop-tauri/src/floatbar/FloatBar.tsx | 59 ++++++---
.../src/lib/capacityPresentation.test.ts | 124 +++++++++++++++++-
.../src/lib/capacityPresentation.ts | 124 ++++++++++++++----
.../desktop-tauri/src/lib/providerRow.test.ts | 21 +++
apps/desktop-tauri/src/lib/providerRow.ts | 5 +-
apps/desktop-tauri/src/styles.css | 24 ++++
.../src/surfaces/ProviderDetailView.test.tsx | 38 ++++++
.../src/surfaces/ProviderDetailView.tsx | 45 +++++--
.../src/surfaces/TaskbarFlyout.test.tsx | 50 +++++++
.../src/surfaces/TaskbarFlyout.tsx | 51 ++++++-
15 files changed, 620 insertions(+), 91 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e37141b4..893266a4 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,7 @@
### Fixed
- **Opening Settings from the floating bar no longer lands on General.** The bar asked for a `menuBar` tab the Settings window does not have, so the window fell back to General instead of Display. It now opens Display, the same tab the dashboard already uses for that action. The lists that name a Settings tab on each side of the bridge are compared in CI so a renamed tab cannot silently send you to General again.
-- **Cursor no longer treats missing usage as zero.** An empty `individualUsage` object used to paint a 0% monthly bar and hide a real team pool sitting next to it. Monthly is now marked unavailable when Cursor reports no reading, and an empty individual object falls through to team usage. On-demand stays billed spend; plan and included dollars are labeled **Included** so they are not read as an invoice. A missing Composer tracking database is shown as unavailable, not as no activity.
+- **Cursor no longer treats missing usage as zero.** An empty `individualUsage` object used to paint a 0% monthly bar and hide a real team pool sitting next to it. Monthly is now marked unavailable when Cursor reports no reading, and an empty individual object falls through to team usage. Glance surfaces no longer paint a 0% Plan bar when monthly is unavailable — Overview, flyout, detail, floating bar, and the native taskbar tile show the named state instead. On-demand stays billed spend; plan and included dollars are labeled **Included** so they are not read as an invoice. A missing Composer tracking database is shown as unavailable, not as no activity.
- **Leftover English on glance surfaces now goes through locale keys.** Floatbar settings, freshness chips, account-status labels, Charts tab names, and About update copy used hardcoded English. They now use `en-US.ftl` (and zh-CN) so chips no longer show raw `stale` / `error` tokens.
- **Refreshing model prices no longer blanks out the prices you already had.** The models.dev price cache was emptied before the new copy was written, so a second Ceiling process reading during that moment saw nothing, and a crash mid-write threw the cache away for good. Either way token costs quietly disappeared until a network refresh worked. The new copy is now written beside the old one and swapped in, so there is never a moment with no prices on disk.
- **A Claude token refresh no longer replaces a symlinked credentials file.** Claude Code owns `.credentials.json`, and people who manage it with chezmoi or stow, or who share one file between WSL and Windows, keep a symlink at that path. Writing a refreshed token used to drop a fresh private file over the link, so the real file kept the old tokens and the next `chezmoi apply` signed Claude Code out. The refresh now follows the link and keeps the file's own permissions. It also takes a per-file lock on the shared file rather than on each path that points at it. If the app and the command line refresh the same login at the same moment, Claude retires the token the slower one used, so that one now steps aside and picks up the tokens that actually work instead of writing back dead ones and signing Claude Code out. Gemini and Grok already worked this way.
diff --git a/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs b/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
index b64cccc1..53762b46 100644
--- a/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
+++ b/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
@@ -97,6 +97,9 @@ struct ConstrainingReadout<'a> {
/// percentage is the wrong readout for a spend lane: "62%" of an $1800 cap
/// does not tell you that you owe $1112.92 (SBS-191).
amount: Option<&'a crate::commands::WindowAmountBridge>,
+ /// Set when the percent on this window is a placeholder, not a reading
+ /// (SBS-876). The tile must not round that placeholder to 0 or 100.
+ named_state: Option<&'a str>,
}
impl<'a> ConstrainingReadout<'a> {
@@ -105,10 +108,47 @@ impl<'a> ConstrainingReadout<'a> {
label,
window,
amount: None,
+ named_state: None,
}
}
}
+/// Inactive-row ids that mark `primary` as a placeholder, not a reading.
+///
+/// Match by id only. Sweep: only Cursor writes 0% primary plus an inactive
+/// row for that same window (`cursor-plan` / `cursor-monthly`).
+fn primary_named_state(snapshot: &crate::commands::ProviderUsageSnapshot) -> Option<&str> {
+ let row = snapshot
+ .inactive_rate_windows
+ .iter()
+ .find(|row| row.id == "cursor-plan" || row.id == "cursor-monthly")?;
+ Some(if row.state == "unavailable" {
+ "unavailable"
+ } else {
+ "notEnforced"
+ })
+}
+
+fn strip_readout_percent(readout: &ConstrainingReadout<'_>, show_as_used: bool) -> Option {
+ if readout.named_state.is_some() {
+ return None;
+ }
+ let value = if show_as_used {
+ readout.window.used_percent
+ } else {
+ readout.window.remaining_percent
+ };
+ Some(value.clamp(0.0, 100.0).round() as u8)
+}
+
+fn strip_heat(snapshot: &crate::commands::ProviderUsageSnapshot) -> f64 {
+ let readout = constraining_readout(snapshot);
+ if readout.named_state.is_some() {
+ return -1.0;
+ }
+ readout.window.used_percent
+}
+
/// Tile text for a currency-billed lane.
///
/// Uncapped spend has no remaining figure to show, so "show remaining" falls
@@ -203,6 +243,7 @@ fn cursor_actionable_windows(
label: Some(label),
window: &extra.window,
amount: extra.amount.as_ref(),
+ named_state: None,
});
}
out
@@ -222,6 +263,7 @@ fn cursor_on_demand_readout(
}),
window: &extra.window,
amount: extra.amount.as_ref(),
+ named_state: None,
})
}
@@ -293,7 +335,12 @@ fn cursor_strip_readout(
{
return readout;
}
- ConstrainingReadout::new(snapshot.primary_label.as_deref(), &snapshot.primary)
+ ConstrainingReadout {
+ label: snapshot.primary_label.as_deref(),
+ window: &snapshot.primary,
+ amount: None,
+ named_state: primary_named_state(snapshot),
+ }
}
fn constraining_readout(
@@ -303,7 +350,12 @@ fn constraining_readout(
return cursor_strip_readout(snapshot);
}
- let mut best = ConstrainingReadout::new(snapshot.primary_label.as_deref(), &snapshot.primary);
+ let mut best = ConstrainingReadout {
+ label: snapshot.primary_label.as_deref(),
+ window: &snapshot.primary,
+ amount: None,
+ named_state: primary_named_state(snapshot),
+ };
// Claude's per-model weekly caps are parallel sub-pools, not blockers: at
// 100% you switch model rather than stop. The tile shows one lane, so
@@ -343,6 +395,7 @@ fn constraining_readout(
label: Some(extra.title.as_str()),
window: &extra.window,
amount: extra.amount.as_ref(),
+ named_state: None,
});
}
out
@@ -387,10 +440,8 @@ where
return Some(*hit);
}
candidates.into_iter().max_by(|a, b| {
- constraining_readout(a)
- .window
- .used_percent
- .total_cmp(&constraining_readout(b).window.used_percent)
+ strip_heat(a)
+ .total_cmp(&strip_heat(b))
.then_with(|| b.account_id.cmp(&a.account_id))
})
}
@@ -1133,14 +1184,8 @@ mod windows_host {
let constraining = snapshot
.filter(|snapshot| snapshot.error.is_none())
.map(super::constraining_readout);
- let percent = constraining.map(|readout| {
- let value = if settings.show_as_used {
- readout.window.used_percent
- } else {
- readout.window.remaining_percent
- };
- value.clamp(0.0, 100.0).round() as u8
- });
+ let percent = constraining
+ .and_then(|readout| strip_readout_percent(&readout, settings.show_as_used));
// A spend lane's headline is the money, not the fraction.
let spend = constraining.and_then(|readout| readout.amount);
let amount_label =
@@ -3273,6 +3318,36 @@ mod tests {
);
}
+ /// SBS-876: Cursor still writes 0% primary when monthly is missing, plus
+ /// `cursor-plan` unavailable. The native tile must not round that
+ /// placeholder to Some(0) or Some(100).
+ #[test]
+ fn cursor_strip_omits_percent_when_plan_is_unavailable() {
+ let mut snapshot = snap("cursor", None, 0.0);
+ snapshot.primary_label = Some("Plan".into());
+ snapshot
+ .inactive_rate_windows
+ .push(crate::commands::InactiveRateWindowSnapshot {
+ id: "cursor-plan".into(),
+ title: "Plan".into(),
+ description: "No usage reported".into(),
+ state: "unavailable".into(),
+ });
+
+ let readout = constraining_readout(&snapshot);
+ assert_eq!(readout.named_state, Some("unavailable"));
+ assert_eq!(strip_readout_percent(&readout, true), None);
+ assert_eq!(strip_readout_percent(&readout, false), None);
+
+ // Auto still wins the strip when present; the placeholder does not.
+ snapshot.secondary = Some(rate_window(42.0, Some(43_200)));
+ snapshot.secondary_label = Some("Auto".into());
+ let with_auto = constraining_readout(&snapshot);
+ assert_eq!(with_auto.label, Some("Auto"));
+ assert!(with_auto.named_state.is_none());
+ assert_eq!(strip_readout_percent(&with_auto, true), Some(42));
+ }
+
#[test]
fn uncapped_spend_reports_spend_even_in_remaining_mode() {
// No denominator means no headroom figure exists. Falling back to
diff --git a/apps/desktop-tauri/src/components/PlanStatusCard.test.tsx b/apps/desktop-tauri/src/components/PlanStatusCard.test.tsx
index ea298622..cb89a821 100644
--- a/apps/desktop-tauri/src/components/PlanStatusCard.test.tsx
+++ b/apps/desktop-tauri/src/components/PlanStatusCard.test.tsx
@@ -309,6 +309,40 @@ describe("PlanStatusCard", () => {
expect(screen.queryByText("lifted")).toBeNull();
});
+ /**
+ * SBS-876: a missing Cursor plan used to paint Plan 0% used (or 100% left)
+ * and a quiet "Plan Unavailable" row at the same time.
+ */
+ it("shows Unavailable for a missing Cursor plan and does not paint 0% or 100% left", () => {
+ render(
+ ,
+ );
+
+ expect(screen.getByText("unavailable")).toBeInTheDocument();
+ expect(screen.getByText("Plan")).toBeInTheDocument();
+ expect(screen.queryByText(/0% used/)).toBeNull();
+ expect(screen.queryByText(/100% left/)).toBeNull();
+ expect(screen.queryByText(/0% left/)).toBeNull();
+ });
+
it("separates unavailable windows from not-enforced ones", () => {
render(
{provider.error}
) : (
-
+ {meters.primary && (
+
+ )}
{meters.companions.map((meter) => (
{
- const constraining = constrainingWindow(provider).window;
+ const gridPercent = (provider: ProviderUsageSnapshot): number | null => {
+ const constraining = constrainingWindow(provider);
+ // Named-state windows are not a 0/100 bar (SBS-876 / CEILING_UI.md).
+ if (constraining.namedState) return null;
const pct = showAsUsed
- ? constraining.usedPercent
- : constraining.remainingPercent;
+ ? constraining.window.usedPercent
+ : constraining.window.remainingPercent;
return Math.max(0, Math.min(100, pct));
};
const totalItems = providers.length + 1;
@@ -106,6 +108,7 @@ export default function ProviderGrid({
{visibleProviders.map((p) => {
const status = providerGlanceStatus(p);
const brand = getProviderIcon(p.providerId).brandColor;
+ const percent = gridPercent(p);
return (
)}
{labelFor(p.displayName)}
- {!p.error && (
+ {!p.error && percent != null && (
{
const delta =
- floatBarWindow(b).window.usedPercent -
- floatBarWindow(a).window.usedPercent;
+ floatBarHeat(b) - floatBarHeat(a);
if (delta !== 0) return delta;
// Lowest account id, matching the native strip and the flyout so all
// three name the same seat when two accounts read the same pressure.
@@ -605,11 +632,7 @@ export default function FloatBar({ state }: { state: BootstrapState }) {
: [...byProvider.keys()]
.map((id) => pick(id))
.filter((p): p is (typeof eligible)[number] => p !== undefined)
- .sort(
- (a, b) =>
- floatBarWindow(b).window.usedPercent -
- floatBarWindow(a).window.usedPercent,
- );
+ .sort((a, b) => floatBarHeat(b) - floatBarHeat(a));
const allEligible = [...byProvider.keys()]
.map((id) => pick(id))
.filter((p): p is (typeof eligible)[number] => p !== undefined);
@@ -617,7 +640,7 @@ export default function FloatBar({ state }: { state: BootstrapState }) {
mode: selectionMode,
detectionEnabled: settings.floatBarForegroundDetection,
lastActiveProviderId,
- usedPercent: (row) => floatBarWindow(row).window.usedPercent,
+ usedPercent: (row) => floatBarHeat(row),
highUsageThreshold: settings.highUsageThreshold,
});
}, [
diff --git a/apps/desktop-tauri/src/lib/capacityPresentation.test.ts b/apps/desktop-tauri/src/lib/capacityPresentation.test.ts
index ec1a34c8..3531dcc0 100644
--- a/apps/desktop-tauri/src/lib/capacityPresentation.test.ts
+++ b/apps/desktop-tauri/src/lib/capacityPresentation.test.ts
@@ -6,6 +6,7 @@ import {
glanceMeters,
activePromoBoosts,
activePromoInclusions,
+ primaryNamedState,
providerGlanceStatus,
resetCreditsAvailable,
bankedResetCredits,
@@ -343,8 +344,8 @@ describe("capacityPresentation", () => {
],
}),
);
- expect(meters.primary.label).toBe("Monthly");
- expect(meters.primary.window.usedPercent).toBe(62);
+ expect(meters.primary?.label).toBe("Monthly");
+ expect(meters.primary?.window.usedPercent).toBe(62);
expect(meters.companions.map((meter) => meter.label)).toEqual(["Auto", "API"]);
expect(meters.companions.map((meter) => meter.window.usedPercent)).toEqual([
90, 12,
@@ -783,6 +784,125 @@ describe("capacityPresentation", () => {
});
});
+ /**
+ * SBS-876: Cursor still writes 0% primary when monthly is missing, plus an
+ * inactive `cursor-plan` row. Glance readers must treat that percent as a
+ * placeholder, not a reading.
+ */
+ describe("named primary placeholder (SBS-876)", () => {
+ const missingPlan = () =>
+ provider({
+ primary: window(0),
+ primaryLabel: "Plan",
+ inactiveRateWindows: [
+ {
+ id: "cursor-plan",
+ title: "Plan",
+ description: "No usage reported",
+ state: "unavailable",
+ },
+ ],
+ });
+
+ it("does not treat a missing Cursor plan as a 0% hero", () => {
+ const snap = missingPlan();
+ expect(primaryNamedState(snap)).toBe("unavailable");
+ expect(glanceMeters(snap).primary).toBeNull();
+ expect(constrainingWindow(snap).namedState).toBe("unavailable");
+ expect(
+ allMeasuredWindows(snap).some(
+ (measured) =>
+ measured.window.usedPercent === 0 &&
+ measured.label.toLowerCase() === "plan",
+ ),
+ ).toBe(false);
+ expect(providerGlanceStatus(snap)).not.toBe("exhausted");
+ expect(providerGlanceStatus(snap)).toBe("ok");
+ });
+
+ it("keeps glance primary null when Auto is present; strip still prefers Auto", () => {
+ const snap = provider({
+ primary: window(0),
+ primaryLabel: "Plan",
+ secondary: window(44),
+ secondaryLabel: "Auto",
+ inactiveRateWindows: [
+ {
+ id: "cursor-plan",
+ title: "Plan",
+ description: "No usage reported",
+ state: "unavailable",
+ },
+ ],
+ });
+ expect(glanceMeters(snap).primary).toBeNull();
+ expect(glanceMeters(snap).companions.map((meter) => meter.label)).toEqual([
+ "Auto",
+ ]);
+ expect(constrainingWindow(snap).label).toBe("Auto");
+ expect(constrainingWindow(snap).namedState).toBeUndefined();
+ expect(constrainingWindow(snap).window.usedPercent).toBe(44);
+ });
+
+ it("surfaces unlimited monthly as notEnforced, not a 0% hero", () => {
+ const snap = provider({
+ primary: window(0),
+ primaryLabel: "Monthly",
+ inactiveRateWindows: [
+ {
+ id: "cursor-monthly",
+ title: "Monthly",
+ description: "Not currently enforced by Cursor",
+ state: "notEnforced",
+ },
+ ],
+ });
+ expect(primaryNamedState(snap)).toBe("notEnforced");
+ expect(glanceMeters(snap).primary).toBeNull();
+ expect(constrainingWindow(snap).namedState).toBe("notEnforced");
+ expect(
+ allMeasuredWindows(snap).some((measured) => measured.window.usedPercent === 0),
+ ).toBe(false);
+ });
+
+ it("still heroes a real 0% plan when no inactive row marks it a placeholder", () => {
+ // Unknown is not empty: a genuine 0% reading must stay a 0% hero.
+ const snap = provider({
+ primary: window(0),
+ primaryLabel: "Plan",
+ inactiveRateWindows: [],
+ });
+ expect(primaryNamedState(snap)).toBeNull();
+ expect(glanceMeters(snap).primary?.window.usedPercent).toBe(0);
+ expect(constrainingWindow(snap).namedState).toBeUndefined();
+ expect(constrainingWindow(snap).window.usedPercent).toBe(0);
+ });
+
+ it("does not hide a real Weekly primary because an inactive Weekly has the same title", () => {
+ // ProviderDetailView.test.tsx Codex fixture: 51% Weekly primary plus
+ // an unavailable Weekly row with a different id. Title-only matching
+ // would hide the real reading.
+ const snap = provider({
+ providerId: "codex",
+ displayName: "Codex",
+ primary: window(51),
+ primaryLabel: "Weekly",
+ inactiveRateWindows: [
+ {
+ id: "weekly",
+ title: "Weekly",
+ description: "Not reported in the latest update",
+ state: "unavailable",
+ },
+ ],
+ });
+ expect(primaryNamedState(snap)).toBeNull();
+ expect(glanceMeters(snap).primary?.window.usedPercent).toBe(51);
+ expect(constrainingWindow(snap).window.usedPercent).toBe(51);
+ expect(constrainingWindow(snap).namedState).toBeUndefined();
+ });
+ });
+
describe("formatShortDuration", () => {
it("formats compactly across ranges", () => {
expect(formatShortDuration(0)).toBe("under 1m");
diff --git a/apps/desktop-tauri/src/lib/capacityPresentation.ts b/apps/desktop-tauri/src/lib/capacityPresentation.ts
index 6743300d..35753542 100644
--- a/apps/desktop-tauri/src/lib/capacityPresentation.ts
+++ b/apps/desktop-tauri/src/lib/capacityPresentation.ts
@@ -7,17 +7,30 @@ import type {
export type CapacityFreshness = "live" | "stale" | "error";
+/** Named enforcement state for a window that must not paint as 0% / 100%. */
+export type NamedWindowState = "unavailable" | "notEnforced";
+
export type ConstrainingWindow = {
id: string;
label: string;
window: RateWindowSnapshot;
/** Money behind this lane, when the provider meters it in currency. */
amount?: WindowAmountBridge | null;
+ /**
+ * Set when this window's percent is a placeholder, not a reading.
+ * Writers still emit a required primary plus an inactive row for the
+ * same identity (SBS-876 / CEILING_UI.md).
+ */
+ namedState?: NamedWindowState;
};
export type GlanceMeters = {
- /** Account plan pool — always the overview hero. */
- primary: ConstrainingWindow;
+ /**
+ * Account plan pool — overview hero. Null when that window is a named
+ * placeholder (unavailable / not enforced) so Overview does not also
+ * paint a 0% MeterRow (SBS-876).
+ */
+ primary: ConstrainingWindow | null;
/** Compact non-primary lanes shown beneath the hero. */
companions: ConstrainingWindow[];
};
@@ -34,6 +47,51 @@ const STALE_AFTER_MS = 10 * 60 * 1000;
/** Companion lanes appear on overview when used reaches this share. */
export const GLANCE_COMPANION_HOT_PERCENT = 70;
+/**
+ * Inactive-row ids that mark `primary` as a placeholder, not a reading.
+ *
+ * Match by id only — never by title. Codex can report a real Weekly
+ * primary alongside an unavailable Weekly inactive row with a different
+ * id (`weekly`); title matching would hide that 51% reading (SBS-876).
+ *
+ * Sweep: the only writer that emits 0% primary AND an inactive row for
+ * that same window is Cursor (`cursor-plan` unavailable, `cursor-monthly`
+ * notEnforced in `rust/src/providers/cursor/api.rs`).
+ */
+const PRIMARY_PLACEHOLDER_IDS = new Set(["cursor-plan", "cursor-monthly"]);
+
+export function isPrimaryPlaceholderId(id: string): boolean {
+ return PRIMARY_PLACEHOLDER_IDS.has(id);
+}
+
+/**
+ * When writers must still emit a primary window, they may also emit an
+ * inactiveRateWindows row for that same identity. The percent on primary
+ * is then a placeholder, not a reading (SBS-876 / CEILING_UI.md).
+ *
+ * Missing `state` on an inactive row is notEnforced (existing back-compat).
+ */
+export function primaryNamedState(
+ provider: ProviderUsageSnapshot,
+): NamedWindowState | null {
+ const hit = (provider.inactiveRateWindows ?? []).find((row) =>
+ PRIMARY_PLACEHOLDER_IDS.has(row.id),
+ );
+ if (!hit) return null;
+ return hit.state ?? "notEnforced";
+}
+
+function primaryConstrainingWindow(
+ provider: ProviderUsageSnapshot,
+): ConstrainingWindow {
+ return {
+ id: "primary",
+ label: provider.primaryLabel?.trim() || "Plan",
+ window: provider.primary,
+ namedState: primaryNamedState(provider) ?? undefined,
+ };
+}
+
/** A window you have already hit stops work no matter what the others read. */
function isBlocking(window: RateWindowSnapshot): boolean {
return window.isExhausted || window.usedPercent >= 100;
@@ -186,11 +244,9 @@ function cursorStripWindow(
if (exhausted) return exhausted;
}
if (onDemand && cursorOnDemandIsActive(provider, onDemand)) return onDemand;
- return {
- id: "primary",
- label: provider.primaryLabel?.trim() || "Plan",
- window: provider.primary,
- };
+ // Plan/Monthly fallback. If that window is a placeholder, carry namedState
+ // so the strip does not paint a bare 0% / 100% bar (SBS-876).
+ return primaryConstrainingWindow(provider);
}
/**
@@ -227,11 +283,7 @@ export function constrainingWindow(
return cursorStripWindow(provider);
}
- let best: ConstrainingWindow = {
- id: "primary",
- label: provider.primaryLabel?.trim() || "Plan",
- window: provider.primary,
- };
+ let best: ConstrainingWindow = primaryConstrainingWindow(provider);
for (const candidate of nonPrimaryWindows(provider)) {
if (isModelScopedLane(provider.providerId, candidate.id)) continue;
@@ -294,11 +346,8 @@ const PINNED_COMPANION_IDS: Record = {
* Clicking never toggles meters — detail mode lists every window.
*/
export function glanceMeters(provider: ProviderUsageSnapshot): GlanceMeters {
- const primary: ConstrainingWindow = {
- id: "primary",
- label: provider.primaryLabel?.trim() || "Plan",
- window: provider.primary,
- };
+ const named = primaryNamedState(provider);
+ const primary = named ? null : primaryConstrainingWindow(provider);
const candidates = nonPrimaryWindows(provider);
const pinned = PINNED_COMPANION_IDS[provider.providerId];
@@ -322,7 +371,12 @@ export function glanceMeters(provider: ProviderUsageSnapshot): GlanceMeters {
let companion: ConstrainingWindow | null = null;
for (const candidate of candidates) {
- if (!isCompanionHot(candidate.window, primary.window)) continue;
+ // No real primary: do not compare against a placeholder 0%. A companion
+ // is hot only on its own used percent (SBS-876).
+ const hot = primary
+ ? isCompanionHot(candidate.window, primary.window)
+ : candidate.window.usedPercent >= GLANCE_COMPANION_HOT_PERCENT;
+ if (!hot) continue;
if (
!companion ||
candidate.window.usedPercent > companion.window.usedPercent
@@ -419,12 +473,12 @@ export function bankedResetCredits(
export function allMeasuredWindows(
provider: ProviderUsageSnapshot,
): ConstrainingWindow[] {
- const primary: ConstrainingWindow = {
- id: "primary",
- label: provider.primaryLabel?.trim() || "Plan",
- window: provider.primary,
- };
- return [primary, ...nonPrimaryWindows(provider)];
+ // A placeholder primary is not a reading — Activity must not list a fake
+ // 0% Plan (SBS-876).
+ if (primaryNamedState(provider)) {
+ return nonPrimaryWindows(provider);
+ }
+ return [primaryConstrainingWindow(provider), ...nonPrimaryWindows(provider)];
}
/** Grid / glance status chip from constraining pressure. */
@@ -433,6 +487,28 @@ export function providerGlanceStatus(
): ProviderGlanceStatus {
if (provider.error) return "error";
const constraining = constrainingWindow(provider);
+ // A named-state window is not "ok because 0%" and not exhausted. Fetch
+ // succeeded; the window is named, not a quota. Unavailable is not error
+ // (provider.error is the fetch-failed path). If another measured window
+ // is applying pressure, that window still ranks the status (SBS-876).
+ if (constraining.namedState) {
+ const others = allMeasuredWindows(provider);
+ let hottest: ConstrainingWindow | null = null;
+ for (const candidate of others) {
+ if (
+ !hottest ||
+ candidate.window.usedPercent > hottest.window.usedPercent
+ ) {
+ hottest = candidate;
+ }
+ }
+ if (!hottest) return "ok";
+ if (hottest.window.isExhausted || hottest.window.usedPercent >= 100) {
+ return "exhausted";
+ }
+ if (hottest.window.usedPercent > 80) return "warning";
+ return "ok";
+ }
if (
constraining.window.isExhausted ||
constraining.window.usedPercent >= 100
diff --git a/apps/desktop-tauri/src/lib/providerRow.test.ts b/apps/desktop-tauri/src/lib/providerRow.test.ts
index 802303c9..94da3435 100644
--- a/apps/desktop-tauri/src/lib/providerRow.test.ts
+++ b/apps/desktop-tauri/src/lib/providerRow.test.ts
@@ -133,6 +133,27 @@ describe("selectStripAccount", () => {
expect(selectStripAccount(rows, "gone")?.accountId).toBe("work");
});
+ /**
+ * SBS-876: a placeholder 0% Plan is not heat. Ranking it as 0 would pick
+ * that seat as the coolest / least constrained.
+ */
+ it("does not rank a named-state Cursor plan as 0% heat", () => {
+ const missing = {
+ ...snap("cursor", "hobby", 0),
+ primaryLabel: "Plan",
+ inactiveRateWindows: [
+ {
+ id: "cursor-plan",
+ title: "Plan",
+ description: "No usage reported",
+ state: "unavailable",
+ },
+ ],
+ } as ProviderUsageSnapshot;
+ const real = snap("cursor", "pro", 5);
+ expect(selectStripAccount([missing, real])?.accountId).toBe("pro");
+ });
+
it("ranks on the constraining window, not the primary one", () => {
// The strip tile shows the constraining window, so ranking seats by their
// primary made the flyout badge "On strip" the account the tile was not
diff --git a/apps/desktop-tauri/src/lib/providerRow.ts b/apps/desktop-tauri/src/lib/providerRow.ts
index a3b76a13..0b2da59e 100644
--- a/apps/desktop-tauri/src/lib/providerRow.ts
+++ b/apps/desktop-tauri/src/lib/providerRow.ts
@@ -111,7 +111,10 @@ export function representativeForProvider<
*/
function stripHeat(provider: Pick): number {
if (!provider.primary) return -1;
- return constrainingWindow(provider as ProviderUsageSnapshot).window.usedPercent;
+ const constraining = constrainingWindow(provider as ProviderUsageSnapshot);
+ // A placeholder 0% is not heat — same as a missing primary (SBS-876).
+ if (constraining.namedState) return -1;
+ return constraining.window.usedPercent;
}
/**
diff --git a/apps/desktop-tauri/src/styles.css b/apps/desktop-tauri/src/styles.css
index 6052944c..bcca28ed 100644
--- a/apps/desktop-tauri/src/styles.css
+++ b/apps/desktop-tauri/src/styles.css
@@ -1619,6 +1619,23 @@ body:has(.taskbar-flyout-frame) #root {
white-space: nowrap;
}
+.taskbar-flyout__inactive {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ min-width: 0;
+ color: rgba(242, 247, 255, 0.56);
+ font-size: 10.5px;
+ line-height: 14px;
+}
+.taskbar-flyout__inactive--unavailable {
+ color: var(--usage-bar-high, #e3b341);
+}
+.taskbar-flyout__inactive--unavailable .taskbar-flyout__meter-label {
+ color: rgba(242, 247, 255, 0.78);
+}
+
.taskbar-flyout__window-more {
color: rgba(242, 247, 255, 0.5);
font-size: 9.5px;
@@ -7189,6 +7206,13 @@ body:has(.dashboard-shell) #root {
line-height: 1;
font-variant-numeric: tabular-nums;
}
+.provider-focus__primary-value--named strong {
+ font-size: 22px;
+ letter-spacing: -0.02em;
+}
+.provider-focus__primary-value--unavailable strong {
+ color: var(--usage-bar-high);
+}
.provider-focus__primary-value span {
color: var(--text-secondary);
font-size: 13px;
diff --git a/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx b/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
index f6a10ebf..296a693a 100644
--- a/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
+++ b/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
@@ -161,4 +161,42 @@ describe("ProviderDetailView", () => {
expect(screen.getByText("96.0%")).toBeInTheDocument();
expect(screen.getByText(/Most used model: gpt-5.6-sol/)).toBeInTheDocument();
});
+
+ /**
+ * SBS-876: Cursor missing-plan still writes 0% primary. Detail must
+ * headline the named state, not "0% used".
+ */
+ it("does not headline 0% when Cursor plan is unavailable", async () => {
+ const cursor: ProviderUsageSnapshot = {
+ ...codex(),
+ providerId: "cursor",
+ displayName: "Cursor",
+ primary: rate(0),
+ primaryLabel: "Plan",
+ extraRateWindows: [],
+ inactiveRateWindows: [
+ {
+ id: "cursor-plan",
+ title: "Plan",
+ description: "No usage reported",
+ state: "unavailable",
+ },
+ ],
+ pace: null,
+ resetCreditsAvailable: null,
+ };
+
+ render(
+ ,
+ );
+
+ expect(screen.getByText("Plan usage")).toBeInTheDocument();
+ expect(screen.getByText("Unavailable")).toBeInTheDocument();
+ expect(screen.queryByText("0%")).not.toBeInTheDocument();
+ expect(screen.queryByText("100%")).not.toBeInTheDocument();
+ });
});
diff --git a/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx b/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx
index ab198f53..07900941 100644
--- a/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx
+++ b/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx
@@ -20,6 +20,8 @@ import {
allMeasuredWindows,
bankedResetCredits,
formatShortDuration,
+ isPrimaryPlaceholderId,
+ primaryNamedState,
} from "../lib/capacityPresentation";
type DetailWindow = {
@@ -299,12 +301,17 @@ export default function ProviderDetailView({
);
const metrics = useMemo(
() =>
- // On-demand is the only Cursor lane that bills real money, and it now
- // carries that money beside its bar, so it is the most actionable row
- // here rather than noise. (Promotional no longer exists at all.)
- allMeasuredWindows(provider).slice(1),
+ // Other limits = every measured window except the hero primary.
+ // Filter by id, not `.slice(1)`: when the primary is a named
+ // placeholder it is already omitted, and slicing would drop Auto
+ // (SBS-876).
+ allMeasuredWindows(provider).filter((window) => window.id !== "primary"),
[provider],
);
+ const namedPrimary = primaryNamedState(provider);
+ const otherInactiveWindows = (provider.inactiveRateWindows ?? []).filter(
+ (metric) => !namedPrimary || !isPrimaryPlaceholderId(metric.id),
+ );
const primaryPercent = Math.round(percentFor(provider.primary, showAsUsed));
const primaryLabel = provider.primaryLabel?.trim() || "Primary";
const planName = displayPlanName(provider.planName);
@@ -366,13 +373,27 @@ export default function ProviderDetailView({
{primaryLabel} usage
- {primaryReset && {primaryReset} }
-
-
- {primaryPercent}%
- {showAsUsed ? "used" : "left"}
+ {primaryReset && !namedPrimary && {primaryReset} }
-
+ {namedPrimary ? (
+
+
+ {namedPrimary === "unavailable"
+ ? t("WindowUnavailable")
+ : t("NotCurrentlyEnforced")}
+
+
+ ) : (
+ <>
+
+ {primaryPercent}%
+ {showAsUsed ? "used" : "left"}
+
+
+ >
+ )}
{provider.pace && (
@@ -386,7 +407,7 @@ export default function ProviderDetailView({
)}
- {(metrics.length > 0 || (provider.inactiveRateWindows?.length ?? 0) > 0) && (
+ {(metrics.length > 0 || otherInactiveWindows.length > 0) && (
Other limits
{metrics.map((metric) => (
@@ -397,7 +418,7 @@ export default function ProviderDetailView({
showAsUsed={showAsUsed}
/>
))}
- {(provider.inactiveRateWindows ?? []).map((metric) => {
+ {otherInactiveWindows.map((metric) => {
const unavailable = metric.state === "unavailable";
return (
({
useSettings: (settings: unknown) => ({ settings }),
}));
+vi.mock("../hooks/useLocale", () => ({
+ useLocale: () => ({
+ t: (key: string) => {
+ if (key === "NotCurrentlyEnforced") return "Not currently enforced";
+ if (key === "WindowUnavailable") return "Unavailable";
+ return key;
+ },
+ }),
+}));
+
import TaskbarFlyout from "./TaskbarFlyout";
function provider(
@@ -375,6 +385,46 @@ describe("TaskbarFlyout", () => {
expect(screen.getByText("$1112.92 of $1800.00")).toBeInTheDocument();
});
+ /**
+ * SBS-876: a missing Cursor plan used to render a lone Plan 0% bar because
+ * flyoutWindows preferred primary and ignored inactiveRateWindows.
+ */
+ it("does not render a 0% Plan bar when Cursor monthly is unavailable", () => {
+ const cursor = provider("cursor", "Cursor", 0, 22 * 24 * 60, "Plan");
+ cursor.inactiveRateWindows = [
+ {
+ id: "cursor-plan",
+ title: "Plan",
+ description: "No usage reported",
+ state: "unavailable",
+ },
+ ];
+ providerState.providers = [cursor];
+
+ render(
+ ,
+ );
+
+ expect(screen.getByText("Unavailable")).toBeInTheDocument();
+ expect(screen.getByText("Plan")).toBeInTheDocument();
+ expect(
+ screen.queryByRole("progressbar", { name: /Cursor Plan 0%/ }),
+ ).not.toBeInTheDocument();
+ expect(screen.queryByText("0%")).not.toBeInTheDocument();
+ });
+
it("opens the full dashboard and dismisses the glance flyout", async () => {
render( );
fireEvent.click(screen.getByRole("button", { name: "Open Ceiling" }));
diff --git a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx
index 481ce7e9..c5da7bee 100644
--- a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx
+++ b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx
@@ -6,7 +6,13 @@ import { useProviders } from "../hooks/useProviders";
import { useSettings } from "../hooks/useSettings";
import { getProviderIcon } from "../components/providers/providerIcons";
import { orderProviderSnapshots } from "../lib/providerOrder";
-import { allMeasuredWindows, bankedResetCredits, type ConstrainingWindow } from "../lib/capacityPresentation";
+import { useLocale } from "../hooks/useLocale";
+import {
+ allMeasuredWindows,
+ bankedResetCredits,
+ type ConstrainingWindow,
+ type NamedWindowState,
+} from "../lib/capacityPresentation";
import {
dismissTrayPanel,
getTaskbarSurfaceColor,
@@ -92,17 +98,30 @@ function isResetClockWindow(window: ConstrainingWindow): boolean {
);
}
+function namedStateRows(provider: ProviderUsageSnapshot): ConstrainingWindow[] {
+ return (provider.inactiveRateWindows ?? []).map((row) => ({
+ id: `inactive-${row.id}`,
+ label: row.title.trim() || row.id,
+ // Percent is not painted for named-state rows; the primary snapshot is
+ // only here to satisfy ConstrainingWindow (SBS-876).
+ window: provider.primary,
+ namedState: (row.state ?? "notEnforced") as NamedWindowState,
+ }));
+}
+
function flyoutWindows(provider: ProviderUsageSnapshot): ConstrainingWindow[] {
+ // allMeasuredWindows already omits a placeholder primary (SBS-876).
const windows = allMeasuredWindows(provider).filter(isMeteredWindow);
+ const named = namedStateRows(provider);
if (provider.providerId !== "cursor") {
- return windows.slice(0, MAX_VISIBLE_WINDOWS_PER_PROVIDER);
+ return [...windows, ...named].slice(0, MAX_VISIBLE_WINDOWS_PER_PROVIDER);
}
- // Cursor's three durable allowances plus the lane that actually charges you.
+ // Cursor's durable allowances plus the lane that actually charges you.
// On-demand is pinned rather than left to fill a leftover slot: when the
// other three are depleted it is the only row that still means anything.
+ // Placeholder Plan is not in `windows`; it arrives as a named-state row.
const preferredIds = [
- "primary",
"secondary",
"extra-cursor-api",
"extra-cursor-on-demand",
@@ -113,7 +132,10 @@ function flyoutWindows(provider: ProviderUsageSnapshot): ConstrainingWindow[] {
const remaining = windows.filter(
(window) => !preferred.some((candidate) => candidate.id === window.id),
);
- return [...preferred, ...remaining].slice(0, MAX_VISIBLE_WINDOWS_PER_PROVIDER);
+ return [...preferred, ...remaining, ...named].slice(
+ 0,
+ MAX_VISIBLE_WINDOWS_PER_PROVIDER,
+ );
}
function ProviderRow({ provider, showAccount, hideEmail, onStrip, showAsUsed, now }: {
@@ -127,6 +149,7 @@ function ProviderRow({ provider, showAccount, hideEmail, onStrip, showAsUsed, no
showAsUsed: boolean;
now: number;
}) {
+ const { t } = useLocale();
const accountName = showAccount
? accountIdentityLabel(provider, hideEmail)
: null;
@@ -190,7 +213,23 @@ function ProviderRow({ provider, showAccount, hideEmail, onStrip, showAsUsed, no
)}
- {windows.map(({ id, label, window, amount }) => {
+ {windows.map(({ id, label, window, amount, namedState }) => {
+ if (namedState) {
+ const unavailable = namedState === "unavailable";
+ return (
+
+ {label}
+
+ {unavailable
+ ? t("WindowUnavailable")
+ : t("NotCurrentlyEnforced")}
+
+
+ );
+ }
const percent = valueFor(window, showAsUsed);
const reset = compactDuration(window.resetsAt, window.resetDescription, now);
const level = meterLevel(window);
From 6669b7c606834c19ff97d2a4e054fc607cac2b33 Mon Sep 17 00:00:00 2001
From: tsouth89
Date: Sun, 16 Aug 2026 06:24:39 -0400
Subject: [PATCH 2/6] Carry the named state through calm, pace, the tile, and
lane order (SBS-876)
Four glance readers still treated a placeholder Plan as a live quota.
Calm float-bar pills called `calmPresentation` for a named-state hero, so a
Cursor account with no monthly reading led with "On pace" and the billing-cycle
reset and never showed Unavailable. Exact mode already suppressed both. Calm now
drops pace and reset and shows the same named label.
The native taskbar tile omitted the percent but had no label to put in its
place, so it fell through to the em dash - the same slot a fetch error paints -
plus the placeholder Plan label and its billing reset. `ProviderReadout` now
carries a localized named label, painted ahead of the em dash, and the reset is
gated behind `strip_reset_label` so a named state cannot print a countdown.
Provider detail headlined the named state and then rendered `provider.pace`
twice below it, a verdict computed from the fake 0%. Pace is now dropped
whenever the primary is a placeholder. The existing test set pace to null, so it
could not catch this; it now carries a real pace.
Dropping "primary" from the Cursor flyout preference list stopped a placeholder
leaving a hole, but it also demoted a *real* Plan reading to the leftover lane,
where it rendered last, under On-demand. `primary` is back in the list;
`allMeasuredWindows` already omits the placeholder, so the existing
find-and-filter handles the missing case.
Fail-without-fix: reverting each production file with the tests kept fails the
new calm pill, detail pace, and lane-order cases, and the two Rust helpers do
not exist. Gate: 622 frontend tests, tsc, cargo fmt, clippy -D warnings, 561
desktop crate tests.
---
.../src-tauri/src/taskbar_widget.rs | 115 ++++++++++++++++--
.../src/floatbar/FloatBar.test.tsx | 50 ++++++++
apps/desktop-tauri/src/floatbar/FloatBar.tsx | 11 +-
.../src/surfaces/ProviderDetailView.test.tsx | 16 ++-
.../src/surfaces/ProviderDetailView.tsx | 18 +--
.../src/surfaces/TaskbarFlyout.test.tsx | 50 ++++++++
.../src/surfaces/TaskbarFlyout.tsx | 5 +-
7 files changed, 243 insertions(+), 22 deletions(-)
diff --git a/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs b/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
index 53762b46..094d1c11 100644
--- a/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
+++ b/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
@@ -45,6 +45,10 @@ struct ProviderReadout {
amount_label_compact: Option,
window_label: String,
reset: Option,
+ /// Localized "Unavailable" / "Not currently enforced" for a placeholder
+ /// window. Painted ahead of the em dash so the tile reads as a named state
+ /// rather than as a fetch error (SBS-876).
+ named_label: Option,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
@@ -129,6 +133,31 @@ fn primary_named_state(snapshot: &crate::commands::ProviderUsageSnapshot) -> Opt
})
}
+/// Tile text for a window that reports a named state instead of a reading.
+fn strip_named_label(
+ readout: &ConstrainingReadout<'_>,
+ lang: codexbar::settings::Language,
+) -> Option {
+ let key = match readout.named_state? {
+ "unavailable" => codexbar::locale::LocaleKey::WindowUnavailable,
+ _ => codexbar::locale::LocaleKey::NotCurrentlyEnforced,
+ };
+ Some(codexbar::locale::get_text(lang, key))
+}
+
+/// Inline reset for the tile, when the user asked for it and the window is a
+/// real reading. A named-state window has no quota to run out, so its
+/// billing-cycle date is not a countdown (SBS-876).
+fn strip_reset_label(readout: &ConstrainingReadout<'_>, show_reset_inline: bool) -> Option {
+ if !show_reset_inline || readout.named_state.is_some() {
+ return None;
+ }
+ crate::tray_bridge::tooltip_short_reset(
+ readout.window.resets_at.as_deref(),
+ readout.window.reset_description.as_deref(),
+ )
+}
+
fn strip_readout_percent(readout: &ConstrainingReadout<'_>, show_as_used: bool) -> Option {
if readout.named_state.is_some() {
return None;
@@ -1210,17 +1239,11 @@ mod windows_host {
snapshot.and_then(|snapshot| snapshot.primary.window_minutes)
}),
),
- reset: settings
- .float_bar_show_reset_inline
- .then(|| {
- constraining.and_then(|readout| {
- crate::tray_bridge::tooltip_short_reset(
- readout.window.resets_at.as_deref(),
- readout.window.reset_description.as_deref(),
- )
- })
- })
- .flatten(),
+ reset: constraining.and_then(|readout| {
+ strip_reset_label(&readout, settings.float_bar_show_reset_inline)
+ }),
+ named_label: constraining
+ .and_then(|readout| strip_named_label(&readout, settings.ui_language)),
}
})
.collect();
@@ -1671,6 +1694,9 @@ mod windows_host {
provider.amount_label.as_deref(),
provider.amount_label_compact.as_deref(),
percent_label.as_deref(),
+ // "Unavailable" before the em dash: a placeholder window is a
+ // known state, not the unknown a fetch error leaves (SBS-876).
+ provider.named_label.as_deref(),
Some("—"),
]
.into_iter()
@@ -3348,6 +3374,73 @@ mod tests {
assert_eq!(strip_readout_percent(&with_auto, true), Some(42));
}
+ /// SBS-876: omitting the percent is only half the job. Without a label the
+ /// tile falls through to the em dash, which is what a fetch error paints —
+ /// the user cannot tell "no reading exists" from "the fetch broke".
+ #[test]
+ fn cursor_strip_labels_the_named_state_instead_of_an_em_dash() {
+ let mut snapshot = snap("cursor", None, 0.0);
+ snapshot.primary_label = Some("Plan".into());
+ snapshot.primary.resets_at = Some("2099-01-01T00:00:00Z".into());
+ snapshot
+ .inactive_rate_windows
+ .push(crate::commands::InactiveRateWindowSnapshot {
+ id: "cursor-plan".into(),
+ title: "Plan".into(),
+ description: "No usage reported".into(),
+ state: "unavailable".into(),
+ });
+
+ let readout = constraining_readout(&snapshot);
+ let lang = codexbar::settings::Language::default();
+ assert_eq!(
+ strip_named_label(&readout, lang).as_deref(),
+ Some("Unavailable")
+ );
+
+ // A lifted limit is a different sentence from a missing reading.
+ snapshot.inactive_rate_windows[0].state = "notEnforced".into();
+ let lifted = constraining_readout(&snapshot);
+ assert_eq!(
+ strip_named_label(&lifted, lang).as_deref(),
+ Some("Not currently enforced")
+ );
+
+ // A real reading has no named label to paint.
+ snapshot.inactive_rate_windows.clear();
+ assert!(strip_named_label(&constraining_readout(&snapshot), lang).is_none());
+ }
+
+ /// SBS-876: the billing-cycle date on a placeholder Plan is not a countdown,
+ /// so the tile must not print it beside the named state.
+ #[test]
+ fn cursor_strip_omits_reset_when_plan_is_unavailable() {
+ let mut snapshot = snap("cursor", None, 0.0);
+ snapshot.primary_label = Some("Plan".into());
+ snapshot.primary.reset_description = Some("Resets monthly".into());
+ snapshot
+ .inactive_rate_windows
+ .push(crate::commands::InactiveRateWindowSnapshot {
+ id: "cursor-plan".into(),
+ title: "Plan".into(),
+ description: "No usage reported".into(),
+ state: "unavailable".into(),
+ });
+
+ assert_eq!(
+ strip_reset_label(&constraining_readout(&snapshot), true),
+ None
+ );
+
+ // A real reading still shows its reset when the setting is on.
+ snapshot.inactive_rate_windows.clear();
+ assert!(strip_reset_label(&constraining_readout(&snapshot), true).is_some());
+ assert_eq!(
+ strip_reset_label(&constraining_readout(&snapshot), false),
+ None
+ );
+ }
+
#[test]
fn uncapped_spend_reports_spend_even_in_remaining_mode() {
// No denominator means no headroom figure exists. Falling back to
diff --git a/apps/desktop-tauri/src/floatbar/FloatBar.test.tsx b/apps/desktop-tauri/src/floatbar/FloatBar.test.tsx
index 0050fc2d..5da8f904 100644
--- a/apps/desktop-tauri/src/floatbar/FloatBar.test.tsx
+++ b/apps/desktop-tauri/src/floatbar/FloatBar.test.tsx
@@ -315,6 +315,56 @@ describe("FloatBar", () => {
expect(container.querySelector(".floatbar__pct--calm")).toHaveTextContent("60%");
});
+ /**
+ * SBS-876: exact mode already dropped the pace and reset for a placeholder
+ * window. Calm still built both from the required 0% primary, so the pill
+ * read "On pace · resets in 5d" for a plan with no reading at all.
+ */
+ it("calm mode names the state instead of pacing an unavailable plan", async () => {
+ const unavailable: ProviderUsageSnapshot = {
+ ...snapshot("cursor", "Cursor", 0, {
+ resetsAt: new Date(Date.now() + 5 * 24 * 3600_000).toISOString(),
+ }),
+ updatedAt: new Date().toISOString(),
+ inactiveRateWindows: [
+ {
+ id: "cursor-plan",
+ title: "Plan",
+ description: "No usage reported",
+ state: "unavailable",
+ },
+ ],
+ pace: {
+ windowLabel: "Plan",
+ stage: "far_ahead",
+ deltaPercent: -38.6,
+ willLastToReset: true,
+ etaSeconds: null,
+ expectedUsedPercent: 38.6,
+ actualUsedPercent: 0,
+ },
+ };
+ tauriMocks.getCachedProviders.mockResolvedValue([unavailable]);
+ tauriMocks.getSettingsSnapshot.mockResolvedValue(
+ settings({ floatBarInformationMode: "calm", enabledProviders: ["cursor"] }),
+ );
+
+ const { container } = renderFloatBar(
+ bootstrap({ floatBarInformationMode: "calm", enabledProviders: ["cursor"] }),
+ );
+ await waitFor(() => {
+ expect(container.querySelector(".floatbar__pill--calm")).toBeInTheDocument();
+ });
+
+ expect(container.querySelector(".floatbar__pct--calm")).toHaveTextContent(
+ "Unavailable",
+ );
+ expect(container.querySelector(".floatbar__pace")).toBeNull();
+ expect(container.querySelector(".floatbar__calm-reset")).toBeNull();
+ expect(container.querySelector(".floatbar__pill--calm")?.getAttribute("title"))
+ .not.toContain("0%");
+ });
+
it("does not render hypothetical local costs from the legacy setting", async () => {
tauriMocks.getCachedProviders.mockResolvedValue([
snapshot("codex", "Codex", 75),
diff --git a/apps/desktop-tauri/src/floatbar/FloatBar.tsx b/apps/desktop-tauri/src/floatbar/FloatBar.tsx
index 18eb67cd..5cb6eea2 100644
--- a/apps/desktop-tauri/src/floatbar/FloatBar.tsx
+++ b/apps/desktop-tauri/src/floatbar/FloatBar.tsx
@@ -245,13 +245,20 @@ function ProviderPill({
// stays one keyboard/click away. The pill becomes an expandable button, so it
// opts out of the native drag region (drag the bar by its handle instead).
if (informationMode === "calm") {
- const calm = calmPresentation(provider, hero);
+ // A named-state window is not a quota. Its pace and billing reset are both
+ // derived from the placeholder 0%, so calm drops them and shows the same
+ // named label exact mode does (SBS-876).
+ const calm = hero.namedState
+ ? { pace: null, hasReset: false }
+ : calmPresentation(provider, hero);
// Compact hides the window·reset row, so calm degrades to pace-or-exact.
// Otherwise show exact only when there is no pace and no reset time to show.
// Either way the pill is never blank.
const showResetRow = !isCompact && calm.hasReset;
const showExact =
- expanded || (isCompact ? !calm.pace : !calm.pace && !inlineReset);
+ !!hero.namedState ||
+ expanded ||
+ (isCompact ? !calm.pace : !calm.pace && !inlineReset);
const onKeyToggle = (event: ReactKeyboardEvent) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
diff --git a/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx b/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
index 296a693a..74397839 100644
--- a/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
+++ b/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
@@ -182,7 +182,18 @@ describe("ProviderDetailView", () => {
state: "unavailable",
},
],
- pace: null,
+ // The bridge still derives pace from the required 0% primary, so a real
+ // Cursor snapshot arrives with a verdict attached. Keep it here: a null
+ // pace could not catch the pace copy leaking beside "Unavailable".
+ pace: {
+ windowLabel: "Plan",
+ stage: "far_ahead",
+ deltaPercent: -38.6,
+ willLastToReset: true,
+ etaSeconds: null,
+ expectedUsedPercent: 38.6,
+ actualUsedPercent: 0,
+ },
resetCreditsAvailable: null,
};
@@ -198,5 +209,8 @@ describe("ProviderDetailView", () => {
expect(screen.getByText("Unavailable")).toBeInTheDocument();
expect(screen.queryByText("0%")).not.toBeInTheDocument();
expect(screen.queryByText("100%")).not.toBeInTheDocument();
+ // A pace verdict read off the placeholder 0% is not a reading either.
+ expect(screen.queryByText(/Plan pace/)).not.toBeInTheDocument();
+ expect(screen.queryByText(/ahead of budget/)).not.toBeInTheDocument();
});
});
diff --git a/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx b/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx
index 07900941..381a0198 100644
--- a/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx
+++ b/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx
@@ -312,6 +312,10 @@ export default function ProviderDetailView({
const otherInactiveWindows = (provider.inactiveRateWindows ?? []).filter(
(metric) => !namedPrimary || !isPrimaryPlaceholderId(metric.id),
);
+ // Pace is computed from the primary window. When that primary is a named
+ // placeholder the verdict is a reading of the fake 0%, so drop it rather than
+ // print "Far behind" beside "Unavailable" (SBS-876).
+ const pace = namedPrimary ? null : provider.pace;
const primaryPercent = Math.round(percentFor(provider.primary, showAsUsed));
const primaryLabel = provider.primaryLabel?.trim() || "Primary";
const planName = displayPlanName(provider.planName);
@@ -394,14 +398,14 @@ export default function ProviderDetailView({
>
)}
- {provider.pace && (
-
+ {pace && (
+
- {provider.pace.windowLabel} pace
+ {pace.windowLabel} pace
- {paceLabel(provider.pace.stage)} ·{" "}
- {provider.pace.deltaPercent >= 0 ? "+" : ""}
- {provider.pace.deltaPercent.toFixed(1)}%
+ {paceLabel(pace.stage)} ·{" "}
+ {pace.deltaPercent >= 0 ? "+" : ""}
+ {pace.deltaPercent.toFixed(1)}%
)}
@@ -444,7 +448,7 @@ export default function ProviderDetailView({
)}
{chartData?.localUsage &&
}
- {provider.pace &&
}
+ {pace &&
}
>
)}
diff --git a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.test.tsx b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.test.tsx
index 48ac233b..1c25719e 100644
--- a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.test.tsx
+++ b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.test.tsx
@@ -425,6 +425,56 @@ describe("TaskbarFlyout", () => {
expect(screen.queryByText("0%")).not.toBeInTheDocument();
});
+ /**
+ * SBS-876 follow-up: dropping `primary` from the Cursor preference list to
+ * make room for the named-state row also demoted a *real* Plan reading to the
+ * leftover lane, so it rendered last — under On-demand — instead of leading
+ * the provider it is the headline allowance for.
+ */
+ it("keeps a real Cursor Plan at the top of its lanes", () => {
+ const cursor = provider("cursor", "Cursor", 51, 22 * 24 * 60, "Plan");
+ cursor.secondary = { ...cursor.primary, usedPercent: 99, remainingPercent: 1 };
+ cursor.secondaryLabel = "Auto";
+ cursor.extraRateWindows = [
+ {
+ id: "cursor-api",
+ title: "API",
+ window: { ...cursor.primary, usedPercent: 38, remainingPercent: 62 },
+ },
+ {
+ id: "cursor-on-demand",
+ title: "On-demand",
+ window: { ...cursor.primary, usedPercent: 62, remainingPercent: 38 },
+ },
+ ];
+ providerState.providers = [cursor];
+
+ const { container } = render(
+
,
+ );
+
+ expect(
+ screen.getByRole("progressbar", { name: "Cursor Plan 51%" }),
+ ).toBeInTheDocument();
+ const labels = Array.from(
+ container.querySelectorAll(".taskbar-flyout__meter-label"),
+ ).map((node) => node.textContent);
+ expect(labels).toEqual(["Plan", "Auto", "API", "On-demand"]);
+ expect(screen.queryByText(/more limits in Ceiling/)).not.toBeInTheDocument();
+ });
+
it("opens the full dashboard and dismisses the glance flyout", async () => {
render(
);
fireEvent.click(screen.getByRole("button", { name: "Open Ceiling" }));
diff --git a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx
index c5da7bee..e02371f1 100644
--- a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx
+++ b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx
@@ -120,8 +120,11 @@ function flyoutWindows(provider: ProviderUsageSnapshot): ConstrainingWindow[] {
// Cursor's durable allowances plus the lane that actually charges you.
// On-demand is pinned rather than left to fill a leftover slot: when the
// other three are depleted it is the only row that still means anything.
- // Placeholder Plan is not in `windows`; it arrives as a named-state row.
+ // A placeholder Plan is not in `windows`; it arrives as a named-state row, so
+ // keeping `primary` in the preference list costs nothing when it is missing
+ // and stops a real Plan reading from being pushed past the visible slots.
const preferredIds = [
+ "primary",
"secondary",
"extra-cursor-api",
"extra-cursor-on-demand",
From 5947ac6e5af293458eaa24deedd50facd31e4d5f Mon Sep 17 00:00:00 2001
From: tsouth89
Date: Sun, 16 Aug 2026 07:33:30 -0400
Subject: [PATCH 3/6] Give the named state a spelling that fits a crowded tile
(SBS-876)
Painting the full "Unavailable" was only half a fix. The tile headline gets
`item_width - 21`px, which is about 51px once five providers share the strip,
and "Unavailable" needs roughly 72px at the 14px tile font. "Not currently
enforced" never fits. The candidate ladder keeps the narrowest spelling when
nothing fits, so both fell through to the em dash - the glyph a fetch error
paints - on exactly the strips that are busiest.
Adds `StripStateUnavailable` ("n/a") and `StripStateNotEnforced` ("No cap") in
both catalogs, and `compact_named_label` between the full spelling and the em
dash, mirroring how `compact_amount_label` already backs `strip_amount_label`.
`named_state_has_a_spelling_that_fits_a_crowded_tile` pins both spellings as
shorter than the full label and within the narrow-tile budget. Locale drift
check passes at 780 keys.
---
.../src-tauri/src/taskbar_widget.rs | 69 ++++++++++++++++++-
apps/desktop-tauri/src/i18n/keys.ts | 2 +
rust/src/locale.rs | 5 ++
rust/src/locale/en-US.ftl | 2 +
rust/src/locale/zh-CN.ftl | 2 +
5 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs b/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
index 094d1c11..e41613cb 100644
--- a/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
+++ b/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
@@ -49,6 +49,8 @@ struct ProviderReadout {
/// window. Painted ahead of the em dash so the tile reads as a named state
/// rather than as a fetch error (SBS-876).
named_label: Option,
+ /// Tile-width spelling of `named_label` for strips too narrow for it.
+ named_label_compact: Option,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
@@ -145,6 +147,24 @@ fn strip_named_label(
Some(codexbar::locale::get_text(lang, key))
}
+/// Tile-width spelling of [`strip_named_label`].
+///
+/// Same reason [`compact_amount_label`] exists: five providers on a crowded
+/// taskbar leave roughly 51px for the headline, and "Unavailable" needs about
+/// 72px at the 14px tile font. Without a short form the ladder falls through to
+/// the em dash — the glyph a fetch error paints — so a known state would read as
+/// an unknown one exactly when the strip is busiest (SBS-876).
+fn compact_named_label(
+ readout: &ConstrainingReadout<'_>,
+ lang: codexbar::settings::Language,
+) -> Option {
+ let key = match readout.named_state? {
+ "unavailable" => codexbar::locale::LocaleKey::StripStateUnavailable,
+ _ => codexbar::locale::LocaleKey::StripStateNotEnforced,
+ };
+ Some(codexbar::locale::get_text(lang, key))
+}
+
/// Inline reset for the tile, when the user asked for it and the window is a
/// real reading. A named-state window has no quota to run out, so its
/// billing-cycle date is not a countdown (SBS-876).
@@ -1244,6 +1264,8 @@ mod windows_host {
}),
named_label: constraining
.and_then(|readout| strip_named_label(&readout, settings.ui_language)),
+ named_label_compact: constraining
+ .and_then(|readout| compact_named_label(&readout, settings.ui_language)),
}
})
.collect();
@@ -1694,9 +1716,11 @@ mod windows_host {
provider.amount_label.as_deref(),
provider.amount_label_compact.as_deref(),
percent_label.as_deref(),
- // "Unavailable" before the em dash: a placeholder window is a
- // known state, not the unknown a fetch error leaves (SBS-876).
+ // "Unavailable", then "n/a", before the em dash: a placeholder
+ // window is a known state, not the unknown a fetch error leaves
+ // (SBS-876).
provider.named_label.as_deref(),
+ provider.named_label_compact.as_deref(),
Some("—"),
]
.into_iter()
@@ -3411,6 +3435,47 @@ mod tests {
assert!(strip_named_label(&constraining_readout(&snapshot), lang).is_none());
}
+ /// SBS-876: five providers leave roughly 51px for a tile headline, which
+ /// "Unavailable" (~72px at the 14px tile font) overruns. Without a short
+ /// spelling the ladder reaches the em dash and the named state reads as a
+ /// fetch error on exactly the strips that are busiest.
+ #[test]
+ fn named_state_has_a_spelling_that_fits_a_crowded_tile() {
+ let mut snapshot = snap("cursor", None, 0.0);
+ snapshot.primary_label = Some("Plan".into());
+ snapshot
+ .inactive_rate_windows
+ .push(crate::commands::InactiveRateWindowSnapshot {
+ id: "cursor-plan".into(),
+ title: "Plan".into(),
+ description: "No usage reported".into(),
+ state: "unavailable".into(),
+ });
+ let lang = codexbar::settings::Language::default();
+
+ for state in ["unavailable", "notEnforced"] {
+ snapshot.inactive_rate_windows[0].state = state.into();
+ let readout = constraining_readout(&snapshot);
+ let full = strip_named_label(&readout, lang).expect("full spelling");
+ let compact = compact_named_label(&readout, lang).expect("compact spelling");
+ assert!(
+ compact.chars().count() < full.chars().count(),
+ "{state}: compact {compact:?} must be shorter than {full:?}"
+ );
+ // The narrowest tile budget fits about 8 characters of the headline
+ // font. Anything longer lands back on the em dash.
+ assert!(
+ compact.chars().count() <= 8,
+ "{state}: {compact:?} is too wide for a five-provider strip"
+ );
+ }
+
+ // A real reading still has no named spelling at either width.
+ snapshot.inactive_rate_windows.clear();
+ let real = constraining_readout(&snapshot);
+ assert!(compact_named_label(&real, lang).is_none());
+ }
+
/// SBS-876: the billing-cycle date on a placeholder Plan is not a countdown,
/// so the tile must not print it beside the named state.
#[test]
diff --git a/apps/desktop-tauri/src/i18n/keys.ts b/apps/desktop-tauri/src/i18n/keys.ts
index 9a646777..f291365d 100644
--- a/apps/desktop-tauri/src/i18n/keys.ts
+++ b/apps/desktop-tauri/src/i18n/keys.ts
@@ -696,6 +696,8 @@ export const ALL_LOCALE_KEYS = [
"FreshnessError",
"NotCurrentlyEnforced",
"WindowUnavailable",
+ "StripStateUnavailable",
+ "StripStateNotEnforced",
"TaskbarUsageTitle",
"ShowTaskbarUsage",
"ShowTaskbarUsageHelp",
diff --git a/rust/src/locale.rs b/rust/src/locale.rs
index 78c5006b..43368e07 100644
--- a/rust/src/locale.rs
+++ b/rust/src/locale.rs
@@ -947,6 +947,11 @@ locale_keys! {
FreshnessError,
NotCurrentlyEnforced,
WindowUnavailable,
+ // Tile-width spellings of the two above. A provider tile on a crowded
+ // taskbar has ~51px for its headline, which "Unavailable" overruns, so the
+ // strip needs a short form or it falls back to the error em dash (SBS-876).
+ StripStateUnavailable,
+ StripStateNotEnforced,
TaskbarUsageTitle,
ShowTaskbarUsage,
ShowTaskbarUsageHelp,
diff --git a/rust/src/locale/en-US.ftl b/rust/src/locale/en-US.ftl
index 4ae5e8af..34d5c5a3 100644
--- a/rust/src/locale/en-US.ftl
+++ b/rust/src/locale/en-US.ftl
@@ -690,6 +690,8 @@ FreshnessStale = Stale
FreshnessError = Error
NotCurrentlyEnforced = Not currently enforced
WindowUnavailable = Unavailable
+StripStateUnavailable = n/a
+StripStateNotEnforced = No cap
AboutCopyrightMid = , which is based on
AboutCopyrightSuffix = { " by Peter Steinberger." }
TaskbarUsageTitle = Taskbar Usage
diff --git a/rust/src/locale/zh-CN.ftl b/rust/src/locale/zh-CN.ftl
index ea2d3561..2c1bc5ec 100644
--- a/rust/src/locale/zh-CN.ftl
+++ b/rust/src/locale/zh-CN.ftl
@@ -690,6 +690,8 @@ FreshnessStale = 数据过期
FreshnessError = 错误
NotCurrentlyEnforced = 当前未强制执行
WindowUnavailable = 不可用
+StripStateUnavailable = 不可用
+StripStateNotEnforced = 无上限
AboutCopyrightMid = ,基于
AboutCopyrightSuffix = ,作者 Peter Steinberger。
TaskbarUsageTitle = 任务栏用量
From bf397c89409898f36064e89a7c9f41b303337c43 Mon Sep 17 00:00:00 2001
From: tsouth89
Date: Sun, 16 Aug 2026 08:31:04 -0400
Subject: [PATCH 4/6] Rank failed accounts below named states, and count hidden
named rows (SBS-876)
Two things the named-state work exposed, both found by CodeRabbit.
`select_strip_snapshot` ranks every account for a provider before
`widget_model` filters `snapshot.error`. An errored account still reads 0% on
its primary, which now outranks a successful account whose Plan is unavailable
at heat -1. The tile was handed a snapshot it then refused to read and painted
the em dash, while the other account could have said "Unavailable". Before this
PR both scored 0.0 and the account-id tiebreak decided it, so introducing -1 is
what made the failure deterministic. `strip_heat` now sinks errored snapshots.
`hiddenWindowCount` measured only metered windows while `windows` also holds
named-state rows, so truncated Unavailable rows were never reported, and once
named rows filled the visible slots the subtraction went negative and clamped to
zero - three measured plus two named rendered four rows and claimed nothing was
hidden. `flyoutCandidateCount` counts both kinds.
Fail-without-fix: reverting TaskbarFlyout.tsx fails the new more-limits case.
Gate: 623 frontend tests, tsc, cargo fmt, clippy -D warnings, 563 desktop tests.
---
.../src-tauri/src/taskbar_widget.rs | 40 +++++++++++++++++
.../src/surfaces/TaskbarFlyout.test.tsx | 43 +++++++++++++++++++
.../src/surfaces/TaskbarFlyout.tsx | 18 +++++++-
3 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs b/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
index e41613cb..fafde2c3 100644
--- a/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
+++ b/apps/desktop-tauri/src-tauri/src/taskbar_widget.rs
@@ -191,6 +191,13 @@ fn strip_readout_percent(readout: &ConstrainingReadout<'_>, show_as_used: bool)
}
fn strip_heat(snapshot: &crate::commands::ProviderUsageSnapshot) -> f64 {
+ // Account ranking runs before `widget_model` drops errored snapshots, so a
+ // failed account must rank below a named state or it wins the tile and then
+ // has no readout to paint - an em dash where "Unavailable" was available
+ // from the other account (SBS-876).
+ if snapshot.error.is_some() {
+ return f64::NEG_INFINITY;
+ }
let readout = constraining_readout(snapshot);
if readout.named_state.is_some() {
return -1.0;
@@ -3017,6 +3024,39 @@ mod tests {
assert_eq!(picked.account_id.as_deref(), Some("work"));
}
+ /// SBS-876: ranking happens before `widget_model` filters errored
+ /// snapshots. A failed account's primary reads 0%, which used to outrank a
+ /// successful account whose Plan is unavailable (heat -1), so the tile was
+ /// handed a snapshot it then refused to read and painted an em dash - while
+ /// the other account could have said "Unavailable".
+ #[test]
+ fn strip_snapshot_prefers_a_named_state_over_a_failed_account() {
+ let mut unavailable = snap("cursor", Some("good"), 0.0);
+ unavailable.primary_label = Some("Plan".into());
+ unavailable
+ .inactive_rate_windows
+ .push(crate::commands::InactiveRateWindowSnapshot {
+ id: "cursor-plan".into(),
+ title: "Plan".into(),
+ description: "No usage reported".into(),
+ state: "unavailable".into(),
+ });
+ let mut failed = snap("cursor", Some("broken"), 0.0);
+ failed.error = Some("network timeout".into());
+
+ let cache = [failed, unavailable];
+ let picked = select_strip_snapshot(cache.iter(), "cursor", None).unwrap();
+
+ assert_eq!(picked.account_id.as_deref(), Some("good"));
+ assert!(picked.error.is_none());
+
+ // A real reading still beats both.
+ let mut cache = cache.to_vec();
+ cache.push(snap("cursor", Some("hot"), 42.0));
+ let picked = select_strip_snapshot(cache.iter(), "cursor", None).unwrap();
+ assert_eq!(picked.account_id.as_deref(), Some("hot"));
+ }
+
#[test]
fn strip_snapshot_respects_pinned_account() {
let cache = [
diff --git a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.test.tsx b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.test.tsx
index 1c25719e..5e572214 100644
--- a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.test.tsx
+++ b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.test.tsx
@@ -475,6 +475,49 @@ describe("TaskbarFlyout", () => {
expect(screen.queryByText(/more limits in Ceiling/)).not.toBeInTheDocument();
});
+ /**
+ * SBS-876: named-state rows compete for the same four visible slots, but the
+ * hidden-row count only measured metered windows. Three measured rows plus
+ * two Unavailable rows rendered four and reported nothing hidden, because the
+ * subtraction went negative and was clamped to zero.
+ */
+ it("counts truncated named-state rows in the more-limits note", () => {
+ const claude = provider("claude", "Claude", 40, 300, "Session (5h)");
+ claude.secondary = { ...claude.primary, usedPercent: 61, remainingPercent: 39 };
+ claude.secondaryLabel = "Weekly";
+ claude.extraRateWindows = [
+ {
+ id: "claude-opus",
+ title: "Opus weekly",
+ window: { ...claude.primary, usedPercent: 12, remainingPercent: 88 },
+ },
+ ];
+ claude.inactiveRateWindows = [
+ { id: "one", title: "Sonnet weekly", description: "", state: "unavailable" },
+ { id: "two", title: "Haiku weekly", description: "", state: "unavailable" },
+ ];
+ providerState.providers = [claude];
+
+ render(
+ ,
+ );
+
+ // 3 measured + 2 named = 5 candidates, 4 slots, so exactly one is cut.
+ expect(screen.getByText("+1 more limits in Ceiling")).toBeInTheDocument();
+ });
+
it("opens the full dashboard and dismisses the glance flyout", async () => {
render( );
fireEvent.click(screen.getByRole("button", { name: "Open Ceiling" }));
diff --git a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx
index e02371f1..78e6e5d6 100644
--- a/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx
+++ b/apps/desktop-tauri/src/surfaces/TaskbarFlyout.tsx
@@ -141,6 +141,22 @@ function flyoutWindows(provider: ProviderUsageSnapshot): ConstrainingWindow[] {
);
}
+/**
+ * Every row `flyoutWindows` had to choose from, before the visible-row cap.
+ *
+ * The "more limits" note is the only sign that something was cut, so it has to
+ * count named-state rows too. Measuring hidden rows against the measured
+ * windows alone hid truncated Unavailable rows entirely, and once named rows
+ * filled the visible slots the subtraction went negative and reported nothing
+ * hidden at all (SBS-876).
+ */
+function flyoutCandidateCount(provider: ProviderUsageSnapshot): number {
+ return (
+ allMeasuredWindows(provider).filter(isMeteredWindow).length +
+ namedStateRows(provider).length
+ );
+}
+
function ProviderRow({ provider, showAccount, hideEmail, onStrip, showAsUsed, now }: {
provider: ProviderUsageSnapshot;
// True when this provider has more than one account, so the account name is
@@ -186,7 +202,7 @@ function ProviderRow({ provider, showAccount, hideEmail, onStrip, showAsUsed, no
const resetCredits = bankedResetCredits(provider);
const hiddenWindowCount = Math.max(
0,
- allMeasuredWindows(provider).filter(isMeteredWindow).length - windows.length,
+ flyoutCandidateCount(provider) - windows.length,
);
return (
Date: Sun, 16 Aug 2026 12:01:47 -0400
Subject: [PATCH 5/6] Scope the pace suppression to the placeholder window
(SBS-876)
`const pace = namedPrimary ? null : provider.pace` was too broad. Pace is not
always the primary's: `preferred_pace` in bridge.rs walks every long window and
keeps the worst delta, so a Cursor account whose Plan is unavailable usually
reports an Auto pace instead. Nulling on `namedPrimary` alone threw that valid
Auto verdict off the detail view along with the placeholder one.
Now suppressed only when the pace window is the primary's own label, so
"Unavailable" and a real "Auto pace" can appear together.
Fail-without-fix: reverting ProviderDetailView.tsx fails the new Auto-pace case
while the existing placeholder case still passes. Gate: 624 frontend tests, tsc.
---
.../src/surfaces/ProviderDetailView.test.tsx | 44 +++++++++++++++++++
.../src/surfaces/ProviderDetailView.tsx | 12 +++--
2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx b/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
index 74397839..523efadf 100644
--- a/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
+++ b/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
@@ -213,4 +213,48 @@ describe("ProviderDetailView", () => {
expect(screen.queryByText(/Plan pace/)).not.toBeInTheDocument();
expect(screen.queryByText(/ahead of budget/)).not.toBeInTheDocument();
});
+
+ /**
+ * SBS-876: `preferred_pace` picks the worst delta across every long window,
+ * so pace is often Auto rather than Plan. Dropping pace whenever the primary
+ * is a placeholder threw away that valid Auto verdict too.
+ */
+ it("keeps an Auto pace when only the Cursor Plan is unavailable", async () => {
+ const cursor: ProviderUsageSnapshot = {
+ ...codex(),
+ providerId: "cursor",
+ displayName: "Cursor",
+ primary: rate(0),
+ primaryLabel: "Plan",
+ secondary: rate(44),
+ secondaryLabel: "Auto",
+ extraRateWindows: [],
+ inactiveRateWindows: [
+ {
+ id: "cursor-plan",
+ title: "Plan",
+ description: "No usage reported",
+ state: "unavailable",
+ },
+ ],
+ pace: {
+ windowLabel: "Auto",
+ stage: "far_ahead",
+ deltaPercent: 31.6,
+ willLastToReset: false,
+ etaSeconds: 3600,
+ expectedUsedPercent: 12.4,
+ actualUsedPercent: 44,
+ },
+ resetCreditsAvailable: null,
+ };
+
+ render(
+
,
+ );
+
+ expect(screen.getByText("Unavailable")).toBeInTheDocument();
+ // The Auto verdict is a reading of a real window, so it survives.
+ expect(screen.getAllByText(/Auto pace/).length).toBeGreaterThan(0);
+ });
});
diff --git a/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx b/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx
index 381a0198..835cf357 100644
--- a/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx
+++ b/apps/desktop-tauri/src/surfaces/ProviderDetailView.tsx
@@ -312,10 +312,14 @@ export default function ProviderDetailView({
const otherInactiveWindows = (provider.inactiveRateWindows ?? []).filter(
(metric) => !namedPrimary || !isPrimaryPlaceholderId(metric.id),
);
- // Pace is computed from the primary window. When that primary is a named
- // placeholder the verdict is a reading of the fake 0%, so drop it rather than
- // print "Far behind" beside "Unavailable" (SBS-876).
- const pace = namedPrimary ? null : provider.pace;
+ // Pace belongs to whichever long window has the worst delta, not always the
+ // primary (`preferred_pace` in bridge.rs picks across all of them). Drop it
+ // only when it is the placeholder's own verdict, which would read a fake 0%;
+ // an Auto pace beside an unavailable Plan is still a real reading (SBS-876).
+ const pace =
+ namedPrimary && provider.pace?.windowLabel === provider.primaryLabel
+ ? null
+ : provider.pace;
const primaryPercent = Math.round(percentFor(provider.primary, showAsUsed));
const primaryLabel = provider.primaryLabel?.trim() || "Primary";
const planName = displayPlanName(provider.planName);
From 85dfae8db37004952605b75609e40e6baf222242 Mon Sep 17 00:00:00 2001
From: tsouth89
Date: Sun, 16 Aug 2026 12:27:30 -0400
Subject: [PATCH 6/6] Keep the Cursor detail fixtures out of Codex plan data
(SBS-876)
Both Cursor cases spread the Codex fixture, so they inherited its
"Pro Lite" plan name and rendered a ChatGPT plan inside a Cursor detail
view. That is the mixing the provider-siloing rule exists to stop, and it
made the fixtures a bad model of what the component actually receives.
---
apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx b/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
index 523efadf..630df652 100644
--- a/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
+++ b/apps/desktop-tauri/src/surfaces/ProviderDetailView.test.tsx
@@ -171,6 +171,9 @@ describe("ProviderDetailView", () => {
...codex(),
providerId: "cursor",
displayName: "Cursor",
+ // Spreading the Codex fixture would otherwise render a ChatGPT plan name
+ // inside a Cursor view, which is exactly what provider siloing forbids.
+ planName: "Ultra",
primary: rate(0),
primaryLabel: "Plan",
extraRateWindows: [],
@@ -224,6 +227,7 @@ describe("ProviderDetailView", () => {
...codex(),
providerId: "cursor",
displayName: "Cursor",
+ planName: "Ultra",
primary: rate(0),
primaryLabel: "Plan",
secondary: rate(44),