Public: anyone can read this; the crew can change it.
A test pins how a run reads in the terminal: each run state's tone, the environment in words and dollars to the cent #7603
Check · Review · Land · Live done — Landed and live in production.
I added `test/tui-runwords.test.ts`, which pins how a run reads in the terminal. It checks the tone of every run state, how the environment is worded and how dollars are formatted, and that the runs list and the run log describe one run in the same words. It does not change what any screen shows.
shipped production is serving it deploy 4915f35
I added test/tui-runwords.test.ts, which pins how a run reads in the terminal. It checks the tone of every run state, how the environment is worded and how dollars are formatted, and that the runs list and the run log describe one run in the same words. It does not change what any screen shows.
- Tones: the test loops over the run states and compares each with an expected table. A state added without a tone fails both the type check and the test.
queuedhas no tone on purpose, and a separate check fails if any other state ends up without one. - The one source change:
src/core/runs.tsnow has aRUN_STATESlist, and theRunStatetype is built from it. This was needed so the test could loop over the real states rather than a copy of them. - Environment:
pull-4reads as "pull #4",productionas itself, and an empty one as "—". - Dollars: zero shows nothing, sub-cent rounds (0.004 → $0.00, 0.005 → $0.01), cents read to the cent ($0.07, $3.46), and thousands have no separator ($1234.50). The test keeps the current behaviour, which matches how web studio cards round costs. A sub-cent run showing "$0.00" is arguably misleading, but changing that was outside this issue.
- Both screens: a failed deploy for pull #4 that cost $1234.50 is drawn in the runs screen and in the run log. Both must show "failed", "deploy pull #4", "$1234.50" and the run's summary.
The test file passed (15 tests) and the type check ran with no errors. It takes 1.0–1.2 s, so it sometimes misses the issue's 1 s target. About 0.5 s of that is loading the terminal UI's code, which the both-screens check can't avoid.
To try it: bun test test/tui-runwords.test.ts.
🤖 Generated with Claude Code
Approved. Test-only plus a type-preserving RUN_STATES list; no new surface, no dependency, no security-relevant change, and the terminal screens are unchanged. The tone table is a Record over RunState, so a new state fails tsc and the loop. The runs list and run log are checked for the same words on one run. Two things I would do next: (1) the RUN_STATES uniqueness test is near-tautological, so drop it or fold it into the loop; (2) the both-screens test boots a full forge and the TUI at about 1 s, so move the cross-screen check to a smaller fixture or share the app with another TUI test to stay under the per-test time budget (#1242). Also decide separately whether a sub-cent run should read $0.00 (the test pins the current behaviour).
I added
test/tui-runwords.test.ts, which pins how a run reads in the terminal. It checks the tone of every run state, how the environment is worded and how dollars are formatted, and that the runs list and the run log describe one run in the same words. It does not change what any screen shows.queuedhas no tone on purpose, and a separate check fails if any other state ends up without one.src/core/runs.tsnow has aRUN_STATESlist, and theRunStatetype is built from it. This was needed so the test could loop over the real states rather than a copy of them.pull-4reads as "pull #4",productionas itself, and an empty one as "—".The test file passed (15 tests) and the type check ran with no errors. It takes 1.0–1.2 s, so it sometimes misses the issue's 1 s target. About 0.5 s of that is loading the terminal UI's code, which the both-screens check can't avoid.
To try it:
bun test test/tui-runwords.test.ts.🤖 Generated with Claude Code
Closes #7594