Performance and coherence:
- Settings > General 'Refresh every' (Manual/30s/1m/3m/5m/10m), live via
RefreshCadenceContext; Manual polls only on demand
- usePolled memoKey LRU: provider/period switches paint the last-good
result instantly with a switching hairline while refreshing quietly
- quota TTL 5min + honest rate-limited copy on 429 backoff
- version-suffixed cache files (session-cache.v5.json, daily-cache.v12,
auto-minted on future bumps); legacy files never written or deleted,
adopted once when versions match: old and new binaries coexist
without clobbering (field-observed menubar-vs-desktop ping-pong)
- advisory hydration lock: concurrent cold starts share one scan
(wait-then-read-warm), stale/dead locks self-heal, never a
correctness gate
Telemetry v1 + onboarding (desktop only, per owner decisions):
- first-launch onboarding (3 feature screens + consent); region-split
default (EU/EEA/UK/CH off, elsewhere on, unknown off); nothing sends
before consent completion or while off; dev builds never send
- anonymous install UUID, rotated on opt-out; day-granularity events,
cost buckets only; whitelisted names; 200-event queue, 5min flush
- Settings > Privacy live toggle replaces the static claim
Zero computed-number changes. App 316/316, root 1805.
Wire contract targets api.codeburn.app/v1/telemetry (Worker follows).
- formatUsd applies the payload currency {code,symbol,rate} once at
display; formatConverted (symbol only) for CLI-preconverted plan
values so nothing converts twice
- provider picker built from providerDetails: label shown, internal id
sent as --provider (fixes filters for providers whose display name
differs, e.g. Grok Build); falls back to map keys on older CLIs
- getYield threads the active provider through preload/main/sections
App suite 170/170, root 1615/1615.
- Provider filter: Models-this-period sources current.topModels (history
days carry empty topModels per provider); StackedBars falls back to a
cost-proportional single segment like the Swift menubar
- Chart windows align to the CLI (week -7, 30days -30, all = 6 months)
and zero-fill a contiguous calendar window; history.daily is sparse and
both sides key local YYYY-MM-DD, so lookups are safe (verified on real
CLI output)
- Custom range threads into Overview panels (chart, models table) and
suppresses MTD/projected and vs-last-week comparisons; Compare states
that custom dates fall back to the period
- usePolled clears errors per attempt and sections show a StaleBanner
instead of silently rendering last-good data after a failed refresh
- Cache-hit denominator matches the CLI; hero savings relabeled 'Saved by
applied fixes' + new 'Saved via local models' line; formatCompact
everywhere; Optimize 'Fixes' count matches the rendered list
App suite 163/163 (was 147), root 1613/1613.
Drop the Waste/Reverts/Abandoned/Fixes tabs. One scrolling page: findings
(count + potential in the header), then Reverted and Abandoned session sections;
empty sections hidden. The redundant Fixes tab folds into the findings header.
typecheck clean; 126/126 tests pass (removed 2 now-moot tab-isolation tests;
impact-badge + section coverage preserved).
Install an app menu without the CmdOrCtrl+R reload accelerator so ⌘R reaches the renderer for
in-place refresh (keeps Edit/Window roles + dev DevTools). Model labels are now family-level
("Opus"/"Sonnet"/"Haiku"/"GPT / Codex") and the Sankey shows the real model id instead of the
wireframe's sample version names. Optimize retains last-good yield across 30s revalidation (no
flicker to "—"). Removed hints for unimplemented ⌘K/⌘E/esc; fixed stale TopBar comment.
Implemented by Codex gpt-5.5 (high); committed by Fable (git blocked in Codex sandbox).
Reverts/Abandoned totals + bodies show "—" while yield is loading/errored instead of a fake
$0.00; adds positive-path Abandoned and Fixes-tab tests (guards category filtering); reverted/
abandoned costs use plain .val (mint reserved for savings); simplified FixesRows copy.
Implemented by Codex gpt-5.5 (high); committed by Fable (git blocked in Codex sandbox).
Segment tabs carry their totals (Waste=optimize.savingsUSD, Reverts/Abandoned from
getYield summary, Fixes=findingCount). Waste findings from optimize.topFindings; reverts
and abandoned lists from yield.details by category. Evidence lines + copy-fix chips are
honestly omitted (not present in MenubarPayload.optimize) — a richer `optimize --format
json` emitter is flagged as a follow-up.
Implemented by Codex gpt-5.5 (high); committed by Fable (git blocked in Codex sandbox).