cyberine
UsageRun recipes

The border vocabulary is corner-less, by decision (kwk4f)

The TUI's chrome draws a top edge and a bottom edge and nothing else. There is exactly ONE border archetype, chromeBorder() in src/tui/theme.ts, no boxed variant, no left or right edge, and no corner glyph anywhere in the product.

That used to be a side effect rather than a choice, which is what this task fixed. theme.ts declared TWO archetypes in one commit; the second, modeBarBorder, claimed in its own doc that the transcript mode/search footers used it, and nothing ever called it — the mode line (components/chat/ChatModeLine.tsx) renders borderless with paddingX. The survivor asks Ink for borderStyle: 'round' while disabling left and right, so its four corner glyphs (U+256D-2570) had never once reached a terminal. modeBarBorder is deleted, and the surviving archetype is now stated as the decision it is, with the reasoning written where the archetype lives.

Why corner-less rather than adding a boxed archetype:

  1. It is what the product already is — 16 call sites, zero boxed, and no component hand-rolls a borderStyle of its own. A box now means either two grammars on one screen or migrating all 16.
  2. A box costs 2 columns of measure per nesting level, and this layout is already rationing measure (MAX_MEASURE clamps prose to 80, MAX_TABLE_W clamps tables to 140). At the 80-column floor selftest:80col defends, that is 2.5% of the row spent on two vertical lines before any nesting.
  3. Side edges must be redrawn on every row, and the rows are not the box's to draw. RowBand (kf6br) is one full-width <Text> carrying the selection background, clipped by its Box — the band reaching the pane edge is the point of it. A vertical border either sits outside the band (a gap in the tint on every selected row) or forces every list row through the box. Same for Transcript rows and WorkerPeek's tail.
  4. Grouping is already done by two mechanisms tuned against these edges — the shared left column (CHROME_PAD_X) and the horizontal rule (Divider). k6shr had just finished matching rule weight to this archetype's edge weight and removing a doubled seam; a boxed archetype reopens both.
  5. Claude Code, the surface this theme mirrors 1:1, is corner-less for panes, and the 2026-06-24 project decision already went further, dropping CC's per-role split so all chrome shares one left column.

One consequence is worth knowing before you touch the archetype: with the side edges off, Ink renders 'round' and 'single' byte-identically — both emit a U+2500 run and no corners. That is measured by the smoke, not assumed. The style name in chromeBorder is therefore inert; do not read a corner style into it, and do not "fix" it to 'single', which changes nothing on screen. What is load-bearing is that borderLeft and borderRight stay false.

Run recipe:

npm run selftest:border-vocabulary   # offline; source scan + renders chrome through Ink

The guard holds four things: exactly one border archetype is exported from theme.ts and it has callers (an archetype nothing calls is deleted, not documented); no file under src/ declares a borderStyle outside the archetype; a rendered chromeBorder() box, AppHeader, TitledBox and HelpOverlay contain no corner glyph from ANY Ink box style (single, double, round, bold, singleDouble, doubleSingle, arrow) while still drawing their light horizontal edge; and the 'round'-equals-'single' claim above is re-measured every run, with a full four-sided box rendered alongside as the control that proves the corner check can actually see a corner.

Extend recipe. Reversing the decision is a deliberate act with a fixed order: rewrite the decision block in src/tui/theme.ts first (it is the record — the smoke only enforces what it says), then update scripts/kwk4f-border-vocabulary-smoke.tsx. Adding a second archetype fails the "exactly one" check by design, and a new archetype with no caller fails a second check on top of it.

Known Limitations and Deferred Work. The render half checks four representative chrome surfaces, not every screen — the source scan is what covers the rest, and it can only see a literal borderStyle token, so a border assembled at runtime from a computed prop object would slip past it (nothing does this today). The decision is about the TUI only: the web dashboard's CSS has its own borders and is not in scope. And "corner-less" is a statement about chromeBorder, not a ban on box-drawing glyphs generally — SYM.vbar remains available as a column separator inside a row, which is content, not chrome.