Turns the read-only Phase-1 view into an interactive shell, split into focused
view components (spec v4 §2 layout):
- view/transcript.tsx: ONE full-height <scrollbox> with a reactive <For>
(opencode's no-scrollback model). Applies the §8 #2 gotchas exactly:
minHeight:0 on the wrapper AND the scrollbox, NO flexDirection on the
scrollbox root, stickyScroll + stickyStart="bottom".
- view/composer.tsx: a native <textarea> captured by ref — flexShrink:0,
focus-on-mount, Enter->submit via keyBindings, imperative .clear() on submit,
and a `submitting` re-entrancy guard. Wired by the entry to fire prompt.submit
(Effect.runFork on the in-hand service value); it's now the PRIMARY input, with
the HERMES_TUI_PROMPT stand-in kept only for launch-with-prompt.
- view/header.tsx + view/messageLine.tsx: extracted, themed (no hardcoded
styles). MessageLine stays flat-text this slice; ordered parts (§7) land in 2b.
test/lib/render.ts now flushes 3 renderOnce passes before capture — a <scrollbox>
needs more than one pass to measure content + apply sticky, else the transcript
row paints blank.
Verified: bun run check green (12 tests / 4 files / 31 expects). Live tmux drive:
typed into the composer -> cleared -> user row -> streamed reply ("Here are three
words"); Ctrl+C quits cleanly even with the textarea focused, no orphan child.
Composer placeholder rendered the live skin's welcome string (skin->theme live).
Smoke P2a + parity matrix updated. Phase 2b (ordered parts/tool render/markdown)
is the next slice.