FABRIC.md item 4.4x: split the REPL prompt into its own bottom strip

Scope expanded from pure CANVAS-rectangle arithmetic (as originally
scoped) to also splitting the REPL prompt/input line out of the
scrollback box into an independent single-line strip, per Captain Bob's
explicit fold-in after the gap was reported (§25.0 rule 3) rather than
silently expanded.

vt100.c: VT100_BOX_ORIGIN_X/Y are no longer hardcoded per-arch literals --
both are now derived from fb_width()/fb_height() at vt100_enable_ttf()
time. New vt100_strip_draw() renders the bottom strip (gray border lines,
bright-white text) directly via the existing ttf_draw_glyph_cell()
rasterizer, independent of the box's own grid/cursor state. Border lines
are drawn after the glyph loop so an oversized cell can only be clipped
by them, never erase them.

console.c/console.h: console_fb_strip_draw() thin wrapper, matching the
existing console_fb_enable_ttf()/console_fb_scroll_*() pattern.

repl.c: builds a plain-text "[VMName] ok> <input>" mirror in
g_strip_prompt/strip_refresh(), refreshed on every keystroke (including
backspace) from sk_readline() -- already wired for item 4.4v, since
keyboard-typed characters will flow through the same console_getc() path
once that lands. Also widened sk_repl_step()/sk_repl_run()'s local input
buffer from a second, smaller 256-byte buffer to INPUT_BUFFER_SIZE
(1025), per 4.4w's decision.

Verified: three-arch clean QEMU boot + logs, amd64 screendump showing
the box and strip as two visually distinct regions with no visible
glyph/border clipping.

Punch list §25 item 4.4x complete.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-12 14:59:07 -04:00
co-authored by Claude Sonnet 5
parent 763c6f2cd5
commit 91742e02f4
21 changed files with 42690 additions and 23 deletions
+64 -8
View File
@@ -5951,16 +5951,72 @@ document and committing that amendment as its own item.*
> words: "as long as there's enough space above and below so it looks right." Not
> reopened as a fresh pixel negotiation; the second mockup pass's numbers stand.
- [ ] **4.4x — Redo 4.4n's CANVAS rectangle for the real (single-line) REPL-strip height.**
- [x] **4.4x — Redo 4.4n's CANVAS rectangle for the real (single-line) REPL-strip height, AND
split the REPL prompt/input line out of the scrollback box into its own bottom strip.**
4.4n's existing CANVAS math assumed 4.4m's 96px/4-line REPL strip; 4.4u replaced that with a
single-line strip (4.4w's gap values, once pinned, give the real height — order-of-magnitude
20-40px, not 96px). Pure arithmetic against already-decided numbers, not a new design
question, but CANVAS's top-left/width/height must be recomputed before any drawing code
reads them. Depends on 4.4w (gap values pinned first).
*Done when:* a new CANVAS rectangle (top-left, width, height) is computed and recorded per
architecture, explicitly superseding 4.4n's numbers the way 4.4n itself is referenced from
4.4u as historical record, not edited in place.
*Refs:* §27.8, 4.4n, 4.4u, 4.4w.
20-40px, not 96px). Depends on 4.4w (gap values pinned first).
**Scope expanded 2026-08-12, folded in by Captain Bob directly.** Originally scoped as pure
arithmetic (recompute the box rectangle, no code). Found while starting this item: today the
REPL prompt (`ok>`, cursor, typed input) prints through the exact same `console_puts()`
vt100-grid path as everything else, confined to the box by 4.4t — there is no separate
bottom strip in the code at all, so 4.4u's design (box above, independent single-line strip
below, separated by the 8px gap) does not exist yet even though the geometry math assumes it
does. Reported per §25.0 rule 3 rather than silently expanded; Bob's answer was to fold the
split into this item rather than open a new one, since the split is what makes the recomputed
geometry meaningful in the first place.
*Done when:* `VT100_BOX_ORIGIN_Y` (and confirmation that `_ORIGIN_X`/`_W`/`_H` are unchanged)
is recomputed and recorded per architecture below; the REPL prompt/cursor/input line renders
in its own single-line strip pinned to the bottom of the screen (row 0 = `fb_height()-1`,
gray border lines per 4.4u/4.4w, bright-white text) independent of the scrollback box's own
grid; scrollback output continues to render only inside the box. Three-arch QEMU boot + logs
per CLAUDE.md; amd64 screendump showing both regions distinctly.
*Refs:* §27.8, 4.4n, 4.4u, 4.4w, 4.4t.
> **DONE 2026-08-12.** `VT100_BOX_ORIGIN_X`/`_ORIGIN_Y` are no longer hardcoded per-arch
> literals — both are now derived at `vt100_enable_ttf()` time from `fb_width()`/
> `fb_height()` (`vt100.c`):
> ```
> origin_x = (fb_width() - VT100_BOX_W) / 2
> origin_y = fb_height() - VT100_BOX_H - VT100_STRIP_BOX_GAP_PX(8) - (2*VT100_STRIP_GAP_PX(15) + 1)
> ```
> Confirmed the old per-arch `_ORIGIN_X`/`_W`/`_H` values fall out of the same formula
> unchanged (only Y moves, since only the strip height changed): amd64 origin=(320,281)
> [was (320,104)], aarch64/riscv64 origin=(80,81) [was (80,4)], both against the same
> 800×600/1280×800 resolutions 4.4l already confirmed.
>
> **The strip split is real, not just geometry.** New `vt100_strip_draw()` (`vt100.c`) draws
> the bottom strip directly via the existing `ttf_draw_glyph_cell()` rasterizer (no second
> text-drawing path), independent of the box's own grid/cursor. `console_fb_strip_draw()`
> (`console.c`/`console.h`) is the thin wrapper, matching the existing
> `console_fb_enable_ttf()`/`console_fb_scroll_*()` pattern. `repl.c` builds a plain-text
> (no ANSI) `"[VMName] ok> <input>"` mirror in `g_strip_prompt`/`strip_refresh()`, refreshed
> on every keystroke from `sk_readline()` (including backspace) — this also means it's
> already wired for 4.4v: once the keyboard bridge lands, typed characters flow through the
> same `console_getc()``sk_readline()` path and the strip updates for free, no further
> changes needed here.
>
> **Also fixed, found while wiring this:** `sk_repl_step()`/`sk_repl_run()`'s local
> `char input[256]` was a second, smaller buffer than `INPUT_BUFFER_SIZE`=1025 — the actual
> gap 4.4w's decision (full 1025-char buffer, not a smaller practical limit) needed closed.
> Widened both to `INPUT_BUFFER_SIZE`.
>
> **Border-line ordering deliberate:** `vt100_strip_draw()` draws the two gray border lines
> *after* the glyph loop, not before — a glyph cell's own opaque background fill (24px tall)
> can extend a few pixels past the 15px baseline-to-line gap for full-ascender characters,
> and drawing borders last means an oversized cell can only be visually clipped by them, never
> erase them. Screendump-verified below: no visible clipping at this font size in practice.
>
> Three-arch QEMU boot + logs: clean (`logs/20260812-144724/amd64`,
> `logs/20260812-144811/aarch64`, `logs/20260812-144922/riscv64`). amd64 screendump
> (`logs/screendump-4.4x/amd64-strip.png`) confirms both regions distinctly: scrollback box
> with boot/POST history near the top, bottom strip with gray borders and
> `[Hera] ok>` in white, clearly separated. aarch64/riscv64 screendump attempted but the
> manual ISO build used for it didn't reproduce the Makefile's exact boot chain (unrelated to
> this item's code) — not blocking, since the formula is resolution-derived and already
> verified correct by direct calculation against both known resolutions, and the real
> acceptance boot (via `make qemu`, not a manual screendump) passed clean on all three.
- [x] **4.4y — Decide the toggle meta-key.** Design-only, no code. 4.4u step 8 left this open —
candidates floated were TAB and Ctrl+TAB, Bob explicitly deferred choosing ("we'll figure out