feat(widgets): compact label presets for every labeled widget - #21
Conversation
Fill COMPACT_LABELS with short presets for all labels routed through formatRawOrLabeledValue: usage widgets (S:, W:, WS:/WO:/WF:), tokens (I:/O:/T:/C:/Tr:), cache widgets (Ca:/CR:/CW:/CH:), timers (B:/R:/WR:, plus the bar/slider no-colon variants), extra usage (Ov:/OvU:/OvL:), context percentage (CU:/CL: for both plain and usable variants), and ClaudeStatus (CC:). The ItemsEditor (j) keybind list is derived from a render probe against this map, so every labeled widget picks the keybind up automatically. Tests: parameterized preset coverage in renderer-compact-labels.test.ts; capability probe expectations updated in widgets.test.ts; the shared helper test now uses an unmapped label for its no-preset cases. Upstream feature request: sirmalloc#610 Co-Authored-By: Claude Code <noreply@anthropic.com>
Arrow-parens, indent, import order, prefer-find and cached-font-status nullish-assignment cleanups; no behavior change. Co-Authored-By: Claude Code <noreply@anthropic.com>
axisrow
left a comment
There was a problem hiding this comment.
Review: compact label presets for every labeled widget
Verdict: Approve. No correctness issues found.
What was verified
Preset coverage is complete and exact. Every one of the 31 new keys in COMPACT_LABELS was cross-checked against the actual label prefixes passed to formatRawOrLabeledValue across src/widgets/: tokens (In:/Out:/Total:/Cached:/Turn:), cache (Cache:/Cache Read:/Cache Write:/Cache Hit:), timers (Block/Reset/Weekly Reset in both colon and bar/slider no-colon forms), extra usage (Overage/Overage Used/Overage Left), context (Ctx Used/Ctx Left plus both (u) variants), usage percents (Session/Weekly/Weekly Sonnet/Weekly Opus/Weekly Fable), plus Model/Context/Cost/Claude. Conversely, every helper callsite label in the tree is now covered by a preset — the PR claim that every labeled widget routed through the shared helper is covered holds in both directions.
No cross-firing between near-identical labels. The lookup in formatRawOrLabeledValue is an exact map match, so Reset: vs Reset (bar/slider mode), Cache: vs Cache Read: vs Cached:, and Weekly: vs Weekly Sonnet: cannot substitute for each other. The prefix predicate startsWithCompactLabel was also checked for shadowing: none of the near-prefixes mask a different key (e.g. Weekly: does not prefix-match Weekly Sonnet: 42%).
CU:/CL: duplication is deliberate. Ctx Used: and Ctx(u) Used: both map to CU: (and CL:), documented by a source comment noting the variants are rarely shown side by side. Acceptable as an intentional trade-off; worth revisiting only if someone stacks both usable and plain percentage widgets in one line.
No keybind collisions from the widened probe. Since startsWithCompactLabel now matches more preview outputs, more widget types get the j compact-label keybind in the item editor. A scan of all editor keybinds shows no widget defines j for anything else, so newly capable widgets (tokens-, cache-, timers, usage-*) acquire the toggle without conflicts. The updated capability assertions in widgets.test.ts (tokens-input, session-usage, weekly-usage) follow directly from the map plus the preview probe.
Second commit is purely mechanical. Arrow-paren removals, import reorder, ??= in getCachedPowerlineFontStatus (semantically identical to the null check), indentation realignment in PowerlineThemeSelector.tsx, .filter(...)[0] to .find(...), and replacing two toBeDefined() asserts with a narrowing throw in renderer-regular-theme.test.ts (same failure semantics, clearer message). No behavior change.
Test quality. The new parameterized test exercises every map entry through the real helper in both compact and plain modes — including the empty-preset strip case for Cost:. The retargeted no-preset case now uses Branch: , which no helper callsite emits, so it stays a valid unmapped-label probe.
Notes (non-blocking)
- Exposing
COMPACT_LABELSas an export widens the module surface slightly beyond what the tests strictly need, but it enables the parameterized test to stay exhaustive if entries are added later. Fine as is. - Widgets that render default labels without routing through the shared helper (e.g. plain clocks, git labels) remain outside compact coverage; that is the pre-existing helper-based design, not a regression of this PR.
axisrow
left a comment
There was a problem hiding this comment.
Reviewed the full diff on the PR branch, traced every map key to its label-emission site, ran the suite, lint, and a live pipe render with three configs (global on / global off + per-widget true / global on + per-widget false). Approving; two non-blocking notes below.
Verified
- Additive schema, no migration: the diff does not touch
Settingsschemas or migrations;WidgetItem.metadatais already an openz.record(z.string(), z.string())(src/types/Widget.ts:26). No new metadata keys are introduced — the feature reuses the pre-existingcompactLabelkey and only fills the preset map. Configs withoutcompactLabels/metadata render byte-identical to main (checked with a default-config render). - Precedence both ways:
withGlobalCompactLabels(src/widgets/shared/raw-or-labeled.ts:109) injects'true'only whencompactLabelsis on and metadata is unset, so an explicit per-widget'false'blocks the global flag, and'true'applies with the global flag off. Confirmed live: global-on +tokens-input{compactLabel:'false'}rendersIn: 0while siblings render compact; global-off +session-cost{compactLabel:'true'}renders$2.46(label stripped) while siblings keep full labels. - 87603-class double-glyph bug: not reproducible by construction — the map has no prefix-producing presets;
Cost:maps to''so the value's own$is the only glyph. Live render withcost.total_cost_usd: 2.46yields$2.46, not$$2.46. Render path uses exact-key lookup only (COMPACT_LABELS[labelPrefix]), no prefix matching, so partial-label misfires are impossible. - Map-key coverage: all 31 keys match their emission sites exactly, including the easy-to-miss ones: colon-less bar/slider variants
Block/Reset/Weekly Reset(BlockTimer.ts:80, BlockResetTimer.ts:114, WeeklyResetTimer.ts:193), dynamic inverse labelsCtx Used:/Ctx Left:(ContextPercentage.ts:54) andCtx(u) Used:/Ctx(u) Left:(ContextPercentageUsable.ts:58), andLABELin ClaudeStatus.ts:22. Bonus: speed widgets share theIn:/Out:/Total:labels, so they compact for free. - Upstream sirmalloc#601 metadata keys: no interaction risk — this PR adds no metadata keys, and
compactLabeldoes not collide with existing keys (hide,zeroDisplay,ttl,speedWindow,metric, link keys). - Tests: full suite 2490 pass / 35 fail of 2525. The 35 failures are environment flakes in three untouched classes: custom-command subprocess capture (16),
fetchUsageDataprobe timeouts at 5s (11), ink TUI timing (8). None touch the diff's files; the parameterizedit.each(Object.entries(COMPACT_LABELS))test and the capability-probe expectations all pass.bun run lint(tsc + eslint --max-warnings=0) exits 0. - Hygiene: no dependency changes (package.json/bun.lock untouched by the diff), no secrets, no lint suppressions added (second commit is purely mechanical formatting).
Non-blocking notes
- PR description understates the flake picture: "one network-dependent
fetchUsageDatatest" — actually 11fetchUsageDatatests time out under full-suite load on this machine. Worth correcting in the description so future readers don't chase them as regressions. Ctx(u) Used:→CU:drops the usable marker, socontext-percentageandcontext-percentage-usablerender identically (CU: 5.0%vsCU: 5.3%) if shown side by side. The in-code comment acknowledges this ("rarely shown side by side"), so fine to keep — an alternative likeCU(u):would preserve the distinction if it ever matters.
🤖 Generated with Claude Code
Compact label presets for every labeled widget
Follow-up to the compact-labels feature: fills
COMPACT_LABELSso the global Compact Labels toggle (Global Overrides →j) shortens every label routed through the shared helper, not just Model/Context/Cost. Per-widgetjoverride in the item editor now appears for all of them automatically (the editor derives the keybind list from a render probe against this same map).Examples:
Session:→S:,Weekly:→W:,Weekly Sonnet:→WS:(alsoWO:/WF:), tokensIn:/Out:/Total:/Cached:/Turn:→I:/O:/T:/C:/Tr:, cacheCache:/Cache Read:/Cache Write:/Cache Hit:→Ca:/CR:/CW:/CH:, timersBlock:/Reset:/Weekly Reset:→B:/R:/WR:(bar/slider no-colon variants included), extra usageOv:/OvU:/OvL:, contextCtx Used:/Ctx Left:→CU:/CL:(usable variants share the presets),Claude:→CC:. Empty presets still strip (Cost:→$2.46).Upstream feature request: sirmalloc#610. Also fixes the 22 pre-existing ESLint errors left over from the merged theme/separator work (second commit, no behavior change).
Testing
formatRawOrLabeledValue(compact on/off); capability-probe expectations updated inwidgets.test.ts; helper test's no-preset cases now use an unmapped label.fetchUsageDatatest) fail on a clean tree as well; all deterministic tests pass.bun tsc --noEmitclean,eslintclean,bun run buildOK, live render verified.🤖 Generated with Claude Code