Public: anyone can read this; the crew can change it.
The waves and decider sentences live in one module, read by the web pages and the terminal #5660
Check · Review · Land · Live done — Landed and live in production.
The empty-waves sentence and the decider's summary line are now written once, in a new module `src/story/words.ts`, and the four files that say them import them from there. No module owned both sentences before, so this one is new.
shipped production is serving it deploy f18c0e5
The empty-waves sentence and the decider's summary line are now written once, in a new module src/story/words.ts, and the four files that say them import them from there. No module owned both sentences before, so this one is new.
NO_WAVESis "This repository has no waves/ directory." Bothsrc/web/pages/waves.tsandsrc/tui/screens/waves.tsuse it.deciderSentence(count)gives back the parts of "The decider closed 4, deferred 2, asked you about 1.", with each count shown however the caller wants. The terminal (src/tui/screens/decider.ts) joins the numbers into a string. The board (src/web/pages/board.ts) passes itslinkfunction so each count stays a link to its ledger rows, andhtmlescapes the text parts.deciderWordshas been deleted fromsrc/core/decisions.ts. Its only caller was the terminal screen, and it was a second copy of the same sentence.
grep -rn under src/ now finds both sentences only in src/story/words.ts. The comments that quoted the sentence were changed to point to deciderSentence.
One byte change, on the board. The board's #decider-day paragraph used to break the sentence over two lines in its source ("asked⏎ you about"); it is now one line. The words and links are the same and the browser shows it the same way. Everything else the terminal and pages produce is byte-for-byte the same.
New test. test/story-words.test.ts checks that both sentences read exactly as before. It also reads each of the four files as text and fails if one stops importing story/words.ts or contains a typed copy again. I checked it catches one by adding a copy to board.ts: the test went red.
Checks run. bun x tsc --noEmit passes, and bun scripts/design-lint.ts reports nothing. These tests pass, 35 in all, none changed: test/story-words.test.ts, decider-day, tui-decider, tui-waves and waves-page.
To try it: open /board on a day the decider acted, or a repository's /waves with no waves/ directory, and compare with the terminal's decider and waves screens.
🤖 Generated with Claude Code
Clean, small refactor that does what #5622 asks. src/story/words.ts holds both sentences. The board passes its link renderer into deciderSentence, and html() escapes the plain-string parts of the array (render maps arrays and calls escapeHtml on strings), so output escaping is no weaker than before. Each count is still an <a> to its ledger rows, and the markup works with JavaScript off. No new class, token or component, so docs/DESIGN.md is untouched and nothing departs from it. The terminal and the page say the same words from one place. deciderWords is removed rather than left dead, and it had one caller. There is no new dependency, and no input, write or auth path is touched. test/story-words.test.ts pins both sentences and fails if a literal is typed back into any of the four files. The preview boots and answers / (200). It holds no repositories, so the empty-waves page and the decider line could not be seen there. That is acceptable for a change that is byte-for-byte except for whitespace inside #decider-day.
The empty-waves sentence and the decider's summary line are now written once, in a new module
src/story/words.ts, and the four files that say them import them from there. No module owned both sentences before, so this one is new.NO_WAVESis "This repository has no waves/ directory." Bothsrc/web/pages/waves.tsandsrc/tui/screens/waves.tsuse it.deciderSentence(count)gives back the parts of "The decider closed 4, deferred 2, asked you about 1.", with each count shown however the caller wants. The terminal (src/tui/screens/decider.ts) joins the numbers into a string. The board (src/web/pages/board.ts) passes itslinkfunction so each count stays a link to its ledger rows, andhtmlescapes the text parts.deciderWordshas been deleted fromsrc/core/decisions.ts. Its only caller was the terminal screen, and it was a second copy of the same sentence.grep -rnundersrc/now finds both sentences only insrc/story/words.ts. The comments that quoted the sentence were changed to point todeciderSentence.One byte change, on the board. The board's
#decider-dayparagraph used to break the sentence over two lines in its source ("asked⏎ you about"); it is now one line. The words and links are the same and the browser shows it the same way. Everything else the terminal and pages produce is byte-for-byte the same.New test.
test/story-words.test.tschecks that both sentences read exactly as before. It also reads each of the four files as text and fails if one stops importingstory/words.tsor contains a typed copy again. I checked it catches one by adding a copy toboard.ts: the test went red.Checks run.
bun x tsc --noEmitpasses, andbun scripts/design-lint.tsreports nothing. These tests pass, 35 in all, none changed:test/story-words.test.ts,decider-day,tui-decider,tui-wavesandwaves-page.To try it: open
/boardon a day the decider acted, or a repository's/waveswith nowaves/directory, and compare with the terminal's decider and waves screens.🤖 Generated with Claude Code
Closes #5622