FABRIC.md: insert 4.4c (wire console_fb_init into boot), renumber 4.4c-4.4o to 4.4d-4.4p

Found while screendump-verifying the prefix fix (now 4.4d): kernel_main.c
deliberately never calls console_fb_init(), so vt100_init() never runs and
vt100_putc() no-ops on every call -- no console output has ever reached the
framebuffer, only fb_init()'s own corner self-test blocks. ROADMAP.md's
obsolete M8 section claimed this path was already live; that was never
actually screendump-verified.

Records Captain Bob's stated end goal (2026-08-11): framebuffer console and
serial console must be functional identically. 4.4c wires that in.

Only uncommitted items were renumbered; 4.4/4.4a/4.4b keep their IDs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-11 07:56:07 -04:00
co-authored by Claude Sonnet 5
parent d187c87671
commit bf89b8239f
+82 -39
View File
@@ -4981,7 +4981,7 @@ document and committing that amendment as its own item.*
*added above this marker.)*
- [x] **4.4 — Design-only: lock the prompt format and color values.** No code. Write down the
exact target string — `[VM name] ok>` for now, `(user)` added later per 4.4o — and the exact
exact target string — `[VM name] ok>` for now, `(user)` added later per 4.4p — and the exact
color values for the bracketed VM name and for `ok>` against
[`repl-mockup.png`](repl-mockup.png). Captain Bob's spoken values (orange, cyan) were both
qualified as tentative/uncertain — this item is where they become specific RGB or ANSI SGR
@@ -5001,14 +5001,14 @@ document and committing that amendment as its own item.*
> classic 16-color ANSI palette (checked — `FB_ANSI_PALETTE` has none), so this is a fresh
> literal value, not a reused constant. `TTF-TEXT`'s `color` argument is a raw RGB value
> (not an ANSI palette index), so this is not a constraint — any RGB is valid.
> These are literal `FB_RGB()`-equivalent values for 4.4a/4.4d to consume directly; no
> These are literal `FB_RGB()`-equivalent values for 4.4a/4.4e to consume directly; no
> implementation performed by this item, per its own "no code" scope.
- [x] **4.4a — Build `[VM name]` bracket text in the prompt, monochrome.** Replace the two
existing, mutually inconsistent VM-identity conventions — `console.c`'s per-line `[Name]`
prefix (`console_set_vm_name()`/`g_active_vm_name`, unaffected/out of scope for non-prompt
lines) and `repl.c`'s prompt-suffix `<Name>)ok>` (`sk_repl_run()`/`sk_repl_step()`) — with
`[VM name] ok>`, no color yet (4.4d). VM attach itself needs no new work: `USE`
`[VM name] ok>`, no color yet (4.4e). VM attach itself needs no new work: `USE`
(`mama_forth_words.c:1108`) already sets both `g_repl_active_vm` and `console_set_vm_name()`
— this item is a *display* change only.
*Done when:* all three architectures boot to a bracketed `[Hera] ok>` prompt (replacing
@@ -5031,9 +5031,9 @@ document and committing that amendment as its own item.*
> untouched — this is a display-only change, the ACL bypass semantics are identical to
> before.
>
> **Known, intentional gap until 4.4o:** the old prompt distinguished `zuse)ok>` from bare
> **Known, intentional gap until 4.4p:** the old prompt distinguished `zuse)ok>` from bare
> `ok>` textually. That distinction is not yet visible in the new unified prompt — it moves
> to the `(user)` segment, which is explicitly scoped-but-blocked at 4.4o. The underlying
> to the `(user)` segment, which is explicitly scoped-but-blocked at 4.4p. The underlying
> `zuse_session`/`emergency_console` mechanics are unchanged; only the on-screen indicator is
> temporarily gone.
>
@@ -5043,35 +5043,62 @@ document and committing that amendment as its own item.*
>
> **Caveat found afterward, not fixed here:** that verification is serial-log-only —
> `[VMName]` never actually reaches the framebuffer (`console.c`'s `emit_prefix()` is
> serial-only by construction). Given its own item, 4.4c, rather than silently rolled into
> serial-only by construction). Given its own item, 4.4d, rather than silently rolled into
> this one.
- [x] **4.4b — Resolve: does prompt color depend on 4.4f?** Investigation, not implementation.
- [x] **4.4b — Resolve: does prompt color depend on 4.4g?** Investigation, not implementation.
Read the REPL's actual output path (`console_puts()` → ... → `vt100_putc()`
`draw_cursor_glyph()`, all currently `font_8x16.c`) to determine whether a single
hardcoded-color prompt segment can call `TTF-TEXT` directly, independent of the general
ANSI/SGR retarget (4.4f), or whether all REPL output — prompt included — shares one
rendering pipeline that requires 4.4f to land first before *any* TTF output reaches the
ANSI/SGR retarget (4.4g), or whether all REPL output — prompt included — shares one
rendering pipeline that requires 4.4g to land first before *any* TTF output reaches the
screen.
*Done when:* the dependency question is answered in writing here, based on reading the
actual call chain, not assumed.
*Refs:* §27.8.
> **DONE 2026-08-11 — answer: no dependency on 4.4f.** `draw_cursor_glyph()`
> **DONE 2026-08-11 — answer: no dependency on 4.4g.** `draw_cursor_glyph()`
> (`vt100.c:125`) already calls `fb_draw_glyph(px, py, ch, f, b)` with `f`/`b` taken from
> `g_vt.fg`/`g_vt.bg` — color support is already wired all the way through the *existing*
> `font_8x16.c` pipeline, completely independent of which font renders the glyph shape.
> `apply_sgr()` (`vt100.c:337-348`) already parses true 24-bit-color SGR:
> `ESC[38;2;R;G;Bm` sets foreground RGB directly (not limited to the 16/256-color palette),
> `ESC[39m` resets to default. So 4.4d does not need to wait on 4.4f/4.4e at all — it can
> `ESC[39m` resets to default. So 4.4e does not need to wait on 4.4g/4.4f at all — it can
> send `ESC[38;2;255;165;0m` (4.4's locked orange) before the bracket, `ESC[39m` after, and
> `ESC[38;2;85;255;255m` (4.4's locked cyan) before `ok> `, all through `console_puts()`
> exactly as it works today. TTF (4.4e/4.4f) changes *what draws the glyph*, not *whether
> exactly as it works today. TTF (4.4f/4.4g) changes *what draws the glyph*, not *whether
> color reaches the screen* — those are orthogonal, confirmed by reading the call chain
> rather than assumed.
- [ ] **4.4c — Fix: `[VMName]` prefix never reaches the framebuffer.** Found while scoping
4.4d, given its own item per §25.0 rule 3 rather than folded in silently. `console.c`'s
- [ ] **4.4c — Wire `console_fb_init()` into the boot path.** Found while verifying 4.4d
(below) by screendump — not a bug in 4.4a/4.4b, a pre-existing, deliberate gap.
`kernel_main.c:830-834` has an explicit comment: *"console.c / vt100.c are superseded by
the Console drawing-fabric redesign (FABRIC.md §27) and are deliberately not invoked
here... `fb_init()` wires the raw GOP framebuffer directly... nothing else touches it."*
Only raw `fb_init()` runs; `console_fb_init()` (which calls `vt100_init()`) is never
called anywhere in the boot sequence. Consequence, confirmed by screendump: `vt100_putc()`
no-ops on every call (`if (!g_vt.initialized) return;`), so **no console output has ever
reached the framebuffer** — not REPL text, not POST/boot logs, nothing except the
framebuffer driver's own corner self-test blocks (`fb_draw_orientation_test()`) and
whatever TTF probes have drawn directly. ROADMAP.md's now-obsolete M8 section claimed this
path was "already live" — that was never actually screendump-verified and turned out to be
wrong.
**End goal, stated by Captain Bob 2026-08-11:** the framebuffer console and the serial
console must be functional **identically** — every character reaching one reaches the
other. `console_putc()` already implements exactly that split for ordinary characters
(`raw_putc()` for serial, `vt100_putc()` for framebuffer, unconditionally paired); the only
thing missing is turning the framebuffer half on at all.
**Fix:** call `console_fb_init(&boot_info->framebuffer, fb_fmt)` in `kernel_main.c`,
replacing or immediately following the existing raw `fb_init()` call, so `vt100_init()`
actually runs.
*Done when:* three-arch screendump shows live boot/POST/REPL text actually rendered on the
framebuffer (not just the corner test blocks) — matching what the serial log already shows;
three-arch QEMU boot + logs per CLAUDE.md.
*Refs:* §27.8.
- [ ] **4.4d — Fix: `[VMName]` prefix never reaches the framebuffer.** Depends on 4.4c (the
framebuffer console must be live before this matters). Found while scoping 4.4e, given its
own item per §25.0 rule 3 rather than folded in silently. `console.c`'s
`emit_prefix()` (called from `console_putc()` at line-start when `g_active_vm_name` is set)
writes its `[VMName] ` characters directly via `raw_putc()` — serial only, per its own
comment ("no recursion into `console_putc`"). It never calls `vt100_putc()`, so the
@@ -5086,14 +5113,14 @@ document and committing that amendment as its own item.*
logs per CLAUDE.md.
*Refs:* §27.8.
- [ ] **4.4d — Apply color to the prompt.** Depends on 4.4c (coloring a bracket that isn't
- [ ] **4.4e — Apply color to the prompt.** Depends on 4.4d (coloring a bracket that isn't
drawn on screen accomplishes nothing). Per 4.4b's finding: either an independent
`TTF-TEXT` call with the color from 4.4, or gated on 4.4f completing first.
`TTF-TEXT` call with the color from 4.4, or gated on 4.4g completing first.
*Done when:* three-arch screendump shows `[VM name]` and `ok>` in the colors locked at 4.4;
three-arch QEMU boot + logs per CLAUDE.md.
*Refs:* §27.8.
- [ ] **4.4e — Verify the VT100 CSI/SGR parser's glyph-draw call site is cleanly separable.**
- [ ] **4.4f — Verify the VT100 CSI/SGR parser's glyph-draw call site is cleanly separable.**
Verification only, no code change. `vt100.c`'s CSI/SGR state machine (escape parsing, cursor
tracking, 16/256-color SGR) calls `draw_cursor_glyph()` from a single site in `put_char()`
confirm nothing else in the parser depends on `font_8x16.c`-specific assumptions.
@@ -5107,8 +5134,8 @@ document and committing that amendment as its own item.*
compatibility question is answered from the actual font data, in writing here.
*Refs:* §27.8.
- [ ] **4.4f — Retarget the glyph-draw call site from `font_8x16.c` to `TTF-TEXT`.** Depends
on 4.4e. **Boundary, corrected 2026-08-11:** `font_8x16.c`/VT100 keeps rendering everything
- [ ] **4.4g — Retarget the glyph-draw call site from `font_8x16.c` to `TTF-TEXT`.** Depends
on 4.4f. **Boundary, corrected 2026-08-11:** `font_8x16.c`/VT100 keeps rendering everything
through and including **POST** (the parity/dictionary-hash self-test) — not just the
pre-bootstrap M1M6 messages originally scoped here. POST runs *after* the capsule/VM system
is up (it hashes the loaded Mama capsule dictionary, per CLAUDE.md), so "before the capsule
@@ -5129,7 +5156,7 @@ document and committing that amendment as its own item.*
> preference"). The actual early-boot/POST fallback is `font_8x16.c` specifically, not "the
> stroke font" generically.
- [ ] **4.4g — Live-verify ANSI color end-to-end.** Depends on 4.4f. Inject an SGR color
- [ ] **4.4h — Live-verify ANSI color end-to-end.** Depends on 4.4g. Inject an SGR color
escape sequence (`ESC[3xm`/`ESC[9xm`/256-color) over serial and confirm it visibly changes
`TTF-TEXT`-rendered glyph color in a screendump — the parser and the retargeted draw call
working together, not just each existing independently.
@@ -5137,49 +5164,49 @@ document and committing that amendment as its own item.*
three architectures; three-arch QEMU boot + logs per CLAUDE.md.
*Refs:* §27.8.
- [ ] **4.4h — Confirm actual booted framebuffer resolution, all three architectures.**
- [ ] **4.4i — Confirm actual booted framebuffer resolution, all three architectures.**
Investigation only. amd64 already confirmed this session: 1280×800 (QEMU/OVMF GOP default,
read directly off the 2026-08-11 verification screendump). aarch64/riscv64 unconfirmed.
*Done when:* resolutions for all three architectures are recorded here from real
screendumps or boot logs, not assumed.
*Refs:* §27.8.
- [ ] **4.4i — Decide REPL-strip pixel height.** Currently undefined anywhere in this document
or the code. Once 4.4f lands, REPL text renders via `TTF-TEXT` at some chosen point/pixel
- [ ] **4.4j — Decide REPL-strip pixel height.** Currently undefined anywhere in this document
or the code. Once 4.4g lands, REPL text renders via `TTF-TEXT` at some chosen point/pixel
size (also not yet chosen) — strip height derives from that size's line height plus padding,
not from `font_8x16.c`'s fixed 8×16 cell.
*Done when:* a REPL text size (px) and a resulting strip height (px) are both decided and
recorded here.
*Refs:* §27.8.
- [ ] **4.4j — CANVAS rectangle definition, per architecture.** Screen height (4.4h) minus REPL
strip height (4.4i) minus the small fixed gap (exact pixel value chosen here) between CANVAS
- [ ] **4.4k — CANVAS rectangle definition, per architecture.** Screen height (4.4i) minus REPL
strip height (4.4j) minus the small fixed gap (exact pixel value chosen here) between CANVAS
and the strip.
*Done when:* a CANVAS rectangle (top-left, width, height) is computed and recorded for each
architecture.
*Refs:* §27.8.
- [ ] **4.4k — 640×480 scroll-box centering math within CANVAS.** Layout math computed on top
- [ ] **4.4l — 640×480 scroll-box centering math within CANVAS.** Layout math computed on top
of `TTF-TEXT`'s own coordinate primitive, which is simpler and already fixed: Cartesian,
origin at the bottom-left of the **physical framebuffer** (not CANVAS-relative — resolved
and implemented ahead of this item, 2026-08-11, `ttf_words.c`'s `baseline_y = fb_height() -
y`, verified by amd64 screendump). This item translates 4.4j's CANVAS-relative rectangle
y`, verified by amd64 screendump). This item translates 4.4k's CANVAS-relative rectangle
into that same physical-framebuffer space.
**Open, blocking question, not assumed:** if any architecture's CANVAS height (4.4j) is
**Open, blocking question, not assumed:** if any architecture's CANVAS height (4.4k) is
smaller than 480, this item cannot center the box as specified and must stop and report per
§25.0 rule 5, not silently shrink it.
*Done when:* box top-left coordinates are computed for each architecture, or the item stops
and reports which architecture's CANVAS is too small.
*Refs:* §27.8.
- [ ] **4.4l — Three-arch screendump verification of 4.4h4.4k.** Geometry only — not the
- [ ] **4.4m — Three-arch screendump verification of 4.4i4.4l.** Geometry only — not the
toggle or scrollback.
*Done when:* screendump on all three architectures shows the 640×480 box centered within
CANVAS at the computed coordinates, with the fixed gap above the REPL strip visible;
three-arch QEMU boot + logs per CLAUDE.md.
*Refs:* §27.8.
- [ ] **4.4m — Scrollback, ~1000 lines.** A circular buffer of prior scroll-box lines, target
- [ ] **4.4n — Scrollback, ~1000 lines.** A circular buffer of prior scroll-box lines, target
depth approximately 1000 (Captain Bob's own qualification: "something along those lines,"
not a hard-locked spec number). Storage mechanism (`kmalloc` ring buffer vs. static array)
is this item's own implementation call.
@@ -5188,16 +5215,16 @@ document and committing that amendment as its own item.*
+ logs per CLAUDE.md.
*Refs:* §27.8.
- [ ] **4.4n — Toggle word: hide/show the scroll box.** A FORTH word that hides the 640×480
- [ ] **4.4o — Toggle word: hide/show the scroll box.** A FORTH word that hides the 640×480
scroll box, revealing the rest of CANVAS beneath it for drawing; showing it again restores
the scroll-box content undisturbed, no scrollback loss. Depends on 4.4k/4.4l (geometry) and
4.4m (scrollback) all being done first.
the scroll-box content undisturbed, no scrollback loss. Depends on 4.4l/4.4m (geometry) and
4.4n (scrollback) all being done first.
*Done when:* toggling off then on again, verified by screendump, shows the CANVAS drawing
area unobstructed while off and the exact prior scroll-box content restored when back on;
three-arch QEMU boot + logs per CLAUDE.md.
*Refs:* §27.8.
- [ ] **4.4o — `(user)` prompt segment — scoped, blocked, not started.** Extends 4.4's prompt
- [ ] **4.4p — `(user)` prompt segment — scoped, blocked, not started.** Extends 4.4's prompt
to `[VM name] (user) ok>`, e.g. `[Hera] (zuse) ok>`. **Blocked:** `zuse_session`
(`include/vm.h:393`) is a boolean only — no username/identity string exists anywhere in the
ACL system today (confirmed by reading `capsules/zuse.4th`, `capsules/ACL.4th`,
@@ -6009,7 +6036,7 @@ direct-arena reference — 4.3.7b's own call) behind that lookup.
*Refs:* §25.5 (punch list), GAP-B2.
### 27.8 REPL: prompt, text path, CANVAS geometry (4.44.4o)
### 27.8 REPL: prompt, text path, CANVAS geometry (4.44.4p)
Scoped 2026-08-11, in conversation with Captain Bob, replacing `docs/lithosananke/ROADMAP.md`'s
M8 section entirely (marked OBSOLETE there, kept for history only). Original visual reference:
@@ -6036,7 +6063,23 @@ actually read — all found by checking the tree per §25.0 rule 4, not by assum
per-line `[Name]` prefix on non-prompt output is unaffected (out of scope, not mentioned by
Captain Bob, not touched here).
- **Stroke-font color.** `TEXT ( c-addr u x y size color -- )` (§27.6.6) already takes a color
argument — confirmed before assuming 4.4f would need to add one.
argument — confirmed before assuming 4.4g would need to add one.
**End goal, stated by Captain Bob 2026-08-11, applies to every item in this series:** the
framebuffer console and the serial console must be functional **identically** — anything
printed reaches both. This is the standard 4.4c4.4e (and, once 4.4g lands, the ANSI-colored
TTF path) are built to.
**Found while verifying 4.4d by screendump — not future work, a pre-existing gap:** the whole
VT100-on-framebuffer pipeline this series assumed was live (parser, cell grid,
`draw_cursor_glyph`) has never actually been connected to the boot sequence.
`kernel_main.c:830-834` deliberately skips `console_fb_init()` (comment: "superseded by the
Console drawing-fabric redesign... deliberately not invoked here"), so `vt100_init()` never
runs and `vt100_putc()` no-ops on every call. No console output — not REPL text, not
boot/POST logs — has ever reached the framebuffer; only the framebuffer driver's own corner
self-test blocks have. ROADMAP.md's now-obsolete M8 section claimed this path was "already
live"; that was never actually screendump-verified, and turned out to be wrong. Given its own
item, 4.4c, ahead of 4.4d, which depends on it.
**Found, changes the shape of "VT100 is obsolete":** `vt100.c` is a complete ANSI/VT100
terminal state machine — CSI parameter parsing, cursor tracking, full SGR color support
@@ -6044,7 +6087,7 @@ terminal state machine — CSI parameter parsing, cursor tracking, full SGR colo
glyph-drawing call is a single, separate site (`put_char()``draw_cursor_glyph()`).
Captain Bob's "completely 100% obsolete" instruction, read against this, resolves to: keep the
CSI/SGR engine (it's exactly the "ANSI colorization throughout" mechanism wanted), retarget only
the one glyph-draw call site from `font_8x16.c` to `TTF-TEXT` (4.4e/4.4f). This is not a reversal of
the one glyph-draw call site from `font_8x16.c` to `TTF-TEXT` (4.4f/4.4g). This is not a reversal of
the obsolescence call — the VT100 *console text path as currently wired* (feeding
`font_8x16.c`-rendered REPL text) is still going away for user-facing text; the parser
underneath it is what survives, repointed.
@@ -6061,8 +6104,8 @@ the *physical framebuffer*, decoupled from REPL-strip sizing (resolved via `AskU
2026-08-11, implemented in `ttf_words.c` ahead of this item, verified by amd64 screendump
showing y=60/400/700 rendering bottom/middle/top respectively). CANVAS-relative placement — the
640×480 scroll box centered within the region above the REPL strip — is a separate layout
computation (4.4k) that translates into that same physical-framebuffer coordinate space before
calling `TTF-TEXT`. The primitive doesn't know about CANVAS or the REPL strip; 4.4k's layout
computation (4.4l) that translates into that same physical-framebuffer coordinate space before
calling `TTF-TEXT`. The primitive doesn't know about CANVAS or the REPL strip; 4.4l's layout
math does.
*Refs:* §25.5 (punch list), §27.6, §27.7.