FABRIC.md: renumber Artemis-last boundary 4.4 -> 4.5, add new 4.4 REPL item (console visual design scoped this session -- CANVAS is one shared region above the REPL strip, 640x480 scroll box centered within it, stroke font, ANSI color, VM-identity + ACL-identity prompt segments, ~1000-line scrollback), linked to repl-mockup.png. ROADMAP.md: mark M8 section OBSOLETE -- replaced by FABRIC.md 4.4, kept for history only. ttf_words.c: TTF-TEXT's y argument now Cartesian (origin bottom-left of the physical framebuffer, y increasing upward) instead of raw framebuffer coordinates, translated once via fb_height() - y. Verified via amd64 screendump (logs/20260811-070418/), text renders right-side-up with increasing y moving up the screen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
12 KiB
LithosAnanke Roadmap
Branch: lithosananke
Current: M7 Complete
Milestone Overview
M0 UEFI Boot ████████████████████ COMPLETE
M1 PMM ████████████████████ COMPLETE
M2 VMM ████████████████████ COMPLETE
M3 IDT ████████████████████ COMPLETE
M4 APIC ████████████████████ COMPLETE
M5 Timer ████████████████████ COMPLETE
M6 Heap ████████████████████ COMPLETE
M7 VM Parity ████████████████████ COMPLETE
M7.1 Capsules ████████████░░░░░░░░ DESIGN COMPLETE
M8 REPL ░░░░░░░░░░░░░░░░░░░░ OBSOLETE — see FABRIC.md §25.5 item 4.4
M9 Block I/O ░░░░░░░░░░░░░░░░░░░░ PLANNED
M10 Networking ░░░░░░░░░░░░░░░░░░░░ FUTURE
Phase 1: Boot Foundation (M0-M6)
M0: UEFI Boot + Serial Output
Goal: Kernel prints "LithosAnanke booting..." to serial
Deliverables:
- UEFI loader (
uefi_loader.c) - BootInfo handoff (memory map, ACPI, framebuffer)
- ExitBootServices
- Serial console output
Validation:
StarKernel UEFI Loader
Loading...
RAW SERIAL UP
M1: Physical Memory Manager
Goal: Track and allocate physical page frames
Deliverables:
- Bitmap allocator
- Parse UEFI memory map
pmm_alloc_pages()/pmm_free_pages()- Statistics reporting
Validation:
PMM initialized.
PMM statistics:
Total pages: 249450
Free pages : 247921
M2: Virtual Memory Manager
Goal: 4-level paging, identity + higher-half mapping
Deliverables:
- PML4 → PDPT → PD → PT setup
- CR3 switch
vmm_map()/vmm_unmap()- Self-test
Validation:
VMM initialized (mapped RAM, CR3 switched)
VMM self-test: mapped OK at 0xffff800000000000
M3: Interrupt Descriptor Table
Goal: CPU exceptions and IRQ handling
Deliverables:
- 256-entry IDT
- ISR stubs (asm)
- Exception handlers (div-by-zero, page fault, etc.)
- IRQ routing framework
Validation:
IDT installed.
M4: APIC Timer
Goal: Local APIC initialization and timer IRQs
Deliverables:
- Local APIC enable
- APIC timer configuration
- Spurious interrupt vector
Validation:
APIC: init...
APIC enabled (SIVR=0xFF).
APIC: init done
M5: Timer Calibration
Goal: Accurate time measurement
Deliverables:
- TSC frequency detection
- HPET calibration (when available)
- PM Timer fallback
- Relative vs. absolute trust levels
Validation:
Timer: init...
Timer: trust=1 (0=NONE,1=REL,2=ABS), TSC=0 Hz
Timer: init done
M6: Kernel Heap
Goal: kmalloc() / kfree() working
Deliverables:
- Heap initialization
- Allocation tracking
- Statistics
Validation:
Kernel heap initialized.
Heap statistics:
Total bytes: 16777176
Free bytes: 16777176
Phase 2: VM Integration (M7)
M7: VM Parity Validation
Goal: StarForth VM boots with reproducible dictionary hash
Deliverables:
- VMHostServices abstraction
- VM arena allocation (5 MB)
- FORTH-79 word registration (295 words)
- Parity checkpoint logging
- Heartbeat thread start
Validation:
VM: bootstrap parity...
[HAL][host] VMHostServices table registered
VM arena allocated: 0xffff900000000000 (5 MB)
Registering FORTH-79 Standard word set...
PARITY:M7.1a word_count=295 here=0x30 latest_id=294 hash=0x684bbf2fa1d96d55
PARITY:OK
VM: parity bootstrap complete
Starting heartbeat...
APIC Timer: started
Commit: 6f350bc — M7: StarForth VM integration with parity validation
Phase 3: Capsule Architecture (M7.1)
M7.1: Init Capsule System
Goal: Content-addressed, immutable init capsules for VM birth
Status: Design Complete (see M7.1.md)
Core Concepts:
| Concept | Description |
|---|---|
| DOMAIN | Mama-only construction space — never visible to babies |
| PERSONALITY | Baby-only identity — result of executing (p) INIT |
| (p) Production | Truth-bearing capsules that birth VMs |
| (e) Experiment | Mama-only workloads for DoE |
Birth Protocol:
- Mama selects one production
(p)capsule by content hash - Mama validates eligibility (ACTIVE, PRODUCTION, not REVOKED)
- Mama allocates new VM
- INIT blocks copied to execution window (RAM blocks 0–2047)
- INIT blocks executed sequentially
- Execution window cleared
- VM begins life with PERSONALITY imprinted
- Mama logs
PARITY:BIRTH vm_id=N capsule_id=X mode=p ... - Mama increments
capsule.birth_count
Deliverables:
CapsuleDescstruct (64 bytes, cache-aligned)CapsuleDirHeaderstruct- xxHash64 implementation (freestanding)
capsule_validate()function- Birth protocol (
PARITY:BIRTHlogging) - DoE run logging (
CapsuleRunRecord) mkcapsulebuild tool
Key Design Decisions:
- Content-addressed:
capsule_id == content_hash - (p) Production vs (e) Experiment modes
- One truth per VM — no shared/implicit base INITs
- Mama holds all truths — (e) capsules never touch babies
- Twins/variants are just VMs with same/similar capsules
Phase 4: Interactive Forth (M8)
⚠ OBSOLETE (2026-08-11). This entire M8 section is superseded by
FABRIC.md§25.5 item 4.4 (REPL). The console/REPL design has moved past what's scoped here — do not use this section as a source for REPL or CANVAS design decisions. Kept in place for history only.
M8: REPL + Interactive Forth
Status: Scoped 2026-08-11 (this section). Substrate (interrupt-driven keyboard input, glyph rendering) already complete via Stadium's Console fabric work (FABRIC.md §25.5 items 4.3.5–4.3.7f) — see "What's already done" below. This scoping pass covers what's left: wiring the existing keyboard-event stream into the REPL's character input path.
Goal: Type Forth at the kernel keyboard (not just serial), get ok prompt.
The REPL already works interactively over serial today (sk_repl_run(),
src/starkernel/repl.c) — that is not what this milestone adds. What's missing
is a second input source feeding the same loop.
What's already done, read from the code before scoping this, not assumed:
- Interrupt-driven keyboard input on all three architectures (amd64 i8042,
aarch64/riscv64 virtio-keyboard-pci + GIC/PLIC), converged behind one shared
interface:
KEY-EVENT ( -- keycode pressed -1 | 0 )insrc/word_source/keyboard_words.c,keycodein the Linux input keycode namespace. FABRIC.md items 4.3.5–4.3.5f, verified live on all three architectures with real keypresses. - Glyph rendering, both paths: the stroke-drawn font (
TEXT, capsule-based, 113-glyph v1 repertoire, FABRIC.md 4.3.6–4.3.6g) and TrueType (TTF-TEXT, proportional spacing via realhmtxadvance widths, FABRIC.md 4.3.7–4.3.7f). Neither is required for the REPL text itself, though — see the VT100 finding below. - The REPL's on-screen text already renders independently of both of the
above.
console_fb_init()(src/starkernel/hal/console.c) callsvt100_init(), which mirrors everyconsole_putc()/console_puts()call to the framebuffer via the baked-infont_8x16.craster font. This is already live — the REPL prompt and its output appear on screen today, serial-driven, no CANVAS/glyph-capsule dependency. This confirms §27.6's mockup: a fixed VT100 REPL strip (already working) plus a separate large CANVAS region above it (still unsized — see the last deliverable below).
What's actually missing, confirmed by reading the code, not assumed:
src/starkernel/repl.c's sk_readline() reads characters via
console_getc() (src/starkernel/hal/console.c), which is serial-UART-only —
it never looks at KEY-EVENT. Separately, the FORTH-79 words KEY/?TERMINAL
(src/word_source/io_words.c:84-108, shared/vendored source) are dead in the
kernel build: KEY calls libc getchar(), which the kernel shim
(src/starkernel/vm/host/shim.c:1206) hardcodes to return -1 (EOF);
?TERMINAL is a literal stub that always returns false. Neither path has ever
been wired to a real keyboard.
Deliverables:
- Minimal scancode→ASCII layout: a small lookup table (US QWERTY,
unshifted/shifted rows only — no dead keys, no locale switching) driven
by
KEY-EVENT's Linux-namespace keycodes, plus shift-state tracking (KEY_LEFTSHIFT/KEY_RIGHTSHIFTpress/release) sinceKEY-EVENTitself carries no modifier state today (confirmed by readingkeyboard_words.c— deferred at 4.3.5f, not implemented anywhere). - Merge keyboard into
console_getc()'s poll: extend it (or add a second functionsk_readline()polls alongside it) to also drainKEY-EVENTand translate presses to ASCII via the layout table above. Serial stays a co-equal input source, not replaced — the entire acceptance/DoE harness injects FORTH commands over the serial socket (socat ... UNIX-CONNECT:$SERIAL_SOCK) and greps the serial log forok>; breaking that path breaksmake qemu,DOE_INJECT, and every screendump verification technique used throughout 4.3.x. Both sources feed the same byte stream into the existingsk_readline()— no new line-editing code needed, backspace/echo already work (sk_readline(),repl.c:83-141). - Wire
KEY/?TERMINAL(io_words.c) to the same merged source under#ifdef __STARKERNEL__, for FORTH-79 compliance — any capsule calling these directly (not just the REPL) should get real input too, not a permanently-EOF stub. Small addition once the merge above exists. - CANVAS viewport sizing (§27.6's explicit deferral to this milestone): the large graphics region above the VT100 REPL strip needs an actual scrollable framebuffer viewport size decided (e.g. 640×480, per the original mockup) — layout/presentation, not input plumbing; do this last, after keyboard input works, since it doesn't block interactivity.
Explicitly out of scope for this milestone (minimal bar, matches "Line
editing (backspace, minimal)"): extended (0xE0-prefixed) i8042 scancodes,
virtio-input autorepeat (value=2) as actual character repeat, arrow-key
cursor movement/history, non-US keyboard layouts. Deferred to a later item if
ever needed — not blocking "type Forth at the kernel, get ok."
Validation:
LithosAnanke v0.3.0
ok 1 2 + .
3 ok
(via a real keypress on all three architectures, same live-keypress verification standard FABRIC.md 4.3.5f already established — not a serial-injected synthetic test, though serial injection must still work identically afterward.)
Phase 5: Persistence (M9)
M9: Block Storage
Goal: Read/write blocks to disk
Deliverables:
- AHCI driver (SATA)
- Block device abstraction
BLOCK/BUFFER/UPDATE/FLUSHwords- Persistent dictionary
Future Milestones
M10: Networking
- VirtIO-net driver
- TCP/IP stack (minimal)
- DHCP client
M11: Process Model
- Forth tasks
- Scheduling
- IPC
M12: Self-Hosting
- Compile Forth on LithosAnanke
- Edit/assemble/link cycle
Validation Commands
# Build
make -f Makefile.starkernel ARCH=amd64 STARFORTH_ENABLE_VM=1
# Run QEMU
make -f Makefile.starkernel ARCH=amd64 STARFORTH_ENABLE_VM=1 qemu
# Clean
make -f Makefile.starkernel ARCH=amd64 clean-kernel
Branch Relationship
master (hosted StarForth)
│
├── lithosananke (kernel branch)
│ │
│ └── M7 complete, M7.1 design complete
│
└── starkernel-junkyard (legacy, can delete)
Success Criteria
LithosAnanke is successful when:
- M7 Parity — VM dictionary hash reproducible across boots
- M7.1 Capsules — Birth protocol enforced, provenance logged
- M8 REPL — Interactive Forth at bare metal
- M9 Persistence — State survives reboot
The foundation is laid. The necessity is clear.