fix(statusline): budget lines by the host's real reserve, not an inherited 85% - #13
Merged
Conversation
…stop it flaking test_perf_heat_rgb_20run_avg failed roughly 4 runs in 10 on an idle machine. Two defects, one cause each. It asserted nothing. The "baseline" was a single timing of heat_rgb and the comparand was the mean of twenty more timings of the same call, so both sides contained identical work and the delta was noise around zero. With n=1 on the baseline, one slow first sample failed the assertion outright. The instrument dwarfed the phenomenon. Timing an EMPTY pair of `date +%s%N` calls on this host returned 4.2, 21.4, 21.7, 21.8 and 23.5 ms across five consecutive attempts — a ~19 ms spread against a 5 ms budget. Per-sample timestamps cannot support that assertion at any sample count the suite can afford. Now: one timestamp pair around a block of 2000 calls, and the same around an equally-sized no-op control carrying the same redirection. The fork is amortized (~0.01 ms per call) and the control subtracts everything that is not heat_rgb. Measured on this host: heat_rgb 173 us/call, control 41 us/call — a 0.13 ms delta against the unchanged 5 ms budget (AC-015/NFR-002). Verified: 15 consecutive runs, 0 failures (was 4/15 failing before, and 4/10 with an interim per-sample fix that corrected only the control). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013SQwMscnDJfTN7sz3Jwzg4
…rited 85%
FIT_RATIO=85 held every line to 85% of the terminal. The figure came from the
pictet-tech claude-statusline plugin, which is no longer installed, and its
claim — a line near the full width is truncated AND costs the block its second
row — was never reproduced here. The previous commit could only document that;
this one replaces it with the host's actual behaviour, read from Claude Code
2.1.220 itself.
The reserve is additive, and it is now taken from the renderer:
<Box width={columns} paddingLeft={2} paddingRight={compact?1:2}> -> 4 cols
<Box paddingX={statusLine.padding ?? 0}> -> 2*padding
The wider of the paddingRight branches is used: one column pessimistic trims a
segment early, one column optimistic is cut by the host. statusLine.padding is
read from settings.json (read_statusline_padding), type-strict in jq because a
JSON string "2" is not a number to the host.
The same read falsifies the inherited claim: every line is rendered
<Text wrap="truncate"> individually, so an over-wide line is truncated on its
own and costs no other row. Line count is independent of line width.
Preset selection moves onto the budget rather than the raw width, which removes
a contradiction between two constants: l was selected from 90 columns up but
could not render untrimmed below 104, so between those widths it was selected
and then trimmed on every refresh. SIZE_L_MIN_COLS=90 becomes
SIZE_L_MIN_BUDGET=89 — exactly l's widest measured line, so "budget >= widest"
is the fit condition and the two cannot disagree. Verified: at 95 columns with
padding 1, budget 89 and widest emitted line 89.
probe_cols consults $COLUMNS before the controlling tty. The host sets COLUMNS
to the width it renders into (`let{columns:N}=process.stdout;if(N)L.COLUMNS=
String(N)`), which is the authority; the tty probe stays below it for hand-run
invocations. Capturing a live payload on 2026-07-26 showed the hook environment
has no controlling terminal at all, so that rung answers nothing under the
host, and that the statusLine JSON carries no width field of any kind.
Net effect on a 200-column terminal: a line may use 196 columns instead of 170.
Verified: shellcheck 0.11.0 clean on renderer, modules and suites; 53 + 22 shell
tests and 18 python tests pass; no rendered line exceeds its budget at 40, 60,
80, 95, 120, 200 or 241 columns.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013SQwMscnDJfTN7sz3Jwzg4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
FIT_RATIO=85held every status line to 85% of the terminal. The number came from the pictet-techclaude-statuslineplugin — uninstalled earlier today, so the citation pointed at a file that no longer exists — and its claim (a line near the full width is truncated and costs the block its second row) had never been reproduced in this repo.This replaces the guess with the host's actual behaviour, read from Claude Code 2.1.220's own renderer.
The reserve, derived
<Box width={columns} paddingLeft={2} paddingRight={compact?1:2}><Box paddingX={statusLine.padding ?? 0}><Text wrap="truncate">per line (TRS)The wider
paddingRightbranch is used: one column pessimistic trims a segment early, one column optimistic is cut by the host.That third row falsifies the inherited claim outright — an over-wide line costs no other row.
Two contradictions this removes
lwas selected from 90 columns up but could not render untrimmed below 104, so between those widths it was selected and then trimmed on every refresh. Selection now runs on the budget, andSIZE_L_MIN_BUDGET=89is exactlyl's widest measured line. At 95 columns with padding 1: budget 89, widest emitted line 89.$COLUMNSnow precedes the controlling tty. The host sets it to the width it renders into; capturing a live payload showed the hook environment has no controlling terminal, so the tty rung answers nothing there, and the statusLine JSON carries no width field at all.Net effect on a 200-column terminal: a line may use 196 columns instead of 170.
Also fixed (§14)
test_perf_heat_rgb_20run_avgwas flaky (~4 runs in 10) and asserted nothing — it compared one sample ofheat_rgbagainst the mean of twenty more of the same call. Separate commit.Completion Ledger
fit_budget: zero/negative/non-numeric width and padding, width below chrome, omitted padding —test_fit_budget_validates_both_inputs,test_fit_budget_floor_is_positiveread_statusline_paddingfallback arm asserted: absent file, absent key, malformed JSON, string/float/negative/null/bool/array —test_read_statusline_padding_defaults_to_zero,..._rejects_non_integersfit_budgetinputs validated (probe fallback, user-edited JSON)fit_budgetpostcondition "positive integer, always"; floor asserted usable byfit_linejqreads per refresh, same as existing config readersSIZE_L_MIN_COLS→SIZE_L_MIN_BUDGET; no persisted formatmeasure_widths.sh(cap formula),statusline-command.sh, both READMEs updatedNot asserted, stated plainly: the tty rung's success path has no test. Stubbing
sttycannot reach it — the< /dev/ttyredirection fails first in a test process — and only a pty harness could. Its failure path is pinned. This is unchanged by this PR.🤖 Generated with Claude Code
https://claude.ai/code/session_013SQwMscnDJfTN7sz3Jwzg4