Skip to content

Latest commit

 

History

History
724 lines (666 loc) · 145 KB

File metadata and controls

724 lines (666 loc) · 145 KB

DipshitOS living status, goals & changelog

Host identity: Apple silicon running macOS 27 or newer only — hosted by Apple's Virtualization.framework; not Linux, not Unix, not QEMU (see AGENTS.md). The runner enforces the floor at runtime (macOS 27+).

This file is the project's living status tracker and its multiagent coordination surface: where we are, what we are trying to build next, how far along each step is, who currently claims which piece of work, and pointers to the append-only per-branch changelog. Claims and logs are sharded (see Multiagent coordination) so parallel agents never collide on one file. Update it as work lands — flip the checkboxes, fill in the notes, and append to your branch's log under docs/logs/. Claims stay honest per AGENTS.md: observed (log evidence under artifacts/) versus inferred (reasoning/docs only).

Premise check (2026-08-06): this tracker was first frozen against the milestone-one-era main. On the same day, PRs #6/#7 merged the milestone-two kernel proper (ADR 0004), which changed the premises below: the kernel now calls ExitBootServices, owns an identity-map MMU, drives a polled TX-only MMIO serial console, and never returns. This file was refreshed accordingly — the plan's shape is kept, its factual anchors are reconciled with the merged state. PR #10 later unified this tracker with the milestone-two gate evidence and added the multiagent changelog (now sharded per branch under docs/logs/; see the Changelog).

Current position

Milestone What it proved / is Status
Zero — boot pipeline A Zig AArch64 UEFI app on a FAT32 ESP boots under real firmware; output observed on host (\BOOTED.TXT) ✅ done
One — kernel handoff Separate freestanding KERNEL.BIN loaded, cache-maintained, jumped to, and returned (\RC.TXT = kernel_rc=0x0); ADR 0002 ✅ done
Two — kernel proper ExitBootServices, captured EFI map, identity TTBR0_EL1 tables, MMIO serial probe + polled TX console (ADR 0004) gates passed 2026-08-08 (claim 1517): bad-handoff failure gate passing since 2026-08-06, VZ serial gate now passing (post-MMU virtio TX fixed)
1.5 — Interactive Kernel Monitor ("Dipshit Monitor") A live, interactive command monitor served by the kernel's serial console (the milestone-two terminal loop becomes its payload) done 2026-08-09 — all 7 hard gates pass; the last (filesystem, claim 3475) closed 2026-08-09 and upgraded to a real FAT32 storage driver (claim 6420); tagged m1.5-interactive-monitor
Three — allocator, interrupts, tasks Physical allocator, GIC + timer, tasks, EL0, and syscalls 🚧 active — allocator, IRQ/timer, and round-robin tasks are done (claims 3972/5162/9187/5275); the first EL0t task + SVC boundary landed in claim 8215; the frozen 64-slot syscall ABI and slots 0–3 (ping/write/yield/exit) pass their live VZ gate (claim 3594); the fault-safe uaccess layer (claim 6120), the per-task address spaces card (claim 5804 — per-task TTBR0 with an EL1-only kernel overlay, VZ TTBR1 fallback), the user task lifecycle card (claim 6729 — explicit states, bounded spawn, exit→zombie, idle-task reaper, plus the callee-saved vector-frame fix that made preemption of compiled tasks safe), and the ESP exec card (claim 6783 — a real user program, USER.BIN, is loaded from the ESP through the claim-6420 FAT path by the exec monitor command, the EL0 user root is rebuilt around its page, and the program runs at EL0, writing via sys_write, round-tripping pings, and exiting through the lifecycle), and the blocking-syscalls card (claim 3200 — sys_sleep slot 4 blocks the caller for N scheduler ticks with timer-driven wakeup, the ESP program sleeps 2 ticks and wakes, and the worker keeps advancing during the sleep window) all landed and pass their live VZ gates. Milestone three is CLOSED 2026-08-10 (claim 0707): the full class A + class B gate set re-ran green at the candidate and the milestone is tagged m3-userspace (see the march tracker docs/march-m3.md row 8).
Four — real randomness Virtio entropy driver + ChaCha20 CSPRNG (RFC 7539), boot-time seed, random command, ASLR, general (non-ESP) filesystem, process abstraction done 2026-08-11 (claim 2839, tag m4-processes at 9d7e4d5) — milestone-four cards 1 + 2 + 3 landed 2026-08-10 (claims 2665/3693 + 3678 + 3848, see the march tracker docs/march-m4.md): the kernel now has a REAL randomness source — virtio-pci entropy driver (kernel/src/virtio_entropy.zig, DID 0x1044) with the post-MMU re-arm (observed: VZ resets the device at ExitBootServices — entropy: pre-rearm st=00), a freestanding ChaCha20 CSPRNG (kernel/src/csprng.zig) keyed from a 64-byte boot seed (entropy: seeded n=64), the random [n] monitor command (registry 27→28), and EL0 user-stack ASLR consuming the seed for BOTH exec'd programs and the boot-time static payload (every EL0 task gets per-boot stack placement — exec: loaded … stack=0x…, aslr: boot user stack=0x…). Card 2 generalizes the claim-6420 FAT32 driver into a general (non-ESP) filesystem: fat.mount_partition mounts any volume at any LBA, directory cluster chains + /-path resolution make the image's EFI/BOOT tree reachable (ls [<dir>], `cat <file
Five — networking The runner attaches a virtio-net device (--net, flag-gated); the guest's virtio-net transport drives TX end to end — feature negotiation, queues 0/1, MAC read, bounded frame staging, polled used-ring drain — and the host receives exact Ethernet frames 🚧 active — milestone five, card N1 (claim 1373, branch agent/buffy/m5-net-tx): the virtio-net TRANSPORT + TX is live on VZ — device DID 0x1041 (class 0x020000), VER1|MTU|MAC negotiated (the device needs MTU accepted — feat=0x28/0x1), host-set MAC read via the feature path (mac=02:00:00:00:00:01 source=feature), queues 0/1 armed size 4, DRIVER_OK through the post-exit re-arm (the net device does NOT reset at ExitBootServices — net: pre-rearm st=0f observed, unlike blk/entropy), a 12-byte virtio_net_hdr consumed on every TX buffer (observed contract — the driver prepends a zeroed header), and netsend sends known frames the host captures byte-exactly (46-byte fixture + ring reuse + honest 1500-byte truncation). New class-B gate bash tools/verify-live-net-tx.sh PASS 2/2; the full class-A set and the 29-gate verify-vz aggregate (incl. the net gate) re-ran green (proof the --net mode left the default VM byte-identical; evidence artifacts/live-net-tx-*, artifacts/live-net-tx-vz-sweep.log). Card N2 (claim 6076, branch agent/buffy/m5-net-rx) — raw Ethernet RX is LIVE 2026-08-11: the runner's --net-inject <file> writes the attachment's socket end ONCE on the guest's net: rx-armed serial trigger (host→guest; OFF by default); queue 0 is supplied with one fixed BSS buffer (4096 bytes), the used ring is drained POLLED (the net device's used-buffer IRQ is not yet observed — recorded, not assumed), each delivery is MAC-filtered (own + broadcast accepted, other dropped with a counter) into a bounded 4-slot frame FIFO, and net recv prints the received frame byte-exact. Claim-time observations: the device WRITES a 12-byte virtio_net_hdr into RX buffers (first frame device-len 72 for 60 bytes, first 16 bytes 00…01 00 ff ff ff ffnum_buffers=1; the RX-header question answered) and REFUSES an RX buffer under 1530 bytes (1526/1528/1529 wedged the device — no frame written, used ring never advanced, TX stalled; 1530 works). New class-B gate bash tools/verify-live-net-rx.sh PASS 3/3: phase 1 injects the 60-byte broadcast known frame — net recv prints it byte-exact AND the guest re-sends it (the host capture is byte-exactly the injected fixture — the round trip); phase 2 own-MAC frame received byte-exact; phase 3 foreign-MAC frame dropped (filtered=1, rx-obs still records the delivery). Full class A green; the 29-gate verify-vz aggregate re-ran green 29/29 (evidence artifacts/live-net-rx-*, artifacts/m5-net-rx-vz-sweep.log). Card N3 (claim 7293, branch agent/buffy/m5-arp) — ARP is LIVE 2026-08-11: kernel/src/arp.zig (pure RFC 826 logic — static IP via net ip <a.b.c.d>, byte-exact request/reply builds, bounded 4-slot BSS table, counters) wired into the RX drain (a request for our IP is answered on the N1 TX path; a reply is learned; the rest dropped with a counter) + net arp [<ip>] subcommand + the runner's --net-arp-respond <host-ip> (deterministic host-side ARP answer inside the capture thread; OFF by default). New class-B gate bash tools/verify-live-net-arp.sh PASS 3/3: phase 1 the guest answers the injected request for its IP (42-byte reply byte-exact in the capture, repl=1); phase 2 the guest resolves 10.0.0.2 (request byte-exact in the capture; the host answer lands as 10.0.0.2 -> 02:00:00:00:00:02, learn=1); phase 3 a request for 10.0.0.99 is dropped (drop=1, repl=0, still observable via net recv). Claim-time observation: the device delivers/transmits the 42-byte ARP frames unpadded (below the Ethernet 60-byte minimum). Full class A green; the 31-gate verify-vz aggregate re-ran green 31/31 (evidence artifacts/live-net-arp-*, artifacts/m5-arp-vz-sweep.log; verify-live-concurrent flaked once on a scheduler-timing interleave=0 and passed on immediate retry — recorded, not hidden). Card N4 (claim 0148, branch agent/buffy/m5-ipv4) — IPv4/ICMP is LIVE 2026-08-11: kernel/src/ipv4.zig (pure RFC 791/792 logic — RFC 1071 one's-complement checksums, parse/build, byte-exact ICMP echo request/reply builders, fragments dropped COUNTED — no reassembly, honest bound) wired into the RX drain BESIDE the ARP dispatch (an echo request for our static IP is answered byte-exact on the N1 TX path; an echo reply is observed — pongs_observed + the echoed sequence; the rest dropped with counters) + net ping <a.b.c.d> subcommand (an echo needs a unicast dst — the peer must be in the ARP table first; refused honestly otherwise) + the runner's --net-icmp-respond <host-ip> (deterministic host-side echo answer inside the capture thread — type 0 reply, id/seq/payload echoed, both checksums recomputed; OFF by default). New class-B gate bash tools/verify-live-net-icmp.sh PASS 3/3: phase 1 the guest answers the injected 46-byte echo request for its IP (reply byte-exact in the capture with the identification + id/seq/payload echoed, repl=1); phase 2 the guest resolves 10.0.0.2 and pings it (the ARP request + 46-byte echo request are byte-exact in the capture; the host answer lands as pong=1 with seq=1); phase 3 an echo request for 10.0.0.99 is dropped (drop=1, repl=0, still observable via net recv). No new hardware-contract entry — the 46-byte frames travel unpadded, consistent with the N3 observation. Full class A green; the 32-gate verify-vz aggregate re-ran green 32/32 (evidence artifacts/live-net-icmp-*, artifacts/m5-ipv4-vz-sweep.log). Card N5 (claim 8552, branch agent/buffy/m5-udp) — UDP is LIVE 2026-08-11: kernel/src/udp.zig (pure RFC 768 logic — the 8-byte header, the checksum over the IPv4 PSEUDO-HEADER computed ALWAYS, a bounded 4-slot LISTEN table, bounded per-listener datagram rings, LOOPBACK — a send to our OWN IP delivers directly into the local receive path, no device round trip) wired into ipv4.zig's protocol dispatch (protocol 17 → udp on ALREADY-VALIDATED frames; TCP/other still dropped_proto) + `net udp [listen
Six — graphics: Driving Award + Road Pops Boot to a graphical interface: a virtio-gpu framebuffer (G1), framebuffer text rendering (G2), the boot terminal re-targeted to the screen as Road Pops (G3), and the Driving Award window manager compositing multiple windows (G5), and a draw/window syscall seam for EL0 programs (G6). Keyboard/pointer input (the original G4) was split into milestone seven (USB XHCI + HID) done 2026-08-13 (cards G1–G6 live) — card G1 (claim 6053, branch agent/buffy/m6-gpu) LIVE 2026-08-12 — the FIRST NON-BLANK GUEST FRAMEBUFFER on VZ: the runner's --display/--screenshot mode attaches VZVirtioGraphicsDeviceConfiguration (1280×720 scanout; OFF by default — the default VM byte-identical); kernel/src/virtio_gpu.zig discovers the modern virtio-pci gpu (DID 0x1050 observed, class 0x038000, dev 7; config layout common@+0x0000 / ISR@+0x1000 / notify@+0x4000 / devcfg@+0x8000 — claim-0013's decoded shape), negotiates VER1-only (device offers RING_PACKED|RING_EVENT_IDX|RING_INDIRECT_DESC|VERSION_1), arms controlq (queue 0) + cursorq (queue 1), re-arms post-exit (VZ RESETS the gpu at ExitBootServices — pre-rearm st=00, like blk/entropy, unlike net's st=0f), and drives the spec 2D path GET_DISPLAY_INFO → CREATE_2D (B8G8R8X8) → ATTACH_BACKING (4K-aligned BSS framebuffer) → SET_SCANOUT → TRANSFER → FLUSH. Claim-time findings (hardware-contract + claim doc): virtio-gpu 1.2 wire shapes (the 24-byte display_one; the pre-1.2 20-byte shape wedged the device with DEVICE_NEEDS_RESET), the tail descriptor's next must be 0 (VZ walks it), command/framebuffer cache cleans are mandatory (MMU-on, not caches-off), and the scanout composites with alpha — an X/A byte of 0 renders fully transparent (the final black-screen fix; fills write X=0xff). screen / screen fill <rrggbb> / screen peek monitor commands (registry 34→35). New class-B gate bash tools/verify-live-screen.sh PASS 1/1 — the transport report + guest-side fill bytes + the DECODED capture: 14400/14400 sampled pixels are the fill green (0x00ff00 → ~(117,251,76) through the color-managed pipeline; evidence artifacts/live-screen-*, artifacts/gpu-screen-*s). Full class A green; the 35-gate verify-vz aggregate re-ran green (artifacts/m6-gpu-vz-sweep.log). Card G2 (claim 3194, branch agent/buffy/m6-text) LIVE 2026-08-12 — the machine boots to WORDS on the screen: kernel/src/text.zig (the public-domain 8x8 bitmap font — ASCII 0x20–0x7e, fixed BSS glyph table; putc/puts, cursor, line wrap, a bounded 128-line scrollback ring, clear; the pure renderer is host-tested against an injectable mock canvas — 21 tests incl. golden glyphs, wrap/scroll/clear, bounds, cursor, composition) paints the SAME banner + prompt the serial log carries over G1's framebuffer (fg 0x00ff00 on bg 0x101418) and pushes it through G1's transfer/flush unchanged (text: boot banner presented); text / text put <string> / text clear monitor commands (registry 35→36). New class-B gate bash tools/verify-live-text.sh PASS 1/1 — the DECODED capture shows real glyphs: the banner region samples fg=0.255 (green family) over bg=0.745 (the dark 0x101418) — the screen is no longer monochrome — with the region below all background (evidence artifacts/live-text-*, artifacts/gpu-screen-*s); the live-pixel bound is "text visible with the expected color family" (color-managed + retina-scaled; byte-exact glyphs live in the class A mock — the G1 gate's precedent). Full class A green; the 36-gate verify-vz aggregate re-ran green 36/36 (artifacts/m6-text-vz-sweep.log). Card G3 (claim 1574, branch agent/buffy/m6-roadpops) LIVE 2026-08-12 — ROAD POPS: the boot terminal is on the screen: kernel/src/road_pops.zig is a TEE console — every byte still reaches serial FIRST (the shared seam; the transcript gates keep passing byte-identical) AND G2's text layer paints the same banner + prompt + every reply on the framebuffer, drained ONE full-frame present per output batch by the shell idle loop. The G2 one-shot boot paint is replaced by the tee rendering the shell's OWN banner (its first present emits the G2 text: boot banner presented evidence on serial). Claim-time fix (claim-0015 redux, observed live): a road_pops.Target struct literal with all-constant fields was folded into .rodata, whose &fn entries hold LINK-TIME absolute addresses — the tee's first write jumped to the link-time rp_text_put_bytes and faulted (esr=0x02000000 elr=0x14260); the Target is now built in RAM like ensure_vtable so every &fn resolves PC-relatively. roadpops monitor command (registry 36→37: armed/dirty/presents). New class-B gate bash tools/verify-live-roadpops.sh PASS 1/1 — the DECODED capture shows the boot banner (fg=0.255) AND the LIVE SESSION glyphs below it (fg=0.124 — the echoed echo ROADPOPS/uname commands + replies rendered; the screen is a working terminal, not a one-shot splash), with the serial transcript still carrying the whole session (evidence artifacts/live-roadpops-*, artifacts/gpu-screen-*s). G1/G2 gates updated honestly for the Road Pops reality: the terminal's drain-presents render over the raw fill, so G1's pixel phase now asserts the non-blank terminal frame (the fill is proven guest-side — fill=…ff00 transfer=ok flush=ok + peek p1=0xff; its cmds= is now session-dynamic), and the text report's cur/lines are session-dynamic (its own output feeds the ring). Full class A green; the 37-gate verify-vz aggregate re-ran green 37/37 (artifacts/m6-roadpops-vz-sweep.log) — the default VM stayed byte-identical. Card G5 (claim 1543) LIVE 2026-08-13 — Driving Award, the window manager: kernel/src/driving_award.zig (bounded BSS registry, z-order, focus, hit-test, dirty-rect compositor) makes Road Pops window 0 and a 1 Hz clock overlay window 1; the I3 keyboard read source is gated on the terminal's focus. win/win focus <n>/win raise <n>/win hit <x> <y> (registry 39→40). New class-B gate bash tools/verify-live-win.sh PASS 1/1 — the serial session (windows=2, hit-test focusing the clock then the terminal) + a KEYBOARD-typed uname landing in the focused terminal (DipshitOS aarch64), and the DECODED capture shows two overlapping windows with the right z-order (the clock's amber title bar + navy body over the terminal, the terminal's green glyphs beside it). Full class A green; the default VM stayed byte-identical. Card G6 (claim 0487) LIVE 2026-08-13 — the draw/window syscall seam: the ADR 0007 amendment slots 12/13/14 (sys_win_open/sys_win_fill/sys_win_present, implemented 12 → 15, then a teardown follow-on adds slot 15 sys_win_close + win close → 16) expose the G5 window manager's user-window surface to EL0 — sys_win_open opens a bounded kernel-owned window (id 2..3, fixed BSS back-buffer ≤ 256×192 B8G8R8X8), sys_win_fill fills rects, sys_win_present marks it dirty for the compositor (no uaccess — plain numbers; the kernel owns the buffers; the window persists after the caller exits, the honest bound). WIN.BIN (user/src/win.zig, the first graphics user program, loaded by exec) drives it end to end: win: open id=2win: fill ok (dark-blue background + red/cyan/white blocks) → win: present oksys_exit(87). New class-B gate bash tools/verify-live-win-syscall.sh PASS 1/1 — the observation phase on the SAME kernel state (win: windows=3 focused=2 + win[2]: user user rect=64,64,256,192 z=2; syscalls implemented=16 with open=1/fill=4/present=1 + slot 15 sys_win_close registered) and the DECODED capture shows the window's own content over the terminal (no terminal foreground showing through — z-order). Full class A green; the default VM stayed byte-identical (sys_win_open returns EINVAL when the manager is unarmed). Teardown follow-on (this branch): win close <n> (monitor) + sys_win_close (slot 15) release a user window so the id (2..3) can be re-opened instead of leaking until reboot — both call driving_award.user_close; open → fill → present → close → re-open is host-tested in driving_award + syscall, and a SEVENTH image WINCLOSE.BIN proves it LIVE from EL0: the class-B gate tools/verify-live-win-close.sh PASS 1/1 — WINCLOSE.BIN opens/fills/presents/CLOSES (slot 15) and exits 88, twice; win shows windows=2 after the close (no win[2]: row) and the re-exec re-opens id 2 (the freed slot reused, never id 3). Ownership follow-on (this branch): windows are OWNED by the opening process and AUTO-CLOSE when it exits (the scheduler's exit_current calls driving_award.close_owner(pid) — the real teardown semantic); sys_win_fill/present/close are owner-restricted (host-tested cross-process refusals); an EIGHTH image WINLOOP.BIN keeps its window alive so the restructured tools/verify-live-win-syscall.sh still pixel-proves EL0 rendering (WIN.BIN's window now vanishes on exit — windows=2, sys_win_close calls=0). Move/raise follow-on (this branch): slots 16/17 (sys_win_move/sys_win_raise, implemented 16 → 18) reposition + restack the caller's window from EL0 (move clamps on-scanout, raise reorders the z-order, both owner-restricted); the monitor's win move <n> <x> <y> is the EL1h half; a NINTH image WINMOVE.BIN drives it live and tools/verify-live-win-move.sh PASS 1/1 shows the clamped rect (win[2]: user user rect=1024,528,256,192) + the counters (move=2/raise=1) + the decoded capture with the window's colors at the NEW position. Read-back follow-on (this branch): slot 18 (sys_win_get, implemented 18 → 19) copies the caller's window rect (four u32 LE words) OUT through uaccess — the ONE pointer-taking win slot — so an EL0 program reads its clamped position back after sys_win_move; WINMOVE.BIN now prints winmove: get 1024,528,256,192 (the gate's get=1 + implemented=19 assertions). Full-state query follow-on (this branch): slot 19 (sys_win_query, implemented 19 → 20) copies the caller's window FULL state (eight u32 LE words: x, y, w, h, z, focused, visible, dirty) OUT through uaccess — so an EL0 program introspects z-order rank + focus + visible/dirty, not just the rect; WINMOVE.BIN now prints winmove: query 1024,528,256,192 z=2 focused=1 visible=1 dirty=1 (the gate's query=1 + implemented=20 assertions). Visibility follow-on (this branch): slot 20 (sys_win_set_visible, implemented 20 → 21) HIDES (visible 0) or SHOWS (visible 1) the caller's window from EL0 (driving_award.user_set_visible, owner-restricted; the fixed terminal + clock are refused, a non-0/1 flag is EINVAL) — hiding marks the terminal dirty so the next composite repaints over the hidden window, showing marks the window dirty so it reappears; the back-buffer + z-order rank are untouched. WINMOVE.BIN now hides its window, sleeps 2 ticks, shows it again, and prints winmove: hide ok / winmove: show ok; tools/verify-live-win-move.sh asserts hide=1/show=1/set_visible=2 + implemented=21 and gained a marker-driven capture (--screenshot-after "winmove: hide ok", a new VMRunner flag) proving the PIXEL DISAPPEARS (no red/cyan/white blocks at the clamped spot while hidden) and RETURNS (the LATEST capture shows them back). Milestone six closed — G1–G6 all live.
Seven — input: USB XHCI + HID (keyboard + pointer) Give Road Pops its FIRST screen-side keystrokes: an XHCI host-controller transport (I1 — MMIO + command/event rings + port status), USB enumeration + HID boot-protocol parsing (I2 — the keyboard + pointing devices behind the XHCI controller), and a bounded event FIFO + keycode decode feeding the line editor (I3). Premise corrected 2026-08-13 (claim 3868): VZ's VZUSBKeyboardConfiguration + VZUSBScreenCoordinatePointingDeviceConfiguration present as an Apple XHCI USB controller (VID=0x106b DID=0x1a06 CLS=0x0c0330, two MMIO BARs 0x50001000 + 0x50000000) with the keyboard/pointer as USB HID devices behind it — the hypothesized virtio-input (DID 0x1052) does not exist in the framework. done 2026-08-13 (cards I1–I3 live) — card I1 (claim 4272) LIVE 2026-08-13 — the XHCI host-controller transport works on VZ: kernel/src/xhci.zig discovers the Apple XHCI controller pre-exit (bus 0 dev 8, DID 0x1a06 CLS 0x0c0330), maps its MMIO register space post-MMU (BAR0=0x50001000 cap regs / BAR1=0x50000000; CAPLENGTH=0x20, HCIVERSION=0x110, DBOFF=0x940, RTSOFF=0x520, HCSPARAMS1=0x10002010 = 16 slots/32 intrs/16 ports), sets up the command ring + event ring + ERST + primary interrupter, drives a NO-OP command TRB to CC=1 (the ring machinery proven), and reads the port status. Claim-time observations (hardware-contract + claim doc): the interrupter register set i lives at RTSOFF+0x20+(0x20×i) (writing ERSTSZ into the MFINDEX region wedged the emulation — the fix); VZ does NOT reset the controller at ExitBootServices (pre-reset USBSTS=0x9/USBCMD=0x0 — the XHCI answer to the st=00 vs st=0f question); after HCRST+RS USBSTS=0x0; ports 9 and 10 report CCS=1 — exactly the two attached HID devices (keyboard + pointer), the I2 handoff. usb monitor command (registry 37→38). New class-B gate bash tools/verify-live-xhci.sh PASS 1/1 (14/14 assertions; the gate asserts the guest's own usb report — the card's gate-shape change: byte-exact host capture does not apply to a memory-mapped controller). Full class A green; the default VM is byte-identical (no XHCI lines in the default serial log; the --input mode is flag-gated OFF). Card I2 (claim 4116) LIVE 2026-08-13 — USB enumeration + HID works on VZ: kernel/src/xhci.zig now enumerates BOTH devices end to end (port reset → Enable Slot → Address Device → device + config descriptors over the control endpoint → Set Configuration 1 → interrupt-IN endpoint armed) and parses the HID boot-protocol reports — the keyboard (port 9, slot 1, VID 0x05ac PID 0x8105, boot protocol=1, EP1-IN maxpkt 8, boot=1) and the absolute pointer (port 10, slot 2, VID 0x05ac PID 0x8106, protocol=0 — NOT a boot mouse — EP1-IN maxpkt 10, Set_Protocol(boot) honestly REFUSED boot=0). A synthesized host keyDown (macOS keyCode 0, dispatched by the runner's new minimal --input-key/--input-key-after seam — VZ has NO programmatic keyboard API) produced the observed 8-byte report 00 00 04 00 00 00 00 00 (mod 0, HID usage 0x04 = 'a'). usb gained usb devices/usb report (registry 38 stays). New class-B gate bash tools/verify-live-usb.sh PASS 1/1 (11/11 assertions; the gate asserts the guest's own usb devices + usb report lines — no host-side byte-exact capture applies to a memory-mapped controller). Card I3 (claim 6050) LIVE 2026-08-13 — keystrokes drive Road Pops on VZ: kernel/src/input.zig is a bounded pure-BSS event FIFO + HID-usage → ASCII keymap + the shell-idle drain (the card-3d pattern, next to net RX): the XHCI interrupt-IN reports decode to ASCII bytes that the Road Pops tee's read path hands to the line editor. Claim-time observations (hardware-contract + claim doc): VZ delivers ~one report per Road Pops present cadence, so the runner's scripted key surface types at 2 s per keystroke (faster drops reports); single-TRB arming (re-armed per completion) is the correct shape — a multi-TRB depth experiment wrapped the transfer ring at the 8th report and dropped everything after; the input drain runs BEFORE the Road Pops present so a report is never starved behind a slow full-frame present. The runner's --input-string/--input-string-after synthesizes one NSEvent per keyDown/keyUp into the VZVirtualMachineView (VZ has NO programmatic keyboard API). input monitor command (registry 38→39: armed/fifo/drop count/last keyboard + pointer events). New class-B gate bash tools/verify-live-input.sh PASS 1/1 (8/8 assertions): the keyboard typed input\n and the guest's own input report showed events=6 (i,n,p,u,t,Enter) with dropped=0 and kb-usage=0x28 kb-byte=0xa (Enter) — the typed command ran end to end. Full class A green; the default VM is byte-identical (no xhci/input/usb lines in the default serial log; the --input mode is flag-gated OFF). Milestone seven closed — I1/I2/I3 are all live,handing Road Pops its first screen-side keystrokes. (G5 — Driving Award
— is now live on milestone six and consumes this input path; see docs/march-m6.md.)
Eight — usability: human interface (ADR 0008) One command grammar + grouped help (D1), a real line editor (history, cursor, Ctrl chords, tab completion — D2), one error:/usage:/unknown command shape (D3), a visible-focus window model (D4), an about/welcome/motd/sysinfo support surface (D5), all enforced by gates (D6). Normative contract: docs/decisions/0008-human-interface-guidelines.md 🚧 active — U0 (ADR 0008, claim 8938) ✅ 2026-08-14; U1 help/catalog (claim 3275) ✅ 2026-08-14; U2 shell editing/history (claim 1809, + the latent XHCI interrupt-ring wrap fix) ✅ 2026-08-14; U3 error/usage contract (claim 1511, + the u4 history-width fix the fuzz found) ✅ 2026-08-14. U4–U8 (pointer focus + cursor, window HIG, first-boot experience, sysinfo, persistent settings) are the next cards — per-card tracker docs/march-m8.md.

Resolved loose end: the milestone-one KERNEL.TXT corruption is fixed (ADR 0002 — the loader now places image content at base+0; the write is byte-perfect and gated by zig build run).

Gate status

Every gate below is backed by evidence re-verified 2026-08-07 (full suite re-run on merged main 4702548, artifacts/status-reverify-20260807.txt) and re-run again at HEAD 5160eef on 2026-08-08 (claim 8592 preflight, artifacts/status-preflight-*.txt), and re-run at the newest HEAD 076ddf1 on 2026-08-08 (claim 8073, artifacts/gates-reverify-20260808-076ddf1.txt — all class A gates plus the primary VZ serial gate), and re-run in full at the m1.5-interactive-monitor tag (74a51f3) on 2026-08-09 (claim 7873, artifacts/gates-reverify-20260809-m15-tag.txt — the complete class A set plus the complete class B set: serial takeover, bad-handoff, marker, nvram-console, host-console, live-transcript, live-fs, live-timer, live-reboot, live-exceptions); all greenand re-run again at the newest HEAD 706712c on 2026-08-09 (claim 2233, artifacts/gates-reverify-20260809-706712c.txt — class A 11/11, class B 10/10: serial takeover, bad-handoff kernel_rc=0x2, marker ladder to M2_TXOK!, nvram-console, host-console, live-transcript RX 1/1, live-fs persistence pair 1/1, live-timer 1/1, live-reboot 2/2, live-exceptions 1/1; all green)and re-run again at the newest HEAD a3644cf (PR #53, claim 6420's FAT32 storage driver merged) on 2026-08-09 (claim 0658, artifacts/gates-reverify-20260809-a3644cf.txt + artifacts/classB-chunk{1,2,3}-a3644cf.log — class A 11/11, class B 10/10: serial takeover, bad-handoff kernel_rc=0x2, marker ladder to M2_TXOK!, nvram-console 82 chunks/5027 B, host-console, live-transcript RX 1/1, live-fs persistence pair 1/1, live-timer 1/1, live-reboot 2/2, live-exceptions 1/1; all green); files under artifacts/. The milestone-three uaccess card (claim 6120) re-ran its affected gates at f4b3143 + uaccess on 2026-08-10: the new live-uaccess gate 1/1 (artifacts/m3-uaccess-live.txt), live-svc 1/1 with the payload's three writes (write=3), live-exceptions 1/1, live-userspace 1/1, live-timer 1/1, live-tasks 1/1, live-transcript 1/1, and zig build run (serial takeover) all green; class A re-run green in full — and re-run in full at the milestone-three candidate HEAD 0c119d8 on 2026-08-10 (claim 0707, artifacts/gates-reverify-20260810-m3-closeout.txt + artifacts/classB-chunk{1,2,3,4}-m3-closeout.log — class A 11/11, class B 17/17: serial takeover, bad-handoff, marker, nvram-console, host-console, live-transcript, live-fs, live-timer, live-tasks, live-userspace, live-svc, live-uaccess, live-addrspaces, live-lifecycle, live-exec, live-sleep, live-reboot; all green). The milestone-three close-out archived the completed M1.5/M3 prompt + design docs into docs/archive/ (see the Related docs section). **Milestone-four close-out (claim 2839, 2026-08-11): the complete class A set (fmt, unit tests, test-console, build, image, inspect, swift runner build, context, coordination, coordination tooling, mmu-debt — 11/11) and the complete class B VZ set (the full 28-gate verify-vz aggregate: serial takeover, bad-handoff, marker, nvram-console, host-console, live-transcript, live-fs, live-gfs, live-timer, live-tasks, live-userspace, live-svc, live-uaccess, live-addrspaces, live-lifecycle, live-exec, live-args, live-procs, live-concurrent, live-long-lived, live-kill, live-sleep, live-entropy, live-reboot, live-ipc, live-procs-syscall, live-scale, live-wait — 28/28) re-ran green at the milestone-four candidate HEAD 9d7e4d5 on a clean tree; the milestone is tagged m4-processes. Evidence: artifacts/gates-reverify-20260811-m4-closeout.txt

  • artifacts/m4-closeout-classA-1.log + the per-gate vz-live-* logs. The M4 prompt docs were archived to docs/archive/; the next plan is milestone five, card N1 (virtio-net transport + TX, docs/m5-net-tx-prompt.md).
Gate Command Result Last evidence
Format zig fmt --check boot/src/*.zig kernel/src/*.zig build.zig ✅ pass re-run 2026-08-08 (preflight); re-verified at 076ddf1 (claim 8073)
Guest build zig build ✅ pass re-run 2026-08-08 (preflight); re-verified at 076ddf1 (claim 8073)
Disk image zig build image ✅ pass re-run 2026-08-08 (preflight); re-verified at 076ddf1 (claim 8073)
Binary + image inspect zig build inspect ✅ pass re-run 2026-08-08 (preflight); re-verified at 076ddf1 (claim 8073)
Swift runner build swift build --package-path host/vm-runner ✅ pass re-run 2026-08-08 (preflight); re-verified at 076ddf1 (claim 8073)
Context snapshot zig build context ✅ pass re-run 2026-08-08 (preflight); re-verified at 076ddf1 (claim 8073)
VZ serial gate zig build run PASS 2026-08-08 banner DipshitOS kernel has seized control. + memory-map descriptors=0x… + kernel terminal state in vm-serial.log (claim 1517; artifacts under artifacts/). Re-verified live at 076ddf1 (claim 8073): banner + 27-descriptor map (key=0x2c4) + dipshit> prompt in artifacts/vm-serial.log, runner exit 0. Re-verified live at 706712c (claim 2233): banner + 27-descriptor map (key=0x2d4) + dipshit> prompt, runner exit 0. Re-verified live at a3644cf (claim 0658): banner + 27-descriptor map (key=0x2c4) + dipshit> prompt, runner exit 0. Root cause was the translation start-level mismatch (claims 6460/7896); fixed in production with T0SZ=16 + tlbi vmalle1 at the switch. Historical blocker detail (claims 0013/0018/0020): console is a virtio-pci device (bus 0 D5 0x1af4/0x1043), transport armed pre-exit, first post-switch BAR/common-config read did not return
Live transcript / RX gate bash tools/verify-live-transcript.sh PASS 2026-08-08 host scripted keystrokes reach the kernel end to end through the polled virtio receive queue and the live dipshit> transcript is asserted in vm-serial.log (claim 6684, 3/3 boots; artifacts live-transcript-*)
Live exception-vector gate bash tools/verify-live-exceptions.sh PASS 2026-08-08 VBAR_EL1 vectors installed; dipshit> fault triggers a real synchronous exception (udf) that the handler reports ([EXC] sync from EL1t, ec=0x00 unknown-reason, ESR/FAR/ELR/SPSR) and resumes — shell continues (fault: handled, resumed after faulting instruction → follow-up echo reply), 2/2 boots (claim 9746; artifacts live-exceptions-*)
Live tasks scheduler gate bash tools/verify-live-tasks.sh PASS 2026-08-09 tick-driven round-robin (claim 5275): the timer PPI preempts the shell, the worker advances (report line tasks worker advances=N, N≥1 — only possible after ≥ 2 real context switches), and the shell resumes to run commands (rx-tasks-ok); tasks command reports both tasks; artifacts live-tasks-*
Live EL0/SVC boundary gate bash tools/verify-live-userspace.sh PASS 2026-08-10 claim 8215 regression: two sequenced pings prove return to EL0; the payload waits for a timer-only witness before cooperative yield, and the shell-side evidence follows real timer preemption
Live syscall-table gate bash tools/verify-live-svc.sh PASS 2026-08-10 claim 3594, 1/1 (re-verified under claim 6120 with write=3): three EL0 writes (good line, bad-pointer EFAULT exercise, marker line), timer IRQ before yield/exit; exact single snapshot ping=2, write=3, yield=1, exit=1; non-returning status-7 exit and one post-exit rx-svc-ok reply.
Live uaccess gate bash tools/verify-live-uaccess.sh PASS 2026-08-10 claim 6120, 1/1: EL0 passes an unmapped bad pointer (0x1_2000_0000, above the identity blanket) to sys_write, receives -3/EFAULT, and survives to write uaccess: efault ok n=8; the uaccess monitor command runs a validated copy (valid=1) and a raw copy from an unmapped address that takes a real EL1 data abort, recovered (recovered=1, fault=1, no [EXC] parking), and the shell answers rx-uaccess-ok.
Live ESP exec gate bash tools/verify-live-exec.sh PASS 2026-08-10 claim 6783, 1/1: USER.BIN (a DSK1 flat image built from user/src/main.zig) is on the ESP (the image builder embeds it; ls lists it), exec USER.BIN reads it through the FAT path and replies exec: loaded USER.BIN size=0x83 entry=0x400000 head=0x200080d2c1020010 (the loaded first instructions), and the program executes at EL0 from the loaded page — its sys_write markers (user: hello from the ESP, user: exec ok), two sequenced pings, sys_exit (status 42 → tasks user-exec exited status=42), and the idle reap (tasks user-exec reaped) are all in vm-serial.log, with the shell responsive (rx-exec-ok).
Live blocking-syscalls gate bash tools/verify-live-sleep.sh PASS 2026-08-10 claim 3200, 1/1: the ESP-loaded program yields (sys_yield, slot 2), sleeps 2 scheduler ticks (sys_sleep, slot 4 — blocked, woken by timer-driven wakeup, return 0), writes the user: awake marker after the wake, and exits (status 43); the scheduler's blocked state and the worker's advance lines during the sleep window prove live progress of other tasks; syscalls reports 4 sys_sleep calls=1
Live timer IRQ gate bash tools/verify-live-timer.sh PASS 2026-08-09 Real IRQ delivery observed, 3/3 boots (claim 9187): GICv3 (GICD @ 0x10000000, GICR/active frame @ 0x10010000) + CNTP (24 MHz, GTDT level-triggered PPI 30); each serial log contains timer irq delivered ppi=0x1e irq_ticks=1 and timer heartbeat ticks=5 irq=5 poll=0, with a follow-up shell reply. Claim 7948's platform-blocker conclusion was invalidated by a delivery-blocking guest bug: SGI/PPI MMIO aimed at the RD frame instead of its +0x10000 SGI frame. The audit also corrected shifted MADT GIC IDs and the wrong ICFGR field bit. Artifacts: live-timer-*; Xcode 27 host-surface audit: vz-irq-api-audit.txt
Live reboot/shutdown gate bash tools/verify-live-reboot.sh PASS 2026-08-08 hard gate 6 closed — a real EFI ResetSystem from a live dipshit> shell observed end to end (claim 0527, 4/4 boots): reboot reset the machine (second full takeover + fresh map key in vm-serial.log), shutdown powered it off (runner reports VM state → stopped); artifacts live-reboot-*. The claim-0011 M2_RST! marker write is scanned + reported but is best-effort by design (lost in the teardown race; the machine-level effect is the evidence)
Live virtio-net TX gate bash tools/verify-live-net-tx.sh PASS 2026-08-11 claim 1373, 2/2 phases: the virtio-net transport is live on VZ — DID 0x1041, VER1|MTU|MAC negotiated (feat=0x28/0x1), host-set MAC from the feature path (02:00:00:00:00:01), queues 0/1 size 4, DRIVER_OK through the re-arm (pre-rearm st=0f — no EBS reset on the net device), and the host capture holds the EXACT frames (phase 1: 46-byte known frame byte-for-byte; phase 2: 46+46+1514 — ring reuse + honest truncation); the 29-gate verify-vz aggregate re-ran green (artifacts live-net-tx-*, live-net-tx-vz-sweep.log)
Live virtio-net RX gate bash tools/verify-live-net-rx.sh PASS 2026-08-11 claim 6076, 3/3 phases: the guest arms queue 0 with a fixed BSS buffer (net: rx-armed), the host injects a known frame into the SAME attachment's socket via --net-inject (a serial trigger), the polled used-ring drain delivers it, the MAC filter accepts own + broadcast and drops the rest, net recv prints the exact bytes, and the guest re-sends them (the phase-1 capture is byte-exactly the injected fixture — the round trip). Claim-time observations: the device writes a 12-byte virtio_net_hdr into RX buffers (num_buffers=1) and refuses an RX buffer under 1530 bytes; the used-buffer IRQ is unobserved (drain polled). The 29-gate verify-vz aggregate re-ran green 29/29 (artifacts live-net-rx-*, m5-net-rx-vz-sweep.log)
Live virtio-net ARP gate bash tools/verify-live-net-arp.sh PASS 2026-08-11 claim 7293, 3/3 phases: the guest's ARP layer (kernel/src/arp.zig) sits on the N2 RX seam — phase 1 the guest answers the injected request for its static IP (the 42-byte reply is byte-exact in the host capture, repl=1, net recv observes the request); phase 2 the guest resolves a peer (its broadcast request is byte-exact in the capture and the runner's --net-arp-respond 10.0.0.2 answer lands: 10.0.0.2 -> 02:00:00:00:00:02, learn=1); phase 3 a request for a foreign address is dropped (drop=1, repl=0, still observable via net recv). Claim-time observation: the device delivers/transmits the 42-byte ARP frames unpadded (below the Ethernet 60-byte minimum). The 31-gate verify-vz aggregate re-ran green 31/31 (artifacts live-net-arp-*, m5-arp-vz-sweep.log)
Live virtio-net ICMP gate bash tools/verify-live-net-icmp.sh PASS 2026-08-11 claim 0148, 3/3 phases: the guest's IPv4 layer (kernel/src/ipv4.zig) sits on the N2 RX seam BESIDE the ARP dispatch — phase 1 the guest answers the injected 46-byte echo request for its static IP (the reply is byte-exact in the host capture with the identification + id/seq/payload echoed, repl=1, net recv observes the request at device len 58); phase 2 the guest resolves a peer and pings it (the broadcast ARP request + the 46-byte echo request id/seq 1 are byte-exact in the capture and the runner's --net-icmp-respond 10.0.0.2 answer lands: pong=1 with seq=1 — the echoed sequence is the ping proof); phase 3 an echo request for a foreign address is dropped (drop=1, repl=0, still observable via net recv). No new hardware-contract entry — the 46-byte frames travel unpadded, consistent with the N3 observation. The 32-gate verify-vz aggregate re-ran green 32/32 (artifacts live-net-icmp-*, m5-ipv4-vz-sweep.log)
Live virtio-net UDP gate bash tools/verify-live-net-udp.sh PASS 2026-08-11 claim 8552, 4/4 phases: the guest's UDP layer (kernel/src/udp.zig) sits on the N4 IPv4 seam (protocol-17 dispatch over already-validated frames) — phase 1 LOOPBACK: a send to our OWN IP (10.0.0.1:7000) is delivered directly into the listener's buffer byte-exact (src 7000, dst 7000, len 12, payload 01 02 03 04), rx=1 tx=1 loop=1, and the capture stays EMPTY (no device round trip); phase 2 the host's injected datagram 10.0.0.2:9999 → 10.0.0.1:7000 is delivered byte-exact (net udp recv + the raw frame at device len 58 via net recv), rx=1 drop=0; phase 3 the guest resolves a peer and sends to it (the ARP request + the 46-byte datagram are byte-exact in the capture and the runner's --net-udp-respond 10.0.0.2:9999 answer — the same payload — lands in the listener buffer, rx=1 tx=1); phase 4 a datagram to a closed port (10.0.0.1:9998) is dropped (drop=1, no delivery, no reply, still observable via net recv). Claim-time fix recorded: the pseudo-header zero/protocol word was initially reversed (0x1100 vs 0x0011) — caught by the byte-exact fixtures, fixed, re-run green. No new hardware-contract entry — the 46-byte datagrams travel unpadded, consistent with the N3/N4 observation. The 33-gate verify-vz aggregate re-ran green 33/33 (artifacts live-net-udp-*, m5-udp-vz-sweep.log)
Live UDP-syscall gate bash tools/verify-live-net-udp-syscall.sh PASS 2026-08-12 claim 1384, 4/4 phases: the ADR 0007 slots 9/10/11 driven end to end by UDP.BIN (the first network-syscall user program, loaded by exec) — phase 1 the program's transcript IN ORDER: sys_udp_listen(7000)udp: listen ok; the LOOPBACK send+recv to its OWN IP → udp: loop ping (the 12-byte datagram, byte-exact); the peer send to 10.0.0.2:9999 + poll sys_udp_recv of the host's --net-udp-respond answer → udp: got ping (the cooperative sys_yield between polls — the ring returns to the program and the poll succeeds); the EINVAL mapping from EL0 (unbound-port recv + unresolved-peer send → udp: recv err -1 / udp: send err -1, nothing transmitted); sys_exit(17)procs UDP.BIN exited status=17 / tasks user-exec exited status=17 / tasks user-exec reaped; the capture is byte-exact (the 42-byte ARP request + the 46-byte datagram); phase 2 the observation commands on the SAME kernel state: syscalls rows 0–11 (implemented=12, rows 9/10/11 counted) + net udp/net counters rx=2 tx=2 loop=1 drop=0. Gate-engineering lessons recorded: the expect is keyed on the program's OWN completion markers (udp: got ping / tasks user-exec reaped) — an early expect killed the VM at ~5 s before the ring returned to the program after its yield and a HEALTHY kernel looked hung (switches=5, all tasks ready); the marker greps carry `
Live NAT gate bash tools/verify-live-net-nat.sh PASS 2026-08-12 claim 4678 (milestone five, card N7): outbound connectivity through VZNATNetworkDeviceAttachment live on real VZ — the runner's --net-nat attaches the NAT device (mutually exclusive with --net, OFF by default — the default VM stays byte-identical); NO guest code, the existing stack is driven against the NAT gateway and the gate asserts GUEST-OBSERVED COUNTERS (the capture-file byte-exact shape does not apply through NAT — the card's documented gate-shape change). ONE run, 11/11 assertions: net ip 192.168.64.5 (the OBSERVED subnet), the 42-byte ARP request to the gateway, the 46-byte echo request, pong=1 with seq=1 (the deterministic gateway round trip — no internet), the learned gateway MAC (net arp: 192.168.64.1 is at …), the MAC-under-NAT line (mac=02:00:00:00:00:01 source=feature — the NAT attachment honors the configured MAC), arp=req=1,repl=0,learn=1,drop=1,fail=0, transport status=0x0f, the shell echo, and the runner's net-nat: ENABLED line. The 35-gate verify-vz aggregate re-ran green 35/35 (artifacts live-net-nat-*, m5-net-nat-vz-sweep.log)
Live DHCP gate bash tools/verify-live-net-dhcp.sh PASS 2026-08-12 claim 0351 (milestone five, card N8): the bounded RFC 2131 DHCP client on the N5/N6 UDP layer, live on real VZ in TWO phases. Phase 1 (deterministic file-handle): --net + --net-dhcp-respond 10.0.0.2 — the guest's net dhcp runs the FULL handshake against the host's crafted server: the 286-byte DISCOVER byte-exact in the capture (dst ff*6, src 02:00:00:00:00:01, 0x0800, 68→67, op 1, cookie, option 53 = 1) → OFFER → the 298-byte REQUEST (the same xid, option 53 = 3) → ACK → net: dhcp bound ip=10.0.0.2 mask=255.255.255.0 gw=10.0.0.1 server=10.0.0.2 lease=3600; the report counters discover=1,offer=1,request=1,ack=1,nack=0,timeout=0,mal=0; the host's NET-DHCP OFFER + ACK lines. Phase 2 (real NAT, rides --net-nat): the CLAIM-TIME observation — the VZ NAT attachment serves NO DHCP server on this host (the DISCOVER went out, offer=0, mal=0; honestly recorded in the hardware contract with the saved log under artifacts/live-net-dhcp-nat-explore/, never faked), and the guest is NOT stranded: the static fallback still reaches the NAT gateway (pong=1 seq=1). The 36-gate verify-vz aggregate re-ran green 36/36 (artifacts live-net-dhcp-*, m5-net-dhcp-vz-sweep.log)
Live DHCP lease-lifecycle gate bash tools/verify-live-net-dhcp-renew.sh PASS 2026-08-12 claim 9489 (milestone five, card N9): the RFC 2131 §4.4.5 lease lifecycle live on real VZ — the client ENFORCES the lease it recorded (T1 = lease/2, T2 = lease*7/8, expiry releases the address). TWO runs: Run A (lease 100 s, --script2-delay 55 / --script3-delay 92) — at elapsed ~57 the client RENEWs with a UNICAST REQUEST to the server (byte-assertable in the 1222-B capture: dst 02:00:00:00:00:02, src/dst IP 10.0.0.2, ciaddr 10.0.0.2) and restarts the lease on the ACK; at elapsed ~93-95 it REBINDs with a BROADCAST REQUEST (frame 4: dst ff:ff:ff:ff:ff:ff); the counters renew=1,rebind=1,renewed=2,expired=0. Run B (lease 100 s, delay 106) — net dhcp: lease expired (elapsed=… >= lease=100), the released report (dhcp=idle,ip=0.0.0.0,…,expired=1 — arp.own_ip cleared), and the client RECOVERS: a fresh DISCOVER → BOUND again. The runner's --net-dhcp-respond <ip>:<lease> + --script2/3-delay knobs are flag-gated (defaults unchanged — every pre-N9 gate byte-identical). The 37-gate verify-vz aggregate re-ran green 37/37 (artifacts live-net-dhcp-renew-*, m5-net-dhcp-renew-vz-sweep.log)
Live TCP gate bash tools/verify-live-net-tcp.sh PASS 2026-08-12 claim 7026 (milestone five, card N10): the bounded RFC 793 TCP client live on real VZ in THREE runs. Run A (deterministic file-handle): --net + --net-tcp-respond 10.0.0.2:9999 + --net-arp-respond 10.0.0.2 — the guest's net tcp runs the FULL lifecycle: SYN (54 B, byte-exact in the capture — src 8000 → dst 9999, proto 6, flags 0x02) → the host's SYN-ACK (the FIXED server ISN 0x12345678, ack = the guest's ISN+1) → the handshake ACK (ack 0x12345679) → ESTABLISHED → net tcp send 5 (the data segment 01 02 03 04 05) → the host echoes it (the ACK 0x1234567e) → net tcp recv prints 01 02 03 04 05net tcp close (FIN) → FIN-ACK → the final ACK (0x1234567f) → closed; then a SECOND connect + net tcp reset (a real RST). The counters syn=2,synack=2,ack=4,data_s=1,data_r=1,fin=1,finack=1,rst_s=1,rst_r=0,timedout=0,mal=0; the 533-byte capture's NINE frames are verified by the gate's python walk (the seq/ack chain, the flags, the ports, the MACs, the payload, and EVERY TCP checksum byte-exact). Run B (deterministic black hole): --net + --net-arp-respond ONLY — the host answers ARP but never TCP — the bounded connect timeout: tcp=syn_sent,syn=1,synack=0 → after 31 s net tcp: connect refused (no SYN-ACK after 30s)tcp=idle,peer=0.0.0.0:0,timedout=1. Run C (real NAT, rides --net-nat): the CLAIM-TIME observation — the VZ NAT gateway answers the SYN with a RST (no TCP listener on 192.168.64.1:9999 — connection refused; rst_r=1, tcp=closed, the drive returns the client to idle; honestly recorded in the hardware contract [observed] with the saved logs under artifacts/live-net-tcp-explore/, never faked; if a future host's NAT silently drops instead, the honest timeout path fires — proven by Run B). The 38-gate verify-vz aggregate re-ran green 38/38 (artifacts live-net-tcp-*, m5-net-tcp-vz-sweep.log)
Live TCP retransmission gate bash tools/verify-live-net-tcp-rto.sh PASS 2026-08-12 claim 5357 (milestone five, card N11): the bounded retransmission + retransmit timer live on real VZ in THREE runs. Run A (deterministic file-handle, ARP-responder-only — a black-hole SYN): the idle-loop RTO poll retransmits the pending SYN autonomously — net tcp: syn retransmitted (1/10) / (2/10) — the report reads retx=2,abort=0 (still tcp=syn_sent — the 30 s connect timeout has not expired), and the capture holds the byte-identical SYN frames (the SAME seq/bytes/checksums — a python walk verifies them). Run B (deterministic file-handle + the full responder): the SYN-ACK clears the pending state — retx=0 in the report despite the 7 s wait (past the RTO), no retransmission lines, and the capture holds EXACTLY ONE SYN (the handshake completes — established). Run C (deterministic file-handle + the :handshake responder — SYN-ACK yes, data silent, the data black hole): connect → established → send 5 (never ACKed) → the idle loop retransmits the data TEN times (data retransmitted (1/10)(10/10)) → net tcp: retransmission limit reached (10) — connection aborted → the report releases the connection (tcp=idle,peer=0.0.0.0:0,…,retx=10,abort=1), net tcp reads no connection, and the capture holds the ELEVEN byte-identical data frames (the initial + the 10 retransmissions). The runner's --net-tcp-respond …:handshake mode is flag-gated (default unchanged — every pre-N11 gate byte-identical). The 39-gate verify-vz aggregate re-ran green 39/39 (artifacts live-net-tcp-rto-*, m5-net-tcp-rto-vz-sweep.log)
Live FAT32 storage gate (fs hard gate) bash tools/verify-live-fs.sh PASS 2026-08-09 hard gate 5 closed, upgraded to a real FAT driver (claim 6420, 1/1 pair)ls/cat/write persist through reboot on the disk itself: run A wrote hello world to the ESP's FAT volume via the virtio-blk transport (write-ok, hello.txt [esp] listed, cat reply) and run B — a fresh boot against the same disk image — still listed HELLO.TXT [esp] (the FAT 8.3 short name) and printed the content. The volume lists the loader's per-boot files too (EFI/, KERNEL.BIN, BOOTED.TXT, MEMMAP.TXT, LOADER.TXT). Two hardware discoveries landed in the claim: VZ presents virtio-blk as DID 0x1042 (the spec's modern virtio-blk DID — the transitional scheme maps net 0x1041, blk 0x1042, console 0x1043), and resets the device at ExitBootServices — the queue is re-armed post-MMU (blk_rearm, common-config MMIO writes verified DRIVER_OK). NVRAM variables are no longer the persistence medium; artifacts live-fs-*
Bad-handoff failure gate bash tools/verify-bad-handoff.sh pass artifacts/m2-badhandoff-fix-after.txt: RC.TXTkernel_rc=0x0000000000000002, gate exits 0 (first observed 2026-08-06, fixed shim)
Marker fallback gate (gate work item 3) bash tools/verify-marker.sh pass artifacts/m2-marker-gate.txt (2026-08-07, re-verified artifacts/m2-marker-reverify-20260807.txt): NVRAM ladder M2_ENTRY → … → M2_MAPD! → M2_MMUP! → M2_SERIA → M2_READY — identity-map switch completes and probe/transport are reached (see gate work item 3, claims 0009/0010/0013)
MMU-takeover root cause & fix (claim 0010) bash tools/verify-marker.sh fixed 2026-08-07 ladder now advances M2_MAPD! → M2_MMUP! → M2_SERIA — the identity-map switch completes on VZ for the first time (artifacts/m2-mmu-takeover-gate.txt; see claim 0010)
VZ serial console discovery (claim 0013) pre-exit probe + NVRAM dump discovered 2026-08-07 console = modern virtio-pci (bus 0 D5 VID=0x1af4 DID=0x1043 class=0x078000), ECAM 0x40000000, BAR0 (64-bit) @ 0x100010000, transport decoded + armed pre-exit (SEL=VIRTIO, ladder M2_READY); declared MMIO windows decoded as Apple efivars store + internal debug UART. Gate blocked at the time (post-MMU transport access hung, claims 0018/0020) — resolved by claim 1517 (T0SZ=16 + TLBI at the switch)
NVRAM console channel (claim 0015) bash tools/verify-nvram-console.sh PASS 2026-08-07 first post-exit console bytes from a real VZ run: 69–70 chunks reconstructed from efi-vars.bin — takeover banner, full memory map, probe record, shell banner, and real version/mem/echo/help command output (artifacts/nvram-console-gate.txt). Found + fixed a latent kernel bug on the way (ADR 0005: const function-pointer tables are not relocated by the flat loader — the first vtable dispatch on real hardware faulted; tables now built at runtime in BSS). See Current blocker

Current blocker (canonical — one description, one ordering)

RESOLVED 2026-08-08 (claims 1517 + 6684 + 0527). The post-MMU virtio TX blocker is fixed in production (claim 1517: T0SZ=16 + TLBI at the switch — the start-level mismatch from claims 6460/7896) and the RX path is live (claim 6684: the polled virtio receive queue delivers host keystrokes end to end — bash tools/verify-live-transcript.sh asserts the real dipshit> transcript in vm-serial.log, 3/3 boots) and the live reboot/shutdown observation is done (claim 0527: reboot resets the machine, shutdown powers it off — 4/4 boots via bash tools/verify-live-reboot.sh) and the filesystem gate is closed (claim 6420: ls/cat/write persist through reboot on the real disk via the FAT32 storage driver, verify-live-fs.sh, 1/1 pair). Every M1.5 hard gate now passes (all 7 closed; the last — the deferred filesystem one — closed 2026-08-09 by claim 3475 and upgraded to a real FAT driver by claim 6420). The post-M1.5 allocator and timer interrupt cards are now complete (claims 3972/5162/9187); tasks are next.

Historical blocker (superseded by claim 1517): reliable post-MMU access to the already-discovered virtio-pci console transport (class B) was required before live RX and a real interactive dipshit> session. The console is a modern virtio-pci device (bus 0 D5 0x1af4/0x1043, BAR0 0x100010000, claim 0013); the transport arms pre-exit (M2_READY) and TX works pre-exit (claim 0017) and post-ExitBootServices on the firmware translation (claim 0020 phase B), but hung on the first post-MMU BAR/common-config read after the DipshitOS identity-map install (claims 0018/0020, phase C/D). ExitBootServices itself is exonerated; the MMU switch (B→C) was the transition that destroyed access (claim 0020). Firmware and kernel memory attributes are byte-identical (claim 0021), so the hang was not an attribute mismatch; the no-TLBI safety contract and its validity window were in ADR 0006 (claim 0022; superseded by claim 1517). The NVRAM fallback console (claim 0015) carried post-exit bytes via runtime SetVariable (69–70 chunks, shell + commands observed) but is not the virtio serial pipe; the mock transcript (zig build test-console, class A) is a portable host test, not VZ hardware. Ordering remains explicit: post-MMU virtio TX (done, claim 1517), then virtio RX / live transcript — RX cannot bypass the TX/MMU layer. Claims 6460/7896 characterized the layer: correcting the T0SZ start-level mismatch (25→16) restored end-to-end post-MMU TX in 6/18 boots, and the 4-cell walk-probe matrix proved the residual was stale-TLB interference, not a device hang — cell B (T0SZ=16 + TLBI) completed 9/9, which is exactly what claim 1517 makes production (see docs/gate-inventory.md). Class definitions: docs/gate-inventory.md (class A = portable/CI, class B = Apple-silicon/VZ hardware, class C = interactive, class D = diagnostic); a green CI badge proves class A only.

Re-verified marker/host gates on merged main (2026-08-07): host-console gate ✅ artifacts/m15-host-console-reverify-20260807.txt; marker re-verify ladder M2_ENTRY → … → M2_READY (artifacts/m2-marker-reverify-20260807.txt); bad-handoff re-verify ✅ artifacts/m2-badhandoff-reverify-20260807.txt.

What we directly observe about the serial gate and the bad-handoff fix

From the bad-handoff run before the fix (re-verified 2026-08-06), fresh from artifacts/bad-handoff.img:

  • BOOTED.TXT — written by the loader: observed (loader executed under firmware).
  • LOADER.TXT — written by the loader: observedbase=0x7e4df000 size=0x823e8 entry_offset=0x18, and ram_first8=0xaa0103eaaa0003e9, which decodes to mov x9, x0; mov x10, x1 — the first two instructions of the kernel's naked shim. The image content is at base+0 and the jump lands on the shim as designed.
  • RC.TXTabsent before the fix: the kernel never returned to the loader. vm-serial.log is empty (expected for ConOut; the runner's terminal=true is only the no-marker default).

Bad-handoff root cause (now observed, fixed 2026-08-06): the naked _start shim's bl kernel_main overwrote the link register with the shim's own return address (disassembly of the current kernel ELF: bl 0x3c at shim offset 0x30, so LR = 0x34). The shim's final ret therefore looped 0x34 → 0x38 → 0x34 forever instead of returning to the loader, so the pre-exit return bad_handoff could never reach the loader and RC.TXT was never written. Fix: save the loader's x30 in x20 (callee-saved under AAPCS64, preserved by kernel_main) before the bl and restore it before ret — two instructions in kernel/src/main.zig _start. After the fix: RC.TXT = kernel_rc=0x0000000000000002 and verify-bad-handoff.sh exits 0 (artifacts/m2-badhandoff-fix-after.txt).

The VZ serial gate is a separate, still-open question: with the fix, the bad-handoff VM provably returns through the shim, but every good-path run still produces no serial output and the kernel never returns. Re-run 2026-08-06 21:19 (claim 0002, artifacts/m2-vz-run-20260806.txt): vm-serial.log 0 bytes after a 30 s run; loader evidence intact (BOOTED.TXT exact content, LOADER.TXT base=0x7e4df000 size=0x823e8 entry_offset=0x18, ram_first8=0xaa0103eaaa0003e9 = the shim's first two instructions mov x9,x0; mov x10,x1 — the loader→shim jump is proven); RC.TXT absent (good path, expected — D6).

Historical — how the serial gate's silence was first explained (claim 0009, superseded by 0010/0013)

The ADR 0004 D4 marker fallback was implemented and its first VZ runs ended at M2_MAPD! (claim 0009) — the ladder discriminated the death site as the MMU-takeover window before the serial probe ever ran (artifacts/m2-marker-gate.txt, historical). A diagnostic run with the switch disabled showed M2_MAPD! → M2_MMUP! → M2_SERIA (layout=none halt). Claim 0010 then root-caused and fixed this: the guest implements the ARMv8.1+ TCR_EL1 layout (claim 0010; re-captured by 0021 artifacts/fw-mmu-capture-lines.txt — raw m2-firmware-regs.txt not in this checkout), the identity map now covers undeclared MMIO as Device, and the tlbi vmalle1-forced re-walk that faulted on VZ is dropped (see TLBI bullets in hardware-contract.md and ADR 0006). The ladder now runs M2_MAPD! → M2_MMUP! → M2_SERIA (artifacts/m2-mmu-takeover-gate.txt). That "device absence in the declared windows" reading of M2_SERIA is itself superseded by claim 0013 (declared windows are Apple's efivars store

Also observed (still current): the ADR 0004 D4 memory-dump form is impossible on VZ — guest RAM is not host-mapped (claim 0009).

The device absence is now fully explained (claim 0013, 2026-08-07). The console is not in the declared MMIO windows at all. Pre-exit diagnostics persisted through the NVRAM channel (the probe dump variables DipshitP* in artifacts/efi-vars.bin) decoded the ground truth: 0x01000000..0x01010000 contains Apple's EFI variable-store region (raw bytes spell efivars\0), and 0x20050000..0x20051000 is a PL011-family PrimeCell UART whose DR writes produce zero bytes in vm-serial.log (Apple's internal EFI debug UART). ACPI names no console (no SPCR/DBG2; the DSDT, Apple's own Apple Vz AML, declares only PCI0 + efivars). The VZ serial attachment is a modern virtio-pci console — bus 0 device 5, VID=0x1af4 DID=0x1043 class=0x078000 — found by pre-exit PCI enumeration over ECAM 0x40000000 (MCFG). Its 64-bit BAR0 is firmware-assigned at 0x100010000 (above the 4 GiB identity-map blanket; assignment varies across boots, which is why the fixed-window probe never saw it), and the transport is fully armed pre-exit (SEL=VIRTIO, ladder reaches M2_READY). The remaining wall is post-MMU access to the transport window hangs on VZ — the first post-switch BAR/common-config read does not return (claims 0018/0020; the MMU switch is the killer, not ExitBootServices). Claim 0015 then carried the console bytes over a post-exit-safe channel (the runtime SetVariable NVRAM channel — next paragraph); the open work is reliable post-MMU access to the transport (see Current blocker).

The post-exit-safe channel is now live (claim 0015, 2026-08-07). The NVRAM console channel carries the kernel's console bytes over runtime SetVariable after ExitBootServices (the channel claim 0009 proved alive). bash tools/verify-nvram-console.sh passes: 69–70 chunks reconstructed from efi-vars.bin give the takeover banner, the full 25-descriptor memory map, the probe record, the seam diagnostics, the shell banner, and real command output (version, mem, echo, help) — the first post-exit console evidence from a real VZ run (artifacts/nvram-console-gate.txt, claim 0015). Two findings surfaced:

  1. Latent kernel bug fixed (ADR 0005): the flat loader copies the kernel image to a runtime base with no relocations, so every const function-pointer table in .rodata (vtables, the 14-command registry, string-slice tables) held link-time absolute addresses. The first vtable dispatch on real hardware — claim 0015's shell seam — faulted instantly; host tests never caught it (macOS relocates test binaries). All such tables are now built at runtime in BSS.
  2. The NVRAM store is ~61 KiB writable, not 128 KiB — the probe-dump variable was starving the chunk channel; it is gated off in nvram builds (the console stream carries the same evidence). The 64-chunk cap also truncated the session (the store still had ~47 KiB free); raised to 128.

The virtio-console TX gate (claim 0002, zig build run) was blocked at that time (now passing since claim 1517); claim 0015 is the fallback channel claim 0013 named, and it makes the milestone's console evidence host-observable. The VZ post-exit death window was flaky (claim 0009, re-observed: runs sometimes die at M2_MAPD! or mid map-dump after M2_TXOK!); the gate retries up to 3 boots with fresh stores.

Milestone 1.5 — the call

Do not add more kernel-proper plumbing before making the machine interactive. The milestone-two kernel already owns the machine: it ends UEFI Boot Services, installs its own page tables, probes the MMIO serial candidates (PL011/16550/virtio-MMIO), and drives a polled TX-only console (ADR 0004 — "no interrupts, no FIFO/DMA, no RX path") before entering a terminal WFE loop. That console is exactly enough to serve an interactive monitor — the monitor is simply the loop's payload. No new firmware dependencies, no allocator, no interrupts, no storage drivers.

One immediate blocker, on both ends of the wire: the kernel console has no RX path at all (ADR 0004), and until 2026-08-06 the VM runner's serial attachment sent guest output to a file with a nil host-to-guest input handle (VZFileHandleSerialPortAttachment(fileHandleForReading: nil, ...) in host/vm-runner/Sources/VMRunner/main.swift). The M1.5 host-plumbing slice (steps 4–7, landed 2026-08-06) added a --console mode that wires a real stdin-backed input handle and tees guest output live; the evidence path (zig build run) keeps the nil-input attachment, unchanged. Until keystrokes can actually be read by the guest, the monitor is output-only.

Definition of done — the target screen

DIPSHITOS 0.1
AArch64 firmware-assisted kernel monitor
256 MiB detected
Type 'help' before touching anything expensive.

dipshit> help
about      explain this questionable system
cat        print a file from the ESP
clear      clean up the crime scene
echo       repeat your regrettable decisions
elephant   operational mascot diagnostics
handoff    display boot-to-kernel ABI data
ls         list files on the ESP
mem        summarize the EFI memory map
reboot     restart the machine
shutdown   request power-off
version    display build information
write      write text to a file

dipshit>

Hard gates (acceptance criteria)

  • zig build, zig build image, and the existing regression checks still pass. (The bad-handoff regression gate was failing; its root cause (shim LR clobber) was fixed 2026-08-06 — the gate now passes, see Gate status.)
  • zig build console reaches dipshit> — the post-MMU TX fix (claim 1517) puts the live banner + dipshit> prompt in vm-serial.log on real VZ runs.
  • Host keystrokes reach the kernel (RX path closed end to end) — PASS 2026-08-08 (claim 6684): the polled virtio receive queue delivers host keystrokes; verify-live-transcript.sh drives help/version/mem/echo into a live session and asserts the replies in vm-serial.log (3/3 boots).
  • At least ten commands work (31 commands, host-tested; the registry grew 20 → 21 with claim 5844's pci, → 22 with claim 5275's tasks, → 23 with claim 3594's syscalls, → 24 with claim 6120's uaccess, → 25 with claim 5804's addrspaces, → 26 with claim 6729's spawn, → 27 with claim 6783's exec, → 28 with claim 2665's random, → 29 with claim 3678's mount, → 30 with claim 3848's procs, → 31 with claim 7786's kill; real command output observed post-exit via the NVRAM channel, claim 0015, and live post-MMU via claim 1517).
  • ls, cat, and write persist through reboot — PASS 2026-08-09, upgraded to a real FAT storage driver (claim 6420): claim 3475's pre-exit snapshot + NVRAM persistence (passing 1/1) is replaced by a live FAT32 driver on the ESP (kernel/src/fat.zig — GPT + FAT32 mount/list/read/write with injected sector I/O, 11 host tests) over a virtio-blk transport (kernel/src/virtio_blk.zig — DID 0x1042 on this VZ, the spec's modern virtio-blk DID; queue 4, one request at a time). write now allocates clusters, updates both FAT copies, and writes the directory entry to the disk itself; run A persisted hello world and listed it [esp], and run B — a fresh boot against the same disk image — still lists HELLO.TXT [esp] (the FAT 8.3 short name) and prints the content. Hardware discovery fixed on the way: VZ resets the virtio-blk device at ExitBootServices (its status reads 0 post-exit), so the queue is re-armed post-MMU (blk_rearm, common-config MMIO writes — verified DRIVER_OK + live reads/writes); the NVRAM variable store is no longer the persistence medium. bash tools/verify-live-fs.sh, class B, 1/1 pair. (Claim 3475's other fixes stand: the per-flush TX markers/probe persist are first-flush-only / -Dprobe-var-gated.)
  • A scripted console session passes automatically (asserting in vm-serial.log) — the mock transcript (zig build test-console, class A) passes, and the live vm-serial.log transcript assertion now passes too (bash tools/verify-live-transcript.sh, claim 6684, class B).
  • The VM can reboot or shut down from the shell — PASS 2026-08-08 (claim 0527): a real EFI ResetSystem driven from a live dipshit> shell is observed end to end on VZ — reboot resets the machine (second full takeover, fresh memory-map key in vm-serial.log) and shutdown powers it off (VM state → stopped), 4/4 boots via bash tools/verify-live-reboot.sh (class B). The mechanism itself shipped + unit-proven in claim 0011. (The claim-0011 M2_RST! marker write is best-effort by design and was lost in the teardown race; the machine-level reset/power-off is the evidence.)
  • No allocator, MMU replacement, interrupts, scheduler, or userspace is falsely claimed.

The march tracker (per milestone)

Moved 2026-08-06: the per-step tracker and the best-agent-split tables used to live in this file; agents marking steps collided here with gate and milestone-status edits. They now live in the per-milestone trackers — the active docs/march-m3.md and the archived docs/march-m15.md (M1.5, closed 2026-08-09) — update a step's row there, never here. This file holds milestone-level facts only (position, gates, hard gates) plus pointers.

What comes immediately afterward

Ordering after M1.5 is explicit and enforced by evidence classification (docs/gate-inventory.md):

  1. Reliable post-MMU access to the already-discovered virtio-pci console transport (post-MMU virtio TX, class B). DONE 2026-08-08 (claim 1517) — root cause (translation start-level mismatch + stale-TLB crutch, claims 6460/7896) fixed in production: T0SZ=16 + tlbi vmalle1 at the switch; zig build run passes (banner + memory-map + terminal state in vm-serial.log).
  2. Virtio RX / live transcript (class B live-transcript-rx). DONE 2026-08-08 (claim 6684) — the polled virtio receive queue delivers host keystrokes end to end; bash tools/verify-live-transcript.sh asserts the live dipshit> transcript in vm-serial.log (3/3 boots).
  3. Live reboot/shutdown observation (M1.5 close-out, hard gate 6). DONE 2026-08-08 (claim 0527) — a real EFI ResetSystem from a live dipshit> shell observed end to end (bash tools/verify-live-reboot.sh, 4/4 boots: reboot resets the machine, shutdown powers it off). The last hard gate — the filesystem one — closed 2026-08-09 (claim 3475: ls/cat/write persist through reboot via the pre-exit ESP snapshot + NVRAM-persisted writes, verify-live-fs.sh) and upgraded the same day to a real FAT32 storage driver (claim 6420): write persists to the ESP's FAT volume through a virtio-blk transport, files survive reboot on the disk itself, and the NVRAM persistence medium is gone. All 7 M1.5 hard gates pass; the milestone is tagged m1.5-interactive-monitor (2026-08-09).
  4. A physical page allocator over the captured EFI map. DONE 2026-08-08 (claim 3972) — first-fit bitmap allocator over the captured map's ConventionalMemory (fixed 128 KiB BSS bitmap over the 4 GiB identity-map span), wired post-exit in kernel_main; pages/pages selftest monitor commands; 18 unit tests; live-observed on VZ (total=0xee2b pages across 7 regions; selftest allocates the largest contiguous run and restores the pool). Extended 2026-08-09 (claim 5162): the pool now also covers loader + boot-services regions, with exclusion ranges protecting the live kernel image, stack, handoff page, and captured-map buffer — pages reports excluded=…; 25 alloc/memmap unit tests; full class-A set green at HEAD 19ad92c (artifacts/verify-portable-5162.txt).
  5. Exception vectors (first half of item 5). DONE 2026-08-08 (claim 9746) — VBAR_EL1 vector table + basic synchronous/IRQ handlers installed post-MMU (kernel owns EL1; a pre-exit VBAR write was measured catastrophic on VZ — see the claim), dipshit> fault triggers a real udf that is reported and resumed live (class B gate tools/verify-live-exceptions.sh, 2/2).
  6. GIC + timer interrupts (second half of item 5). DONE 2026-08-09 (claim 9187; supersedes claim 7948's blocker conclusion). The spec-corrected GICv3 driver uses MADT types 0x0B/0x0C/0x0E, targets SGI/PPI registers in the redistributor's +0x10000 SGI frame, selects the boot CPU frame, and programs the GTDT trigger mode. On real VZ, periodic CNTP PPI 30 enters the claim-9746 EL1 IRQ vector, is acknowledged, handled, EOI’d, and re-armed; bash tools/verify-live-timer.sh requires five IRQ ticks and zero poll ticks and passes 3/3 while the shell remains responsive. The old idle-loop timer poll is no longer used in production.
  7. Tasks: tick-driven round-robin scheduler. DONE 2026-08-09 (claim 5275) — the first milestone-three tasks card: two kernel tasks (the shell/main task + a demo worker on its own static BSS stack) preempt at every timer PPI, round-robin, with a minimal save/restore (vector-frame pointer + ELR/SPSR only — the claim-9746 stubs already keep the register file on the stack). dipshit> tasks reports per-task saves/resumes/advances; the worker reports its progress from the shell idle loop (tasks worker advances=N); host tests cover frame construction, round-robin round-trips, and the report machinery. Live gate bash tools/verify-live-tasks.sh PASS 3/3 (worker report line after >= 2 real context switches + responsive shell), and the strict live-timer gate still passes 3/3 under preemption (heartbeat/report lines now snapshot their counters at the event). Live regressions all green: live-exceptions, live-transcript, live-reboot, live-fs. Class-A green. No userspace, no MMU changes — a later card adds userspace.
  8. First EL0t task + SVC boundary. DONE 2026-08-09 (claim 8215, PR #60) — a statically linked EL0 task, page-local user text/stack apertures, x8-selected svc #0, SP_EL0-preserving scheduling, and a strict live userspace gate.
  9. Frozen syscall ABI + dispatch table. DONE 2026-08-10 (claim 3594) — ADR 0007 freezes x8 number, x0–x5 arguments, x0 result, slots 0–3 implemented and 4–63 reserved. The runtime-built table, bounded user-aperture sys_write, cooperative yield, non-returning exit, deterministic counters, and corrected one-shot live SVC gate pass.
  10. uaccess: fault-safe copy-in/copy-out. DONE 2026-08-10 (claim 6120)kernel/src/uaccess.zig adds bounded copy_in/copy_out over the kernel-known EL0 apertures (user text read-only, user stack read-write) with the ADR 0007 EFAULT (-3) contract enforced (out-of-region, overflow, unmapped, permission), plus a masked fault-recovery window: a real EL1 data abort during a copy is latched, ELR advanced past the 4-byte faulting instruction, and the copy returns EFAULT instead of crashing the kernel (an optimizer-reordering hazard that parked on the first live run was fixed with volatile window state). sys_write migrated onto uaccess; the uaccess monitor command proves valid=1 fault=1 recovered=1 on VZ; the EL0 payload passes an unmapped bad pointer, observes -3, and survives to write its marker. New class-B gate bash tools/verify-live-uaccess.sh passes 1/1; verify-live-svc updated to the payload's three writes (calls=3).
  11. Per-task user address spaces. DONE 2026-08-10 (claim 5804) — every task gets its own TTBR0 root; the EL0 task's root is a clone of the kernel identity tree with its text+stack leaves overlaid at their user VAs, so EL0 can reach ONLY those leaves (kernel RAM, firmware, and MMIO are EL1-only AP=0b00 → permission faults), with UXN/PXN (W^X) on every user leaf. VZ TTBR1 fallback: the original kernel-in-TTBR1 KVA-shadow design was measured incompatible on VZ (TTBR1 walks fault at the first descent with 4 KiB tables — the signature of 64 KiB table-address masking — and Normal-WB TTBR1 data accesses abort even with 64 KiB-aligned tables; see ADR 0007 + hardware-contract.md), so the kernel stays identity-mapped in TTBR0 with TTBR1=0 and per-task isolation comes from switching TTBR0 between roots that all carry the EL1-only kernel overlay. The scheduler switches TTBR0 per task; the addrspaces monitor command reports TTBR1=0, T0SZ=16, per-task TTBR0 roots, and the user root's leaf inventory (el0=4, el0_device=0 on VZ). New class-B gate bash tools/verify-live-addrspaces.sh PASS 1/1, all live regressions green (uaccess/svc/userspace/tasks/timer/exceptions/transcript).
  12. User task lifecycle. DONE 2026-08-10 (claim 6729) — the scheduler pool gains an explicit lifecycle: State per slot (free→ready→running→zombie→free), bounded spawn (first free slot, null when full), exit_current → zombie, and the scheduler-owned idle task (always-ready ring fallback; reaps one zombie per iteration so the pool drains without a parent/child relationship). The spawn monitor command exercises a runtime spawn on a dedicated demo stack; tasks reports per-row state= + pool/zombie header; reports are per-task slots so the worker cannot starve the demo's. Load-bearing fix (measured on VZ): the claim-9746 vector frame saved only x0..x17+x30, so a context switch resumed the next task with the preempting task's live callee-saved registers — the shell's mon in x19 was clobbered by the worker's loop counter (≈0x872) and the shell's next console write faulted (esr=0x96000021, far=0x872; a VM-level error when idle was registered). The frame is now 32 slots (x19..x28+x29 saved; shared exc_restore_tail; stubs stay inside their 128-byte slots), making preemption of compiled tasks safe. The addrspaces command also prints user root= directly (the reaper removes the exited user's task row before the gate's post-exit script runs). New class-B gate bash tools/verify-live-lifecycle.sh PASS 1/1; all live regressions green (addrspaces/uaccess/svc/userspace/tasks/timer/exceptions/transcript/fs/reboot).
  13. Load and exec a real user program from the ESP. DONE 2026-08-10 (claim 6783) — a separate EL0 program (user/src/main.zig, naked asm on the fixed syscall ABI) is built into a flat USER.BIN (elf2bin DSK1) and embedded on the ESP by the image builder (mkfat32.py + make-image.sh + zig build user). The new exec [<file>] monitor command reads it through the claim-6420 FAT path into a fixed 4 KiB BSS page, strips the 24-byte header, rebuilds the EL0 user root around the loaded page with claim 5804's build_user_root (proven to work post-install because the kernel stays identity-mapped — @intFromPtr is still physical), and spawns it as an EL0t task — gated on the previous user task being gone (one user program at a time; the lifecycle's closed loop). The loaded program executes at EL0 from the ESP-loaded page: its sys_write markers land in the serial log directly, two sequenced pings prove SVC round-trips from a loaded image, and sys_exit (status 42) + the idle reap close the lifecycle. Two live-measured fixes: the user linker script must discard .eh_frame (the orphan sections landed at VMA 0, so the flat image's entry pointed at CFI bytes), and exec must strip the DSK1 header in place (the user-root leaf masks phys to page granularity, so mapping program+24 mapped the header page — the EL0 task fetched "DSK1" and faulted on the zero pad). New class-B gate bash tools/verify-live-exec.sh PASS 1/1; all shared-seam regressions green (lifecycle/addrspaces/uaccess/svc/userspace/tasks/timer).
  14. Blocking syscalls: sleep/yield/wakeup in the tick scheduler. DONE 2026-08-10 (claim 3200) — a new sys_sleep(ticks) row (slot 4, ADR 0007 amendment) blocks the calling task for N scheduler ticks; the scheduler gains an explicit blocked state with per-task wakeup deadline, a tick counter advancing on every timer PPI, and a timer-driven wake_expired (IRQ context, console-free) that moves expired sleepers back to ready — the same resume path as sys_yield. The ESP-loaded user program is extended with a cooperative yield, a 2-tick sleep (asserting the 0 return), and a post-wake marker before exiting with status 43. The worker's advance lines during the sleep window prove other runnable tasks keep progressing. user_root_in_use now counts blocked tasks too — a sleeping user program still owns the user root. New class-B gate bash tools/verify-live-sleep.sh; all shared-seam regressions green.
  15. Milestone-four close-out (DONE 2026-08-11, claim 2839) — full class A (11/11) + class B (28/28) gate re-run at the candidate HEAD 9d7e4d5; milestone tagged m4-processes (the claim-0707 pattern).
  16. Milestone six, card G1 — virtio-gpu transport + framebuffer (DONE 2026-08-12, claim 6053; prompt docs/m6-gpu-prompt.md). The FIRST NON-BLANK GUEST FRAMEBUFFER is live on VZ: --display runner mode, kernel/src/virtio_gpu.zig, screen/screen fill/screen peek (registry 34→35), gate tools/verify-live-screen.sh PASS 1/1, and the claim-time observations (DID 0x1050, VER1-only, reset at ExitBootServices, B8G8R8X8 + opaque alpha, virtio-gpu 1.2 wire shapes). The full 35-gate verify-vz aggregate re-ran green. What's next: card G2 — framebuffer text rendering. DONE 2026-08-12 (claim 3194): text.zig (the built-in 8x8 bitmap font, putc/puts/cursor/scrollback/clear; 21 host tests against a mock canvas) paints the banner + dipshit> prompt on G1's framebuffer; text/text put/text clear (registry 35→36); gate tools/verify-live-text.sh PASS 1/1 (the decoded capture shows glyphs — green fg over the dark bg, screen no longer monochrome); the full 36-gate verify-vz aggregate re-ran green 36/36. What's next: card G3 — Road Pops, the boot terminal goes graphical. DONE 2026-08-12 (claim 1574): road_pops.zig tees the console — serial shared seam + G2's text layer, drained one present per output batch by the shell idle loop; the boot banner is the shell's own, rendered by the tee; roadpops command (registry 36→37); gate tools/verify-live-roadpops.sh PASS 1/1 (the decoded capture shows banner + live session glyphs below it); the 37-gate verify-vz aggregate re-ran green 37/37. Post-G3 hardening (the SCK switch, 2026-08-12): the pixel gates now REQUIRE the ScreenCaptureKit composited-window evidence (any cacheDisplay fallback fails), and introduced the tools/verify-live-glyphs.sh mirror-tripwire gate. Issue #125 correction (claim 8742, 2026-08-14): the imported font rows are LSB-left, but BOTH kernel rasters read bit 7 as the left pixel; the first decoder repeated that same wrong convention, so its historical PASS was self-consistent, not independent proof of orientation. font8x8.row_pixel now owns the LSB-left contract for the terminal and Driving Award renderers, while the decoder normalizes source rows to screen order and pins the convention with a hard-coded asymmetric C golden. [observed] The repaired gate passed on VZ/ScreenCaptureKit: the terminal decoded forward with 0 unknowns / 604 ink versus 549/595 mirrored; the clock decoded exactly as title clock and body DRIVING AWARD, versus 4/5 and 10/13 unknown glyphs mirrored. The earlier 38/38 aggregate remains historical; its glyph-orientation result is superseded by this claim's targeted live rerun (artifacts/live-glyphs-gate.txt, artifacts/gpu-screen-15s). What's next: milestone seven — input (keyboard + pointer) so keystrokes come from the screen side. [observed] 2026-08-13 (claim 3868): VZ exposes keyboard/pointer as an Apple XHCI USB controller (VID=0x106b DID=0x1a06 CLS=0x0c0330) with USB HID devices behind it — NOT the hypothesized virtio-input (DID 0x1052), which does not exist in the framework. The G4 card was split into its own milestone (I1 XHCI transport → I2 USB enumeration + HID → I3 event FIFO + keycode decode); then G5 Driving Award back in milestone six. Card I1 (claim 4272) DONE 2026-08-13 — the XHCI host-controller transport (MMIO + command/event rings + NO-OP + port status) is live on VZ. Card I2 (claim 4116) DONE 2026-08-13 — USB enumeration + HID is live on VZ: BOTH devices enumerate end to end (port reset → Enable Slot → Address Device → config descriptors → Set Configuration → interrupt-IN armed) — the keyboard (port 9, PID 0x8105, boot protocol, 8-byte reports) and the absolute pointer (port 10, PID 0x8106, non-boot, 10-byte reports); a synthesized host keyDown produced the observed 8-byte report 00 00 04 00 00 00 00 00 (mod 0, HID usage 0x04 = 'a'). Card I3 (claim 6050) DONE 2026-08-13 — the bounded BSS event FIFO + keycode decode feeds Road Pops' line editor: the runner's new --input-string seam (one synthesized NSEvent per keyDown/keyUp; VZ has no keyboard API) typed input\n and the guest's own input command reported events=6 (i,n,p,u,t,Enter) with dropped=0 — the first screen-side keystrokes reach the terminal end to end. Plan docs/march-m7.md. Card G5 (claim 1543) DONE 2026-08-13 — Driving Award, the window manager: kernel/src/driving_award.zig (bounded BSS registry, z-order, focus, hit-test, dirty-rect compositor) makes Road Pops window 0 and a 1 Hz clock overlay window 1; win/win focus/win raise/win hit (registry 39→40); gate tools/verify-live-win.sh PASS 1/1 (two overlapping windows with the right z-order — the decoded capture shows the clock's amber title bar + navy body over the terminal — and a keyboard-typed uname landing in the focused terminal). The 42-gate verify-vz aggregate now includes live-win; the default VM stayed byte-identical. Card G6 (claim 0487) DONE 2026-08-13 — the draw/window syscall seam: the ADR 0007 slots 12/13/14 (sys_win_open/sys_win_fill/ sys_win_present, implemented 12 → 15, then a teardown follow-on adds slot 15 sys_win_close + win close → 16) expose the G5 user-window surface to EL0; WIN.BIN opens a bounded kernel-owned window (id 2..3, fixed BSS back-buffer ≤ 256×192 B8G8R8X8), fills it (dark-blue background + red/cyan/white blocks), presents it, and exits 87; gate tools/verify-live-win-syscall.sh PASS 1/1 (win: windows=3 focused=2 + win[2]: user user rect=64,64,256,192 z=2, syscalls implemented=16 with open=1/fill=4/present=1 + slot 15 sys_win_close registered, and the decoded capture shows the window's own content over the terminal). Teardown follow-on: win close <n>
    • sys_win_close (slot 15) release a user window so the id can be re-opened instead of leaking until reboot (open → close → re-open host-tested in driving_award + syscall, and proven LIVE by WINCLOSE.BIN — the gate tools/verify-live-win-close.sh PASS 1/1: the window gone (windows=2) and the freed slot re-opened as id 2). Ownership follow-on: windows are OWNED by the opening process and AUTO-CLOSE when it exits (close_owner from the scheduler's exit path); fill/present/close are owner-restricted (host-tested cross-process refusals); WIN.BIN's window now vanishes on exit (windows=2, sys_win_close calls=0) and WINLOOP.BIN keeps a window alive for the decoded-capture pixel proof. Milestone six closed — G1–G6 all live; the default VM stayed byte-identical.
  17. Milestone five, card N1 — virtio-net transport + TX (the roadmap's network sketch, whose dependency — "the process/IPC foundations" — is now satisfied). DONE 2026-08-11 (claim 1373). The runner gains a flag-gated --net mode (VZFileHandleNetworkDeviceAttachment capture, fixed host MAC; the default VM stays byte-identical — the full 31-gate verify-vz aggregate re-ran green). Guest kernel/src/virtio_net.zig discovers DID 0x1041 pre-exit, negotiates VER1|MTU|MAC (claim-time finding: the device NEEDS MTU accepted — VER1-only and VER1|MAC are rejected with FEATURES_OK cleared), reads the host-set MAC via the feature path, sets up queues 0/1 (split rings size 4), re-arms post-exit (claim-time finding: the net device does NOT reset at ExitBootServices — st=0f — unlike blk/entropy), and consumes a 12-byte virtio_net_hdr on every TX buffer (observed; the driver prepends a zeroed one). net/netsend monitor commands (registry 32→34); bounded BSS frame staging (no heap). Class-B gate tools/verify-live-net-tx.sh PASS 2/2 — the host receives known frames byte-exact (46-byte fixture, ring reuse, honest 1500-byte truncation). RX (N2), ARP (N3), IPv4 (N4) are the later cards.
  18. Milestone eight, card U0 — human interface guidelines (ADR 0008).DONE 2026-08-14 (claim 8938). The normative interface contract (docs/decisions/0008-human-interface-guidelines.md: D1 command grammar
    • grouped help, D2 prompt/editing, D3 error/usage shapes, D4 window interface, D5 support surface, D6 gate-enforceability) plus the milestone-eight per-card tracker + agent split (docs/march-m8.md: U0–U8 — help/catalog, editing/history, error contract, pointer focus, window HIG, first-boot, sysinfo, persistent settings). Docs only; explicitly NOT an ADR 0007 change and NOT a POSIX/readline promise. Card U1 (claim 3275) DONE 2026-08-14 — the ADR 0008 D1 discovery surface: kernel/src/monitor.zig gains a Category field on all 40 commands + a grouped help catalog in the D1 group order + help <cmd> detail + help <topic> pages (networking, windows, storage, graphics; command-named syscalls/input resolve to their command detail). The byte-identical transcript (shell.zig e2e + tests/transcript-console.txt) regenerated to the grouped listing, and the new live gate tools/verify-live-help.sh PASS 1/1 on VZ (scripted help walk). Card U2 (claim 1809) DONE 2026-08-14 — the ADR 0008 D2 editing surface: a bounded history ring, cursor left/right + Home/End, Ctrl- A/E/K/U/L/C, Delete, and tab completion in kernel/src/lineedit.zig; arrow/Home/End/Delete usages + Ctrl-chord decoding in kernel/src/input.zig; \b/\r honored in kernel/src/text.zig; the registry completer + repaint wired in kernel/src/shell.zig; and the runner's --input-chords seam. Live gate tools/verify-live-editing.sh PASS 1/1 on VZ (scripted chords drive mid-line insert + Up recall; unchanged transcript paths stay byte-identical). En route it root-caused + fixed a latent I3 interrupt- ring wrap OOB in kernel/src/xhci.zig (a phantom stale-report read after the Link-TRB boundary). Card U3 (claim 1511) DONE 2026-08-14 — the ADR 0008 D3 error/usage contract, mechanically enforced: one usage: <cmd> <args> (registry single usage string via print_usage, reused for sub-verb misuse), one error: <actionable> (err_prefix) across every refusal/failure site, one unknown command '<x>' -- try 'help'. The byte-exact misuse transcript now asserts all three shapes, and three deterministic host fuzz tests (tokenizer / arbitrary argv / full editor+shell input path) prove no handler panics. The full-path fuzz found + this card fixed a latent U2 width bug: remember_line's `@min(hist_count, hist_capacity
    • 1)inferred **u4** and overflowed at the 16th distinct history entry (explicitusize` anchor + a fill-past-capacity regression test). Live help + live transcript gates re-run green. U4–U8 are the next cards.

The command layer above is portable; docs/archive/march-m15.md step 15's filesystem-command deferral is superseded 2026-08-09 — first by the pre-exit ESP file window (claim 3475) and then, on the same day, by the real FAT32 storage driver (claim 6420): ls/cat/write now read and write the live ESP's FAT volume through a virtio-blk transport, so files persist on the disk itself and no storage driver remains deferred. The allocator, interrupts, first tasks, EL0 boundary, syscall ABI, uaccess, per-task address spaces, lifecycle, ESP exec, and blocking syscalls are all complete; milestone three is closed 2026-08-10 (tag m3-userspace, claim 0707).

Assumptions & gaps in this plan (checked against the merged main)

  • ADR 0004 now exists and matches the plan's citation. It is the milestone-two kernel-proper ADR; its console is polled TX-only with explicitly "no RX path" — exactly the constraint the plan warned about ("VZ may expose only a virtio console rather than a simple MMIO UART"). The console identity on VZ is observed — a modern virtio-pci device (claim 0013, bus 0 D5 0x1af4/0x1043, BAR 0x100010000); the transport is armed pre-exit and pre-exit TX works (claims 0013/0017). Post-MMU access to that transport was blocked (claims 0018/0020) until claim 1517 fixed the underlying start-level mismatch; post-MMU TX is now observed (banner + memory-map + terminal state in vm-serial.log, claim 1517). The virtio console's register layout is [observed] for the driven queues — queue 1 TX (claim 1517) and queue 0 RX (claim 6684, live keystrokes end to end) — see docs/hardware-contract.md.
  • Runner serial input was nil; it is now a real handle in --console mode. The evidence path (zig build run) still uses VZFileHandleSerialPortAttachment(fileHandleForReading: nil, ...) unchanged; the M1.5 --console mode (landed 2026-08-06) wires a stdin pipe as fileHandleForReading and forwards host bytes into it (evidence: artifacts/m15-host-console-gate.txt).
  • Output observation: evidence path still file-polls; console mode streams. zig build run still re-reads the serial log (Data(contentsOf:)) on a timer — unchanged, evidence semantics intact. The M1.5 --console mode uses a pipe-based duplex attachment and tees guest output live to the terminal and the log (no full-log reloads).
  • "256 MiB detected" matches the runner's configured memorySize = 256 * 1024 * 1024 (unchanged on merged main); mem should derive it from the captured map, not hardcode it.
  • The kernel is post-Boot-Services and never returns. ExitBootServices is called (ADR 0004), x3 is the handoff v2 struct (not the ESP root), and the kernel ends in a WFE loop. Consequences baked into the steps above: no UEFI Serial I/O protocol probe, no GetMemoryMap, no Simple File System — the monitor is the terminal loop's payload.
  • VZ firmware quirks still apply: ConOut is not routed to the virtio serial port or framebuffer, but the kernel drives the virtio console itself — post-MMU virtio TX is now reliable (claim 1517, zig build run passes; MMU-takeover, device identity, and post-MMU TX are [observed] per claims 0010/0013/0020/0021/1517, and the RX-side register layout is [observed] for the receive queue (claim 6684); see hardware-contract.md). Transcript tests: zig build test-console (class A mock) gates on bytes the shell actually emitted; the live vm-serial.log assertion is the separate class-B gate (live-transcript-rx, claim 6684 — bash tools/verify-live-transcript.sh passes: live RX observed end to end, re-verified at 4ca9fb4 by claim 7392) and is not proven by mock or NVRAM bytes.

Multiagent coordination

This repo is developed by multiple agents and humans, sometimes on the same day (e.g. PR #8's M1.5 tracker and PR #10's gate evidence landed within hours of each other and collided; PR #12/#13 collided again on the same changelog section). The rules below make that safe. They are binding (mirrored in AGENTS.md).

Rules

  1. Claim before you start. Any non-trivial work gets a claim file in docs/claims/ and a log entry in docs/logs/ before code is written. Unclaimed work is fair game; claimed work is not.
  2. One editor per file at a time. If two agents need the same file, the second waits, or merges through the integration branch — never both edit kernel/src/main.zig (or this file's tracked sections) simultaneously.
  3. Append-only logs, one per branch. The changelog is split by branch under docs/logs/<branch>.md so parallel appends cannot collide. Append-only: never rewrite or delete an entry. Corrections are new entries that reference the old one.
  4. Update on completion (and on blockers). Flip your claim file's status and append a log entry when done; append one when blocked so the next agent doesn't repeat the attempt.
  5. Own your evidence. Every entry cites artifacts/ files. No observed claim without a saved log.
  6. Doc edits go through this file. Status prose lives here; other docs link to it. If you must touch README.md/roadmap.md/testing.md, prefer pointer-level changes and put the substance here.
  7. Never hand-edit a generated index. The claim and log index tables in docs/claims/README.md / docs/logs/README.md are generated from the claim/log files by tools/status/refresh-indexes.sh — create your file, run the script, done. tools/verify-coordination.sh (just verify-coordination, also CI) fails if the indexes drift from the files, so a stale hand-edit cannot slip through a merge.

Active claims

How to claim: copy docs/claims/TEMPLATE.md to docs/claims/<NNNN>-<slug>.md, fill it in, set Status to 🔄 <branch> before starting work, then run bash tools/status/refresh-indexes.sh — the claim and log index tables are generated from the files, so claiming never edits a shared table and never edits this file. Flip your claim file to (evidence) or (note why) on completion and re-run the script. Unclaimed () claims are fair game; 🔄/ claims are not. The canonical index with status is docs/claims/README.md; this file holds no claims table, so parallel claims never touch the same lines here.

Changelog (append-only, per branch)

Moved 2026-08-06: the changelog used to live in this file; every agent appended here and parallel work collided (PR #8/#10, then PR #12/#13). It is now sharded by branch under docs/logs/ — each branch owns its own append-only log, so cross-branch merges never touch the same lines. All entries — including the final two stragglers, migrated verbatim to docs/logs/agent-buffy-m15-commands.md on 2026-08-06 — live in the per-branch logs; this file holds no changelog entries, so there is nothing here for parallel agents to collide on. See the log index for the format and each branch's file.

Immediate gate work (prerequisites for M1.5)

Ordered; each has a prompt doc and a gate. Status lives in the claim files (canonical index: docs/claims/README.md) — this section is pointer-level only, so a gate passing never needs an edit here.

  1. Root-cause the failing bad-handoff gatedocs/m2-bad-handoff-fix-prompt.md. The kernel must return 0x2 to the loader on a bad magic; it does not. This unblocks M1.5 hard gate 1 and possibly the serial gate too. Gate: bash tools/verify-bad-handoff.sh exits 0 with RC.TXTkernel_rc=0x2; good path unregressed. Status: see 0001-bad-handoff-gate — ✅ fixed 2026-08-06 (root cause: shim LR clobber; evidence in the claim and docs/logs/agent-buffy-m2-badhandoff-fix.md). The serial gate (item 2) no longer shares that suspect.
  2. Run the VZ serial/MMU gatedocs/m2-vz-serial-gate-prompt.md (M1.5 march step 8's "confirm the serial console", docs/archive/march-m15.md). Gate: exact banner DipshitOS kernel has seized control., memory-map descriptors=0x..., and kernel terminal state in vm-serial.log; then flip matching [inferred] → [observed] entries in docs/hardware-contract.md. Status: see 0002-vz-serial-gate — ⛔ blocked (historical) → PASS 2026-08-08 (claim 1517): the gate (zig build run) now exits 0 with the exact banner, memory-map descriptors=0x…, and kernel terminal state in vm-serial.log. Root cause of the historical block (virtio TX hangs post-MMU) was the translation start-level mismatch; fixed in production with T0SZ=16 + tlbi vmalle1 at the switch (claims 6460/7896/1517). The post-exit-safe fallback (claim 0015, bash tools/verify-nvram-console.sh) remains as the NVRAM channel for nvram-console builds.
  3. If no usable serial device exists on VZ, implement the ADR 0004 D4 fixed-memory-marker fallback (host-side dump of the kernel's BSS takeover_marker). Gate: saved host-side dump matching the M2_* markers. Status: ✅ done 2026-08-07 — see 0009-m2-marker-fallback and artifacts/m2-marker-gate.txt. The gate passes with the NVRAM ladder form (the memory-dump form is impossible on VZ — guest RAM is not host-mapped, observed), and the ladder discriminated the serial gate: every run ended at M2_MAPD! — the death was in the MMU-takeover window. That death is now root-caused and fixed by claim 0010 (see the gate table): the ladder advances M2_MAPD! → M2_MMUP! → M2_SERIA, the switch completes, and the probe runs to completion finding no usable device in the declared windows (that reading is superseded by claim 0013 — the real console is a virtio-pci device outside them, see the gate table). See claim 0009 for the original ladder and claim 0010 for the root cause and fix.

Housekeeping conventions (keep the project nice as it evolves)

  • This file is the single source of truth for status and coordination. Update the moment a gate passes, fails, or a milestone completes; claim work before starting (claim file in docs/claims/); append to your branch's log under docs/logs/; regenerate the indexes with bash tools/status/refresh-indexes.sh after creating either. Run bash tools/verify-coordination.sh before opening a PR.
  • Evidence lives under artifacts/ (gitignored, except .gitkeep). Every gate claim names its evidence file and date. No evidence, no "observed".
  • Facts vs. inference: hypotheses are marked (inferred); hardware tags flip only with matching saved logs (AGENTS.md evidence rules).
  • Branch hygiene: feature work on agent/... branches, PRs against main (ADR 0003, docs/branch-protection.md); M1.5 work merges through the integration branch.
  • OS junk: .DS_Store files are gitignored; delete them when noticed (find . -name .DS_Store -not -path './.git/*' -delete).

Related docs

  • roadmap.md — milestone planning (the "where we're going"), plus the maintainer's wishlist / hope chest (destinations, not commitments) at the end.
  • archive/march-m15.md — archived M1.5 per-step tracker and best-agent split (milestone closed 2026-08-09; the active tracker is march-m3.md).
  • march-m4.md — milestone-four per-card tracker and best-agent split (cards 1 + 2 + 3 + 3a + 3b landed 2026-08-10 — entropy/CSPRNG + ASLR (claims 2665/3693), the general non-ESP filesystem (claim 3678), the process abstraction (claim 3848, procs), the concurrent-processes follow-on (claim 0826, two live user processes), and the long-lived-process follow-on 2 (claim 4613, a never-exiting COUNTER.BIN among live peers); network sketched as ⬜).
  • march-m6.md — milestone-six per-card tracker (graphics: the Driving Award window manager + Road Pops terminal, sketched 2026-08-12; not committed).
  • march-m7.md — milestone-seven per-card tracker (input: XHCI + USB HID + keycode decode).
  • march-m8.md — milestone-eight per-card tracker (usability: ADR 0008 + the U0–U8 ladder).
  • testing.md — the verification sequence and evidence policy.
  • logs/README.md — per-branch append-only changelog index (the sharded changelog).
  • claims/README.md — per-claim files index (the sharded claims table, generated).
  • ../tools/status/ — index generator (refresh-indexes.sh) and the coordination gate (verify-coordination.sh).
  • hardware-contract.md — hardware assumptions, [observed]/[inferred].
  • architecture.md — components and data flow.
  • archive/m2-bad-handoff-fix-prompt.md — archived prompt: fix the failing failure-path gate (now passing; root cause was the shim LR clobber).
  • archive/m2-vz-serial-gate-prompt.md — archived prompt: run the VZ serial/MMU gate.
  • archive/m15-host-plumbing-prompt.md — archived prompt (agent A): duplex serial attachment, teeing, terminal safety, zig build console.
  • archive/m15-commands-prompt.md — archived prompt (agent C): command registry, identity/memory/utility/control commands, personality (mock-console based).
  • decisions/ — ADRs 0001–0008 (binding: 0004 kernel proper, 0005 runtime-built function tables, 0006 MMU debt boundary, 0007 syscall ABI, 0008 human interface guidelines).
  • archive/ — archived one-shot prompts and frozen designs from completed milestones (M2 kernel proper, M1.5 shell/commands + T0SZ experiment + tracker, M3 syscall ABI / march tracker / ragshit dogfood / runner scripted input).
  • ../AGENTS.md — project rules (now including the multiagent coordination rules).