# Work evidence

Generated by `scripts/render_progress.py`; do not edit. `progress.html` lists only what is not yet implemented: for every pending item the *remaining* work. This file keeps the rest: the full evidence of each pending (partially implemented) item, and the completion record of every closed one.

## Pending and partially implemented

### C104 — NeperOS stage 2: the kernel as an AVF guest on a Pixel (crosvm bring-up) (75%)

Opened by D2143 when C103 closed D2119 stage 1. Acceptance (D2119 stage 2): the same microkernel boots as an Android Virtualization Framework guest that crosvm starts with the Linux arm64 boot protocol -- device tree in x0, GICv3, PSCI 1.0, an ns16550 serial console, and virtio console, block and vsock over PCI -- first under crosvm, then on a retail Pixel via `adb shell vm run` as a non-protected VM. Device addresses are read from the device tree, never hard-coded; the virtio-pci transport already serves both. Done (D2144): the ns16550/8250 console -- neperos/src/ns16550.e drives the 8250 (THR at 0, LSR at 5 bit 5), the kernel picks it vs PL011 from the stdout uart node's `compatible` (ns16550a for crosvm, arm,pl011 for virt), base and reg-shift from the device tree; console_write and the console server's device_write dispatch by a boot-set flag. Written to crosvm's actual source (aarch64/src/fdt.rs: compatible ns16550a, reg=<addr size>, no reg-shift => shift 0) and regression-verified under QEMU virt (the tree selects PL011, all stage-1 marks pass, ns16550 path inert). Also extracted crosvm's aarch64 memory map from source (RAM 0x80000000, GIC/PCI bases). BLOCKER confirmed (D2144): crosvm is built and runs in this WSL but is KVM-only with no CPU emulation, and the host is x86-64, so it cannot run the aarch64 kernel (rejected as a bad bzImage). Verifying the crosvm/AVF boot -- and the remaining pieces, a virtio-vsock driver and the crosvm memory-map boot -- needs an aarch64 host (a Pixel via adb, or an aarch64 Linux box with KVM); surfaced to the user as a resource decision. Advanced (D2145): the EL0 user window moved to the top of the 39-bit space (index 511, VA 0x7FC0000000) so it no longer collides with crosvm's RAM at 0x80000000, which would otherwise have unmapped the kernel from every user space on the first trap; QEMU-verified -- kernel boots, every EL0 server runs, isolation holds (thread W faults at 0x7FC0040000, X at kernel RAM 0x40000000, Q at ECAM 0x4010000000). The chosen aarch64 host is an AWS Graviton bare-metal instance (only *.metal exposes /dev/kvm for crosvm's KVM backend); the account's configured AWS credentials are invalid and await refresh. The kernel image already carries a valid arm64 Image header. VERIFIED ON REAL HARDWARE (D2146, AWS a1.metal Graviton bare-metal with /dev/kvm): the kernel boots under crosvm/KVM, reads crosvm's DTB (RAM 0x80000000, GICv3, ns16550 at 0x3f8), turns the MMU on and runs the whole EL0/capability suite -- D2145 confirmed, thread W faults at the relocated window 0x7FC0040000. Two crosvm-vs-QEMU gaps found and fixed: crosvm's PCI host is CAM (pci-host-cam-generic, shifts bus<<16/slot<<11/fn<<8) not ECAM, now detected by compatible with a cam flag in pci.Host; and a virtio device's BAR is the one its capabilities name (BAR0 on crosvm, pre-assigned; BAR4 on QEMU, guest-assigned), now discovered and mapped at its real size instead of a hard-coded BAR4/64KB. All three drivers then run under crosvm: entropy returns 8 bytes, block reads/writes sector 0, console writes a virtio-console port; QEMU's ECAM path unchanged (stage-1 boot still green). D2147 then closed the last crosvm functional gap: the EL0 page mappings were global (missing the nG bit), so on a real Cortex-A72 (not QEMU's interpreter) a thread's USER_BASE TLB entry served another thread after the ASID-only context switch, making the console-server client read a neighbour's 0xCD poison and a round-printer re-run. Marking the EL0 leaf descriptors non-global fixed it; the WHOLE stage-2 demo now runs clean under crosvm/KVM on AWS a1.metal -- all three virtio drivers, the capability/isolation threads, `console server up` over the P->K server, `all threads done` and a PSCI power-off with exit 0 -- and QEMU's stage-1 boot is byte-unchanged. D2149 added the virtio-vsock driver (EL0 server T): vsock_connect sets up the three queues (rx/tx/event), reads the guest CID from device config (passed via a new aux slot 5), transmits a STREAM REQUEST to host CID 2, and reads the reply. Verified on AWS a1.metal under crosvm `--vsock cid=3` over /dev/vhost-vsock -- no listener gave op 3 (RST), a Python AF_VSOCK listener on port 1234 gave op 2 (RESPONSE) with the host logging the accept from (3, 1024), a full round trip. QEMU has no vsock device so T is skipped and stage 1 is unchanged. The whole crosvm device list (console, block, vsock over PCI) is now done. Remaining before score 1: the same kernel on a retail Pixel via `adb shell vm run`. NeperOS stages 3 (bare-metal Pixel 6) and 4 follow (D2119).

### C185 — macOS file and protocol associations, Finder-opened files and URLs (small bundles, application delegate) (90%)

Built and verified 2026-10-25 (D5217): shell.associate_file/associate_protocol write a bundle under ~/Library/Application Support/Neper/Associations (Info.plist with CFBundleDocumentTypes or CFBundleURLTypes, a copy of the program as its executable), register it with lsregister -f and make it the default handler (LSSetDefaultRoleHandlerForContentType / LSSetDefaultHandlerForURLScheme); dissociate removes it. The shell target is the NSApp delegate and the GURL Apple event handler; application:openURLs: (file URLs become File activations by path) and application:openFiles: feed activation_poll. tests/macos/probe/open_events.e: open on a file of the registered type and on a registered URL start the registered copy, which receives both and the parent reads them back, on aarch64 and x64; ui_activation passes with associations on; the corpus is 1105 pass. Open: a double-click in Finder and a link in a browser are what a person does and are untested (C192), and the bundle holds a copy of the program, so it is stale after the program is rebuilt (register again). Done when a real Finder open is checked.

### C186 — macOS permissions: camera, microphone and location status and request (80%)

Built 2026-10-25 (D5218): permission_status reads AVCaptureDevice authorizationStatusForMediaType (camera, microphone) and CLLocationManager authorizationStatus (location); a status that is not decided or is restricted is Unavailable because shell.Permission has no not-determined state. permission_request asks for the camera and microphone through AVCaptureDevice requestAccessForMediaType with a global Objective-C block (isa from dlsym _NSConcreteGlobalBlock, BLOCK_IS_GLOBAL, an @cc invoke), only when a capture device exists, and waits for the answer (up to five minutes). tests/macos/probe/permissions.e on the runners: camera unavailable, microphone granted, location unavailable, requests return at once, no crash; ui_permissions passes and the corpus is 1105. D5901: shell.Permission has NotDetermined on every host (macOS answers it) and the location request is built (requestWhenInUseAuthorization, then the status polled for a minute); the runners' answers did not change. Open: a real prompt on a Mac, for the camera and the location, which only a person can answer (C192). Done when those are checked.

### C187 — macOS biometrics (LocalAuthentication) and the photo picker (PHPicker) (50%)

Built 2026-10-25 (D5220): biometrics through LocalAuthentication, capabilities().biometrics is LAContext canEvaluatePolicy for Touch ID asked at every call (true only where enrolled), permission_status(Biometric) is Granted there, and biometric_verify shows the system sheet through evaluatePolicy:localizedReason:reply: with a hand-built global block and waits up to a minute; without biometrics it answers Unsupported. The photo picker is the open panel narrowed to image extensions (png, jpg, jpeg, gif, heic, tiff, bmp, webp), several files on request; PHPicker (the Photos library) is a SwiftUI view this library cannot present. ui_permissions now follows what the host offers (the fixture used to require biometrics to be off everywhere). tests/macos/probe/biometrics_photos.e on the runners: no biometrics, verify is Unsupported, the picker is shown and dismissed (Cancelled); the corpus is 1105. Open: a real Touch ID sheet and a confirmed photo selection need a person and a Mac with Touch ID (C192); Photos-library access (PHPicker) is not done. Done when those are checked.

### C188 — macOS print dialogs: NSPrintPanel and the page setup panel over the PDF printer (70%)

Built 2026-10-25 (D5219): print_dialog runs NSPrintPanel modally over a copy of the shared NSPrintInfo with the page range preset to the caller's minimum and maximum, copies and range shown, and returns a Printer (the virtual PDF printer of D5212) carrying the chosen range and copies; page_setup_dialog runs NSPageLayout and returns paper and margins in hundredths of a millimetre (points converted). tests/macos/probe/print_dialogs.e shows both on the runners and dismisses them from the run loop: both answer Cancelled on aarch64 and x64, the screenshot shows the print panel with range 1 to 9; ui_print passes and the corpus is 1105. Open: a confirmed OK (range, copies and the paper and margin values read back) needs a person (C192); a printer other than PDF picked in the panel is ignored, so real printing (NSPrintOperation drawing into a view) is still a design of its own. Done when a confirmed dialog is checked and the real-printer question is decided.

### C189 — macOS notices through UNUserNotificationCenter: removal, replacement and actions (40%)

Built 2026-10-25 (D5221), the center path unverified: for a program with a bundle identifier (shell.bundled()), notice_publish and notice_update ask UNUserNotificationCenter for alert and sound authorization once (requestAuthorizationWithOptions with a hand-built global block, waiting up to a minute) and post a request whose identifier is neper-<id> (the same id again replaces it); notice_remove removes the delivered and pending request; the capability notice_remove is true once the center has authorized the program. A program with no bundle, or one that was not authorized, keeps osascript banners and Unsupported removal. tests/macos/probe/un_notices.e on the runners (a registered association bundle started with open): bundled detection works and the program runs through publish, count, remove, count and ends, but the runner never authorizes the center, so the banner went through osascript, the delivered count stayed 0 and removal was refused; the corpus is 1105. Open: the center path itself (post, replace, remove, getDelivered) has never run, because nothing here can answer the authorization prompt (C192); action buttons (UNNotificationAction categories and a delegate for responses) are not built. Done when a real authorized run posts, replaces and removes, and actions are decided.

### C190 — macOS window system: accessibility, input methods, close veto, live resize, Retina (75%)

Done 2026-10-25 and 2026-10-26 (live resize, D5856: os.window_on_resize registers a handler the window delegate's windowDidResize: calls from AppKit's tracking loop with the new pixel size; macos_window_resize on aarch64 and x64 resizes a window from code, which takes the same path; Unsupported on the other hosts): the close button is a request answered through a window delegate (D5222, macos_window_close); the published accessibility tree is NSAccessibilityElements under the content view (D5223, macos_accessibility); input methods commit text (D5229, macos_text_input). The content view's class (NeperTextView, made at run time over the view's own class) answers the text input protocol: insertText:replacementRange: turns committed text, from an NSString or an NSAttributedString, into Text events; setMarkedText, unmarkText, hasMarkedText, markedRange and selectedRange hold a composition's state (marked text is not shown, since a window event has no preedit kind: that is an API change for every host); firstRectForCharacterRange answers a point in the window's top left for the candidate window; doCommandBySelector: is ignored; the view accepts first responder, so the window has an input context. A key with an input method selected (its source id has "inputmethod" in it) goes through interpretKeyEvents:, a plain layout's key keeps its own characters as before (a synthetic key event does not come back from the input context synchronously, so the layout path stays direct). macos_text_input calls the input method's methods by hand: an accented letter and a kana become Text events, marked text produces none, committing clears the mark; aarch64 and x64, corpus 1109. Not done: a real input method composing Japanese, Chinese or Korean and its candidate window's place (C192); preedit display; focus, set-value and selection requests, tables, relations and live regions in the accessibility elements, and a real VoiceOver reading the tree (C192); native-resolution checks on a real Retina display (C192). A Retina scale change between displays needs no delegate method: every poll re-reads backingScaleFactor and the content size in pixels, so moving a window to a display of another scale shows up as a Resize with the new pixel size, and window_metrics reports the new scale_percent. Still to see on a real Mac: a drag of an edge by a person repainting smoothly through the handler.

### C191 — macOS application bundles and distribution: a bundle command, icon, code signing, notarization (75%)

Built 2026-10-25 (D5224) and extended 2026-10-26 (D5855): scripts/macos-bundle.sh, run on a Mac, makes NAME.app from a program built for macOS: Contents/Info.plist (bundle id, name, version, NSHighResolutionCapable, LSUIElement with --agent, camera, microphone and location usage descriptions, URL schemes and document extensions on request), Contents/MacOS/NAME, Contents/Resources/NAME.icns from a png (sips and iconutil), an ad-hoc signature verified with codesign --verify --deep --strict (or --sign IDENTITY with the hardened runtime), NAME.zip (ditto) with --zip and NAME.dmg (hdiutil, verified) with --dmg. The macos-corpus job runs it on os_poller with an icon and checks plutil, the bundle id, the URL scheme and extension keys, the zip, the dmg and that the program inside the bundle runs, on aarch64 and x64 (BUNDLE PASS). D5876: --entitlements and --notarize PROFILE (notarytool submit --wait, staple, spctl) are written and unrun. Not done: running a Developer ID signature and notarization, which need an Apple developer identity this repository does not have; a neper command that calls the script; Info.plist entitlements. Done when a notarized bundle has been built and opened on a clean Mac.

### C192 — macOS verification on real hardware: what the CI runners cannot do (20%)

The checklist is a program, written 2026-10-25 (D5228) and compiled for both architectures but never run: tests/macos/manual/main.e. Build it on the Mac (neper-self emit-executable tests/macos/manual/main.e . aarch64 macos manual; x64 on an Intel Mac) and run ./manual from a Terminal: it goes through one check at a time, says what to do, waits where a person is needed, and writes PASS, FAIL or skipped lines to ~/neper-manual-results.txt. It covers: the window's Retina scale, a menu-bar icon's left and right click, a pop-up menu choice, a global shortcut press (Control-Option-Shift-F12), the Open panel with two files and the Save panel's name and .txt, a drop from Finder, the clipboard in TextEdit, a notice banner, a Dock menu task and the 50% badge, Finder starting a program for an associated file, the print panel's range and copies, the camera permission, Touch ID where enrolled, the screen capture size, and VoiceOver reading a published tree and pressing its button. Not covered by it (a program cannot drive them): a real pointer drag out of a window into Finder, a notarized bundle opened on a clean Mac (C191), live resize while dragging an edge and IME composition (C190), a Metal or MoltenVK device run (C193). Done when it has been run on an Apple-silicon Mac and an Intel Mac and its results are recorded here.

### C193 — macOS GPU: a Metal backend for e.gpu (the Vulkan fixtures cannot run on a Mac) (95%)

Phase 1 done 2026-10-25 (D5231): e.gpu.metal, the runtime alone. Phase 2 2026-10-26: src/msl.e, the MSL emitter (D5838; kernel as a switch state machine over heap offsets that reconverges by lowest block, precise::divide/sqrt, fast math off, D5840 32-bit relaxed atomics, D5852 subgroups) and e.gpu's Metal backend (D5839): on a macOS target a kernel's K$spirv carries MSL, Backend.Metal opens a device with a 256 MiB shared heap, buffers are heap ranges, launch_metal runs the SPIR-V launch ABI over it, faults come back through the fault block. Verified on Metal on aarch64 and x64: macos_metal_emitted, macos_metal_exact, macos_gpu_metal, macos_metal_atomics, macos_metal_subgroup (every word equal to the CPU backend's); the emitter's saxpy, loops and exact float are pinned in tests/conformance/msl; the full macOS corpus passes (1130/1130 on both). D5853: a heap larger than 256 MiB read back wrong on the runners. D5892: up to four launches in flight with their own fault blocks (the CPU queues ahead of the GPU; the GPU still runs them in order). D5878: up to four 256 MiB heaps, about 1 GiB of buffers (a single buffer still under 256 MiB). D5875: gpu.launch on Metal commits without waiting (the next call into the device finishes it and reports the fault), so the CPU can work while the GPU runs. Remaining: stronger atomic orders (Metal 3.1 has no fence), 64-bit atomics and subgroup operations on 64-bit values, switch and helper calls (SPIR-V has neither), the Windows and Linux suites for the shared compiler change.

### C194 — macOS corpus: the fixtures that are only reported (extern_many, freestanding, os_syscall, x_tds_integrated, gpu_*) (70%)

Done 2026-10-25 (D5225): the Mac corpus asserts every fixture that can run on a Mac (1108 pass, 0 fail, 0 info) and skips seven with the reason a Mac has by nature, as SKIP lines counted apart in the TOTAL: extern_many (four glibc extensions libSystem lacks, then it reads its own ELF header), freestanding and os_syscall (an ELF image, Linux system call numbers), gpu_vulkan_raw and gpu_fault_unchecked (Vulkan, which a Mac does not have; a Metal backend is C193), x_tds_integrated (SSPI, Windows), net_ssh (driven by the workflow's SSH step, reported as its SSH line). gpu_reshape is now asserted at 50, the sum its own comment gives. Open: Mac counterparts of the ELF and system-call fixtures (a Mach-O header check and BSD system call numbers) would turn three skips into asserted tests; ui_collections4_v2 failed once on x64 under Rosetta (exit 190, a gesture timing check at 50 ms after a release) and passed on rerun, so it is timing-sensitive on a loaded runner. Done when the three Mac counterparts exist or are decided against.

### C195 — macOS shell polish: drag files and images out, session restore, Dock overlay image (70%)

Built 2026-10-25 (D5226): drag_start now drags files (each path as an NSURL file URL, one dragging item per file, up to 16) and images (TIFF data under public.tiff) as well as text and bytes; taskbar_overlay draws the overlay into the lower right quarter of the program's own Dock icon (the first icon is kept so a second overlay replaces the first, and a picture with no area puts the system's back). tests/macos/probe/polish.e on the runners: the overlay is seen in the Dock screenshot over the folder icon, replaced and cleared without error, and a drag of two files and an image out of a window ends Cancelled when a mouse up is posted, on aarch64 and x64; ui_drag_drop and ui_taskbar pass and the corpus is 1108. Not done: session restore (restart_register) stays Unsupported, because a launchd job with KeepAlive starts at once and a Mac restores a program's windows through the system's own saved state, which is not a command line to register; promised files (a file made at the drop's destination) and a real pointer drag with the files landing in Finder (C192).

### C107 — NeperOS shell 3: the e.os surface on NeperOS (os.neperos.e) (93%)

Queued by D2148. Acceptance: an `os` variant for target `aarch64 neperos` over NeperOS system calls -- memory from untyped/frame capabilities, threads, monotonic time from the counter and wall time from the RTC the device tree names (PL031 on virt), file I/O through the C106 server, stdout and stderr through the console server; e.io, e.fs, e.time, e.thread and e.fmt compile unchanged for NeperOS, and their existing fixtures that need no network pass under QEMU. BEGUN D2154 (lib/e/os.neperos.e): the e.os surface is intrinsic-based (compiler seeds open/read/write/close/seek/stdout/stderr/exit/threads/clock into e.os; the per-target variant file adds helpers), and NeperOS had no variant -- it fell back to the types-only os.e. New os.neperos.e is the variant project.select_source picks for a neperos os (a variant is the whole module: full type block + ErrorKind/ErrorDetail + NATIVE_SEPARATOR + read_detail/write_detail over the seeded read/write). e.io now compiles and RUNS unchanged on NeperOS, verified on QEMU both hosts: io_test.e reaches os.stdout() + a Writer via io.print (not the console primitive), prints two lines, exit 0; fixtures in run.ps1/run.sh. Existing neperos programs (init, shell/fs servers) unaffected (seeded intrinsics + base types only). e.time DONE (D2155): os.clock lowered to kernel syscall 13 -- monotonic from the virtual counter converted to ns, wall from the PL031 RTC the device tree names, verified on QEMU both hosts (time_test.e: elapsed ns across a spin + a 2026 wall timestamp). e.fmt DONE (D2156): the 45 fmt codecs are pure (no os primitive), so the variant + e.io carry them -- fmt_test.e encodes a struct with json.encode[T] to an e.io Writer, verified both hosts. e.thread DONE (D2157): os.thread_create spawns a thread in the same address space on a kernel-mapped stack (vm.map_stack in the spare L3 entries above the program window), join reuses the reap syscall, detach is syscall 15; a by-pointer Thread arg caused a non-blocking-join race (99 on Windows QEMU, 0 on Linux) until the wrapper dereferenced it, now 5/5 on each host. e.fs DONE (D2158): file I/O through the C106 server -- un-seed open/read/write/close/seek/readdir for neperos, add a console_write intrinsic for stdout, and write the file surface in os.neperos.e as a client-side handle model over fsproto IPC (open/read/write/close/stat/mkdir/remove real, symlink/rename/dirs/env Unsupported); fs_efs.e writes+reads /hello through the server, both hosts. ALL FIVE MODULES (e.io/e.time/e.fmt/e.thread/e.fs) now compile+run on NeperOS. Last 0.1 (thread_create/join/detach), e.fs (the ~40 path/dir/stat functions over the C106 server), e.fmt breadth, and porting the existing lib fixtures to run under QEMU. Last 0.1: stdout through the EL0 console server (now the kernel console write); the Unsupported fs ops the flat C106 server cannot serve; and porting the lib modules' own existing fixtures to NeperOS beyond the one-per-module here. D2183: e.fmt BREADTH -- fmt_test.e now also writes two rows through e.fmt.csv (a header and a data row, the default comma/LF dialect) after the json encode, so the serial reads `fmt csv: x,y,label` then `3,7,neperos`; a second pure e.fmt codec runs unchanged on NeperOS, identical on both QEMU hosts (8.2 WSL, 11.1 Windows). Built and verified with a worktree-local neper-self (~17s via the Windows bootstrap) because the shared one had been swapped by a concurrent session to a divergent line lacking this worktree's D2158 write-seed guard (resolve.e:436 keeps open/read/write/close/seek out of the seeded intrinsics for neperos so the variant defines them). D2184: a THIRD codec -- fmt_test.e also encodes the struct through e.fmt.ini (flat key=value: `x=3`/`y=7`/`label=neperos`), so three pure e.fmt codecs (json/csv/ini) run unchanged on NeperOS, identical on both QEMU hosts. Boundary found: only the SHELL boot is verifiable here; the gpu/DRIVER boot faults at the program's first instruction (unexpected exception 0x08, far 0x10000000000, exit 0x87) for every driver program incl. the unmodified, previously-green gpu_test/calc_app/clock_app -- the same binaries run under the shell boot. Two independent compilers (c103b self-host rebuilt today + build/windows/neper.exe), both from the divergent C103/master line that overwrote the shared build/, produce the IDENTICAL fault; no fa07c7d0-line compiler is available and one cannot be built here (frozen bootstrap lacks capacity, WSL crashes on the self-host build, Windows bootstrap needs absent MSVC). So the gpu-boot C107 fixtures and the C112-C114 app-face rendering are unverifiable until the branch lands on master / a matching toolchain is restored -- a coordination state, not a code defect. D2185: e.thread GROUP -- thread_test.e now also runs thread.spawn_all/join_all (three workers over three contexts, one barrier; each write checked after join_all), serial `thread group of 3 joined`, both QEMU hosts. This also sharpens the boundary: the toolchain miscompile is NARROW -- thread_test drives os.thread_create + vm.map_stack (page-table code of the same family as the faulting map_range_el0) and runs correctly on the shell boot with the same neper-self that faults the driver boot, so only the device-MMIO driver-boot path is affected; the rest of the e.os surface (e.io/e.time/e.fmt/e.thread spawn+join+group) stays verifiable. D2186: e.time CALENDAR breadth -- time_test.e now converts the wall timestamp to a civil date via time.to_date (days_from_civil/civil_from_days floor-division math) and prints `time date 2026-10-7`, proving the calendar path runs on NeperOS beyond the raw clock read; fixtures assert a `time date 20xx-` pattern, both QEMU hosts. Confirmed the C113/C114 faces render via e.gpu's CPU backend (no real GPU) but need the 16MB out-of-window arena, which both the driver boot and start_process's bigarena path get through the one miscompiled map_range_el0 (main.e:85), and the 2MB in-window cap is far too small -- so the faces are sound but verifiable only with a matching toolchain. D2187: e.io BUFFER round-trip -- io_test.e now, after the two stdout prints, writes seven bytes through an io.SliceWriter and reads them back through an io.SliceReader over the written portion (bytes and both counts checked), serial `io roundtrip ok`, both QEMU hosts. The verifiable e.os surface now has shell-boot breadth across all four shell-reachable modules: e.io (stdout + buffer round-trip), e.time (clocks + civil date), e.fmt (json/csv/ini), e.thread (spawn+join+group). C107 holds at its ~0.9 ceiling here: e.fs's remaining ops are flat-C106 Unsupported-by-design and its driver-boot fixtures (plus the C112-C114 rendering) need a matching toolchain, so further shell-boot breadth adds coverage without moving the score. PART (D4704): os.neperos.e declares the whole e.os fence, NeperOS runtime gains neper_hash_bytes/args/spawn stubs, shell/ident/host variants, target.Os.Neperos; 1,063 of 1,090 link fixtures compile for aarch64 neperos, 126 apps byte-identical. Compile-verified; neperos/src/map_test.e boot not yet run.

### C092 — M3-04: e.gpu runtime surface: Device, Queue, Buf[T], launch, sync, barrier (95%)

`e.gpu` at `surface: partial`: `open`/`close`/`has`/`info`, `queue` and `queue_with`, `Buf[T]` as a generation-checked handle into a per-device table, `alloc`/`upload`/`write`/`download`/`release`/`len`, tokens with `done`/`wait`/`wait_for`, `sync`, `grid1/2/3`, and `gpu.launch[K]` as the third argument-pack intrinsic: the pack is checked against the kernel's parameters (`Buf[T]` for a device slice, a value of the parameter's type otherwise) and expands into a generated launcher per calling module, kernel and argument shape (D778). `gpu.barrier()` is the third device intrinsic recognised, legal only in a kernel's own body, lowered as the cut of the CPU build (D780). The fault buffer (D785): a failed tag, alignment, null, enum or bounds check in a kernel's CPU build writes the queue's one `FaultRecord` and ends the invocation, `sync`/`download` answer `Fault` once, `last_fault` answers the record. Presentation (D791): `Image`, `open_target`, `acquire`, `present`, `presented`, `resize` and `close_target`, offscreen on the CPU device. `[]Atomic[T]` launch parameters and both `gpu.memory_barrier` scopes already run in `link/gpu_vulkan_sync` on CPU and Vulkan (D1615). `queue_with` now uses a lazily allocated reusable Vulkan staging block, chunks writes by `block_bytes`, and frees it on close; CPU remains a direct copy (D1787). `link/gpu_staging` passes on CPU and two Windows Vulkan devices, and `gpu_vulkan_sync`, `gpu_cpu`, and `gpu_gaps` still pass there; the Linux CPU/no-device staging fixture passes. The device block now has a reentrant mutex covering queue, buffer and close operations; a short registry lock protects publication and token lookup, and CPU launches serialize their shared scheduler globals (D1788). `link/gpu_device_lock` passed ten Windows runs on CPU and both Vulkan devices, and passed Linux's CPU/no-device path. Existing GPU staging, sync, CPU, gaps and presentation fixtures pass on Windows; staging passes Linux's CPU/no-device path. Not yet: full-suite verification. The prior Windows suite reached its final function/type-renamed compiler image, which crashed with an access violation when compiling the original sources. Linux's bootstrap compiler rebuild restarted WSL even at pre-staging `afdc224b`. The current synchronous implementation reuses one staging block even when the configured bound allows more.

### C093 — M3-05: device selection: devices, DeviceInfo/DeviceKind/DeviceKey, open_id, info (95%)

`devices` answers the bounded snapshot with the CPU device (`supported`, no stable key, capabilities copied into the caller's arena), `open` takes `.Cpu` index 0 and refuses other indices with `NoDevice` and other backends with `Unsupported`, `open_id` refuses a CPU key with `NoDevice` since the CPU has none, `info` copies the opening-time descriptor (D778). Not yet: Vulkan and CUDA enumeration, stable keys and `AmbiguousDevice`, memory capacity. PART (D4200): Vulkan device keys from deviceUUID with key_valid, open_id matching backend and all 16 bytes (NoDevice, AmbiguousDevice, Unsupported), devices a complete snapshot, real index in info; gpu_devices passes on this host's two Vulkan devices; AmbiguousDevice only through the pure resolve_key. Missing: CUDA enumeration, a --gpu-inventory file, three-attempt re-enumeration. PART (D4700, D4703): neper run --gpu-inventory FILE, three-attempt count/list re-enumeration, CUDA enumeration via dlopen (CUDA uuid equals the Vulkan deviceUUID on the RTX 3080); gpu_inventory, gpu_devices pass. Missing: a CUDA backend (M4), AmbiguousDevice from real hardware, MIG.

### C094 — M3-06: device-callable inference into the kernel-owning module's .em (95%)

PART (D4201): a second oracle pass flattens every kernel-reached plain function into Builder.device_entries so the kernel module's .em carries the device code; a 3-module chain with a 2-result helper runs on both Vulkan devices in debug and release (gpu_device_edit). Missing: generic and function-pointer helpers, constants read from a third module. PART (D4702): three faults fixed (inlined BranchIf merge block, generic instance body edges, constants read by an inlined body in its edge hash -- a master correctness bug where incremental --release kept an old constant); gpu_device_helpers and release_const_edge pass. Missing: function-pointer helpers.

### C095 — M3-07: GPU floating point: no contraction, math.fma only, denormals, ftz (88%)

PART (D4203): DenormPreserve/DenormFlushToZero over every reachable function, ftz kernels run under FTZ/DAZ on the CPU (stmxcsr/ldmxcsr; aarch64 FPCR hand-derived, not run), math.fma as Fma/NoContraction; gpu_float_modes passes on the CPU and the Intel Xe device. Missing: f64 in the SPIR-V writer, NVIDIA DenormPreserve, ftz+f64 on the CPU. PART (D4701): f64 in the SPIR-V writer (Float64, NoContraction FAdd/FSub/FMul, compares, conversions, fma); float64.spv hash-checked, gpu_f64 bit-exact on the CPU; no device here runs f64 (Intel Xe lacks Float64, the RTX 3080 fails the denormal gate). Missing: f64 div/sqrt, NVIDIA DenormPreserve, ftz+f64 on the CPU.

### C096 — M3-08: determinism harness, the device-reached edit case (90%)

PART (D4201-D4202): gpu_device_edit edits a helper two modules from the kernel and requires main and lowhelp rebuilt, midhelp kept, hot image equal to clean, device equal to host, -j 1 and -j 3 --perturb images equal; also fixed emit-em-all --incremental rebuilding main/e.gpu/e.sync every time (D4202). Run by hand on x64 Windows and the Linux target; the run.sh block not executed.

### C083 — Determinism harness (95%)

compiler fixed point on both platforms, artifact-linked equals source-linked for every artifact fixture, and incremental equals clean for link/incremental (D205); the compiler's own 31 artifacts, listed in graph order, link byte-equal to the source build, and so does the set with one module rebuilt incrementally (D213, D214) -- `link-em` lays functions out in the order the artifacts are given, so the order is an input. `-j N` caps every phase's workers and `--perturb` turns the crew's schedule around (D331): both suites require the compiler built under `-j 1` and under `-j 3 --perturb` to be the stable stage byte for byte, and the inlined release fixture under `-j 1 --perturb` the default build; the hot build under either is the cold image. A relocated build is the same image (D337): the sources spelled from the project root in the line table, so the operand's spelling and the project's place change nothing, pinned by both suites. The fixed point caught the crew's one shared scratch table (D505): the workers' checkers forked every table they append to but the constant expressions, so D500's fold on eight workers wrote over each other's copies and once folded `if 4991usize < limit` away in a loaded stage 3; each worker now has its own. Not yet: the device-reached edit case that waits on M3 Placed after C096 (D1580): the one case left is C096's device-reached edit case, which the GPU line before it has to deliver first. The device-reached edit case is delivered (C096) with schedule-independence assertions (3f393d47); the suites were not run on it.

### C088 — Bootstrap frozen and deleted (0%)

bootstrap/neper.c still builds stage 0. Follow-on (D1898): deletion is also the biggest LLMx lever â€” until it lands, agents write M1 per the docs and compile neper-0 plus quirks, and failures like T021's look like agent error.

### T004 — run (93%)

`run PATH ROOT ARCH OS OUTPUT [--release] [--arena SIZE] --json` (D231): a build, then the program is launched with its stdout and stderr to files beside the executable and read back whole into one `run` record with the process exit code, captured bytes base64 when they are not UTF-8 (section 2); tests/conformance/tools/run.e exits 3 and writes a non-UTF-8 stderr byte. A trap's record is read back out of stderr as the structured `trap` payload (D253): its kind, a byte-precise zero-width span at the site when the file is the operand, the record's values text as one entry, and one backtrace frame per `  at` line with its qualified function, the operand source where the frame lies in it, and its line; tests/conformance/tools/run_trap.e pins a bounds trap two frames deep, spelled relative to the test build dir so the golden carries no host path. `-- ARGS...` after the flags reaches the program as its arguments on both hosts, spaces kept (D267, tests/conformance/tools/run_args.e echoes three and exits with their count); a relative OUTPUT with directories launches on Windows too, spelled the host's way. A Linux build writes its executable mode 0755 and `run` and `test` launch it directly, no `sh -c` and `chmod` in front (D291: `os.set_mode` joined the bootstrap's fixed surface, the per-host `e.os` source having it); the Linux suite requires the corpus build's executable to be one. a trap and a frame in another module name that module's source under its own root with the line and column the child printed (D503; `run_trap_module`), where both were null. A project root is `run`'s operand (D1682): `neper run DIR`, or no operand, runs the project's `src/main.e`, pinned with `build` in both suites; a repeated `run` is incremental (D1681). Not yet: streaming

### T011 — info (95%)

`info --json` (D229): the header, one `info` record -- tool version, the one language profile, the commands the stream reaches (`check`, `info`, `parse`, `tokens`), the host target, both build targets, the one CPU level the emitter honours -- every collection sorted by bytes, and a result; tests/conformance/tools pins it per host. `commands` names every section 1 command the stream reaches -- build, check, dis, fmt, index, info, parse, run, test, tokens -- sorted by UTF-8 bytes (D259); it had stopped at the four of D229. `--language-version MAJOR.MINOR` on any command selects the one advertised profile, 0.1, and is taken off the arguments; another version is E-CLI-9999 before any source is read, as a stream whose header names the command (D283, tests/conformance/tools/info_version). `info` now lists `cpu_levels` `x64-v1`..`x64-v3` (the `--cpu` levels of D765) and `features: ["tls"]` with the TLS profile, per the per-host goldens. Not yet: the spec table's other levels -- `x64-v4`, `aarch64-*`, `x86-*`, `sm_*` -- which the emitter does not produce

### T012 — v1 schema validation of emitted records (95%)

`python scripts/validate_stream.py` validates every committed golden against docs/schemas/neper-v1.schema.json, and both suites run it (D250): the 23 `.jsonl` streams under tests/conformance -- one record per line, 895 of them -- and docs/modules.json as a whole document, so the three shapes anything currently emits are covered (`streamRecord`, `buildManifest`, `modulePlan`). The goldens are what the commands emit byte for byte, so validating them validates the emitters. A self-check rejects a header carrying an unregistered command before the corpus runs, so a validator that accepted everything could not pass; a machine without the `jsonschema` package prints a skip rather than failing the suite. The runner's source map (D264) is validated by both suites as a fourth shape; `packageManifest` is in the schema with nothing producing it yet PART (D4305): tests/conformance/package/p0.package.json validated by validate_stream.py with a five-mutation negative self-check; 3,368 records, 0 invalid. Missing: the producer (M6 pacman P0).

### T016 — Conformance corpus accept/reject/format/tokens/parse/tools (95%)

All six corpus roots of tooling.md section 9 exist with byte-exact expected output the suites compare on both platforms: tokens/ and parse/ (D227), accept/ and reject/ (D228), tools/ -- one `info` stream per host (D229), a build and a rejected build (D230), a program run (D231) and a trapping one (D253), a symbol index (D232, D251), a disassembly per host (D233), a canonical format and a `--check` rejection (D234, D244), a build manifest per host (D238), a test run and a timed-out one (D240, D246) -- and format/ (D255): a non-canonical source beside what `fmt` makes of it, the canonical side also passing `--check`. Every `.jsonl` golden validates against the v1 schema (D250). Every root has at least two fixtures (D284: accept/aggregate -- structs, an enum, a generic and a switch -- and format/types, whose first draft found `fmt` writing `case.Red` and mis-indenting `case` labels). Every registered code the compiler can raise today has a reject fixture pinning its stream (D297): ten more -- E-MODULE-0001/0002/9999 (the last two as two-module projects under reject/), E-NAME-0002/0003, E-ERROR-9999, E-MEM-9999, E-TYPE-0001/0003/9999 -- beside the six already pinned, leaving E-LINK-9999 (an error-hash collision no small fixture produces) and the codes whose subjects do not yet diagnose (E-GPU, E-SAFETY, E-TOOL-9999). reject/nesting pins section 3's 128-level nesting bound (D341), which a mutation-and-depth fuzzer (benchmarks/fuzz) guards beside the artifact readers. Not yet: the generated-code benchmark report section 9 asks for PART (D4302): the generated-code benchmark report section 9 asks for exists and runs in both suites over the reference corpus. Missing: a live model pass rate (provider and budget).

### T021 — Compiler hashes from the library (95%)

xxHash64 and FNV-1a land (D747): `src/artifact_hash.e` calls `e.algo.hash` for both, and the tuned inline-load one-shot D388 wrote for the artifact path moved into the library rather than the library's byte-buffered one surviving -- D333's rule that the faster moves. `round` (the `program_snapshot` fold, D407) and `fnv1a32_step` (the module-dot-name fold, D6) stay in the compiler with `rotate_left` and `xor` under them; `read_u32`, `read_u64`, `merge_round` and three primes went with the body. Pinned by a seventy-seven byte vector in `artifact_hash.self_test` -- two whole blocks, then an eight, a four and a one -- and by the suite's artifacts, manifest goldens and stage-2/stage-3 fixed point. `e.algo.hash` is `surface:"source"`, so the move added no declaration. CRC-32C is the library's (D1701): `e.algo.hash.crc32c*` with slicing-by-8 past 256 bytes, the compiler keeping only the CRC32 instruction and the zeroed field, artifacts unchanged. Not yet: SHA-256, which is blocked -- the C bootstrap builds stage one on every suite run and refuses `lib/e/crypto/hash.e` with nineteen E-TYPE-0002s where a `u64` shifts by a `u32`, so that half waits on the bootstrap's deletion (D208), which is the finding D333 asked for UPDATE (D2329): the blocker is gone -- lib/e/crypto/hash.e now builds under the C bootstrap (u64 shifts by u64, no `-=`, Keccak slices through a local pointer copy) and the six crypto fixtures still pass. What remains is a decision, not a blocker: the compiler's `os.sha256_blocks` intrinsic (D332) against the library's portable block function, to be measured on T023's corpus. PART (D4301): artifact_hash.sha256_hex_into calls e.crypto.hash.sha256 (about 90 lines left the compiler); the library tops up a partial block and feeds whole blocks to os.sha256_blocks at 1.0-1.25 GB/s; build manifest byte-identical, stage 2 equals stage 3, crypto_hash split check passes on Windows and Linux. Missing: the suite's stage-one (bootstrap) build verification.

### T023 — Generated-code benchmark corpus (85%)

benchmarks/llm_edit PART (D4302): benchmarks/llm_gen/report.py scores a candidates directory with parse-file, check-file, fmt --check, build and run against expected output, with repair rate and thresholds; wired into both suites over the 10 references (100/100/100, correct 100%). Missing: a live model's numbers (needs a provider and budget; T027).

### T026 — Agent workflow adoption: context-file before file reads, patch or plan-* before scripts (85%)

The tools exist (context-file C053/D361, tools/patch D1455, plan-*-file C052) and nothing routes agents to them: scripts/lang-stats.py on every transcript to 2026-09-26 puts the median context at a turn that lands Neper code at 515K tokens against Dart's 235K, while context-file answers in 1.2K-5K (D948); 39% of landed Neper source arrived inside Python patch scripts and heredocs at 5x the cost per byte of a direct edit, and 5.0% of edit applications failed, almost all of them heredoc scripts. Done when the AGENTS.md rule and a card section route both paths and lang-stats.py's ctx Ktk and script% move on new sessions; the two numbers are the score. The same routing gap holds for the language card: 19 of 161 Neper sessions in 2026-09-20..27 ever named docs/llm-neper-card.md, AGENTS.md carries no language guidance, and the card lists the keywords but not the traps that ended most builds -- `target` (D31), `Vec` and `i8` as reserved names, D66's rule that a local may not reuse a module-scope function, use qualifier or builtin, the string escape set (`\u000F` was written for `\x0F`), and the bootstrap-only rules until C088. A traps section in the card, pointed to from AGENTS.md, is part of this item. Follow-on (D1898): fix the render_card.py mojibake in the normative refs and land the traps section (target, Vec/i8, D66, escapes, bootstrap-only); T036 routes agents to read the repaired card first. Measured on Claude alone (lang-stats.py --harness claude, 2026-08-28..09-27), context is the one gap left against Dart: 513K tokens at a turn that lands Neper code against 210K, with 5.7 turns per edit against 3.9; correctness is level (1st-ok% 96.4 vs 95.0, selfcor% 14.4 vs 15.2, fail% 4.9 vs 3.8), and the 35% cost gap ($0.691 vs $0.513 per KB) is the script share alone (38% vs 17%; direct $/KB 0.198 vs 0.263). Over the last 7 days of it the script share fell to 22% and context to 422K after tools/patch replaced Python patches of src/ on 2026-09-26 (254 and 326 such scripts a day on 09-20 and 09-21, one on 09-27), while 448 patch scripts named dNNNN.py still reached test fixtures, most on 09-25 and 09-26. The score is read from --harness claude: ctx Ktk toward Dart's ~200K and script% toward its 6-17%. Codex on Neper (10% of its code) reads 16 bytes per byte landed and repeats the previous error code 78% of the time, so the traps section serves it too. Snapshot 2026-10-03 (14d, --harness): Claude ctx 388 Ktk (was 422), script 19% (was 22%), $/KB 0.442 (was 0.691, under Dart's 0.468), turns/ed 6.0 (was 5.7), 1st-ok 94.0% (was 96.4). Codex: 3.4 MB landed, script 0% via native apply_patch, ctx 166 Ktk but 15.8 read/KB, turns/ed 7.0, 1st-ok 89.0%, fail 7.2%, 2.7x think per byte. DeepSeek (dsh): zero rows in 14d â€” the split currently measures nothing (D1904). LANDED (D2308): the card's Traps section (reserved names target/Vec/i8, D66 shadowing of functions and qualifiers, ok/err/error field names, tuple-call return, the escape set, bootstrap-only rules) with five checked examples; AGENTS.md routing was already in place. REMAINING: the measured movement of lang-stats ctx Ktk and script% on new sessions. PART (D4303): measured over 14/7/3 days: script share 6-8% (baseline 38%), ctx 459/448/377 Ktk, $/KB 0.674/0.600/0.439, turns/ed 6.1/5.9/6.4. Open: turns/ed against Dart's 3.3-3.8, read volume.

### T027 — H12 v1 precursor: held-out two-family evaluation on real tools (5%)

post-m2-llm-hardening.md section 15 specifies the only evidence that can support a superiority claim -- correctness first, then total interaction tokens per verified success, repair turns and source-token pressure, 20 seeds per case, Neper's own tools against each baseline's native ones, rank first or statistically tied or expand rather than assert -- and nothing in this queue schedules it. benchmarks/llm_edit/neper_advantage_matrix.md and benchmarks/llm_gen are smoke runs by their own READMEs. Follow-on (D1898): include an OpenCode-harness arm in the held-out design, or LLMx fixes are measured everywhere except where agents actually run. Done when ten held-out tasks in two model families run under the acceptance rule with the harness, prompts, cards and baseline results frozen and the report versioned. Follow-on (D1954): full E2 comparative gate after this pilot â€” broad plus registered cohorts with frozen weights, oracles and statistical rules; the ten pilot tasks above are the rehearsal, not the claim. FIRST STEP (D2330): scripts/freeze_llm_protocol.py writes docs/llm-protocol-freeze.json -- hashes of the card, schema, capabilities golden, budgets, benchmark tasks and runner, the compiler/library/conformance trees, the acceptance rule as data, arms and strata -- and --check names drift. NOT DONE: register the model families and versions, the held-out task ids and the OpenCode arm, archive baseline results, and run (needs provider access and budget).

### T028 — Repeated diagnostics: fixtures and fingerprints for the codes that recur across a repair (85%)

Over 198 observed repairs in the transcripts (lang-stats.py, REPAIR table), a compile diagnostic is fixed in the next reply but only 15.7% of repairs took one edit, and 61.5% of consecutive failed builds repeat an error code from the failure before -- E-TYPE-0002 and the other kind-level codes cannot tell a second site from an unfixed first one. H31's cross-run fingerprints are T2; the v1 precursor is a fixture per recurring code that pins what the message must name (the span, the expected and found types, the binding) so a model can act on it once, tracked by lang-stats.py's repeat% and 1-edit%. Follow-on (D1898): the repeat metrics must cover OpenCode rows once the T037 harness split lands, or agent-visible progress stays Claude-only. Transcripts 2026-09-20..27 name the first fixtures: 134 builds failed on a compile code and 24 of 42 consecutive ones repeated a code. E-TYPE-9999 (29) printed an internal error name for its message -- `type checking failed: check.UnknownCallable`, `.ArgumentCount`, `.InvalidOperator`, `.Unsupported`, `.InvalidType`, `.MissingContext` -- naming no callee, count or operator; E-LEX-0003 (21) said `invalid token` for a malformed escape without naming the escape or the legal set (src/main.e print_parse_failure); E-NAME-9999 (8) said `unknown value name` without the name; E-TYPE-0003 (9) said `ret gives a different number of values` without the two counts; E-SYNTAX-9999 (9) said `unexpected ==` without what was expected. Each of those messages names its subject, the check.* names get codes of their own, and a fixture pins each. D1679 does that: ArgumentCount is E-TYPE-0005 (`take` takes 1 argument and this call gives 0) or E-TYPE-0007 (results discarded), UnknownCallable E-NAME-0004 with the callee, InvalidOperator E-TYPE-0006 with the operator and its expression, MissingContext E-TYPE-0001, InvalidType and Unsupported E-TYPE-0008/0009 quoting the statement; the unknown name, both ret counts, the bad escape with the legal set (and an unclosed literal, a control byte, a tab, a non-UTF-8 byte), and `; expected X` after `unexpected` where the parser knows X. The C bootstrap says the two messages its neper-0 fixtures pin, so self-host parity stays byte-equal. Pinned: seven check fixtures by text in both suites, the conformance and tools goldens, byte-equal on Linux. E-TYPE-0009 is reached by reject/not_supported, an assignment to an array range quoted by its first line (D1706, both suites). Not yet: lang-stats.py's repeat% and 1-edit% over transcripts written after D1679. Snapshot 2026-10-03 (14d): repeat% Claude 59.5 (was 61.5), Codex 70.0; 1-edit% identical across harnesses (54.3/53.5), so landed fixes transfer but recurrence does not; DeepSeek empty. Cross-run fingerprints remain the stuck point on both measured harnesses (D1904).

### T029 — Rename fix for a local that collides with a module-scope name (E-NAME-0003) (85%)

E-NAME-0003 ended 35 of the 134 builds that failed on a compile code in 2026-09-20..27, the most of any code: common nouns that large modules use as functions (`text`, `level`, `row`, `placeholder`, `at`, `cell`, `icon`), `use` qualifiers (`source`, `bytes`, `check`) and the reserved `target`, `Vec` and `i8`. D66's no-shadowing rule stays; what is missing is a fifth fix kind beside the four in src/main.e's diagnostic writer that proposes a free name for the local and every use of it in its scope, so D948's repair loop applies it without a model turn. Done when a fixture per collision kind (module function, qualifier, builtin, reserved) carries a machine-applicable rename and lang-stats.py shows E-NAME-0003 no longer the top repeated code. Fix kind 5 (D1678) does the first half: on ModuleShadow, ReservedLocal and DuplicateLocal the diagnostic carries a `maybe` fix renaming the local and every use in its scope, one edit per site under one SHA-256 precondition, to the first free `name_value`/`name_value2`..`9`. Uses are found lexically to the end of the block (`let`/`var`) or of the body a parameter, `for` name or capture heads; members, field labels, calls of the colliding function, qualified paths through the colliding qualifier and type positions of a colliding builtin are left alone. Fixtures reject/rename_function, rename_qualifier, rename_builtin and rename_duplicate, and reserved_local's golden now carries its fix: byte-equal under stage 1, stage 2 and on Linux, and each applied fix checks clean. Not yet: lang-stats.py over transcripts written after D1678 showing E-NAME-0003 no longer the top repeated code. Follow-on (D1898): same measurement must include OpenCode rows; a Claude-only reading cannot close a harness-wide top-code claim.

### C082 — Work-stealing pool, parallel parse and codegen (75%)

the front end runs in waves of eight workers (D321); the modules are lowered, selected and written as artifacts on eight workers with checkers that share the declarations (D325); and the same workers check the bodies and build both inlining oracles first, each with a checker forked from the program's and importing the types of a body copied from another worker's oracle (D326). A two-million-line program builds cold in 7.6 s debug and 7.4 s release where it took 29 and 26, its body sweep 0.6 s where it took 1.9 (1.3 s where it took 5.7 in release), the settle nothing on a cold build and the lowering not re-checking what the sweep checked (D327), and the bootstrap runs a thread inline. The names are validated on the workers too (D328), the artifact writer copies bytes with one runtime call (D329), and the allocator, the digest and the lexer lost their last quadratic and per-byte costs (D330): a million-line program builds cold in 3.0 s on Windows and 3.4 s on Linux, warm in half a second; the link's per-artifact passes run on the workers too, with SHA-256 and CRC-32C in hardware where the CPU has them (D336): a million-line program builds warm in a quarter of a second, the compiler in 65 ms; what remains sequential is collecting the declarations, reachability and layout; the work is assigned statically, not stolen Stealing modules through a shared counter was built and measured, and reverted (D1578): the compiler's body phase is bound by its largest module (`check.e`), which no worker can split, and on sc500k the lowering lost the static schedule's balance (1.7-1.9 s against 1.3-1.5 s); the lever left is stealing a module's functions, across the D326/D327 coupling of checks to lowering. Moved to the end of the queue by the user's decision (D1579): what is left needs the declaration tables redesigned -- per-module tables merged in module order with every index relocated -- for at most the 152 ms of a 2.16 s sc500k build the declarations take (resolve 74 ms, the link from artifacts 130 ms), or function-level stealing across the D326/D327 coupling.

### C098 — AES-GCM at OpenSSL's speed: AES and carry-less multiply instructions for e.crypto.aead (80%)

e.crypto.aead's AES-GCM is portable Neper, a bitsliced AES (BearSSL's aes_ct64) and a GHASH from masked integer products (ghash_ctmul64), D1645. Measured 2026-09-28 on the Core i5-12500H, sealing one TLS record: 11.6 us for 100 bytes and 702 us for 16 KB (23 MB/s), against OpenSSL's 0.73 us and 3.19 us (5.1 GB/s, through Python's cryptography 48, whose call overhead is included): 16 times slower on small records and 220 times on large ones. It bounds every TLS user: x.microsoft.tds scans SQL Server at 28-35% of the fastest language (D1643), where OpenSSL, Go and rustls run AES-NI and PCLMULQDQ. Closing the gap needs the back end to emit AESENC/AESENCLAST and PCLMULQDQ (x64) behind a CPU check with the portable path as the fallback, as SHA-256 and CRC-32C already are in the link (D336), then a GCM that keeps its expanded key and H powers across records (e.net.tls expands the key for every record today) and runs four to eight blocks in flight. Until then, the portable path's own lever is codegen: the same bitsliced rounds run at about 130 cycles a byte, several times BearSSL's in C. PART (D4300): four e.os intrinsics (cpu_features, aes_expand_key, aes_ctr, ghash_blocks; AES-NI and PCLMULQDQ on x86-64, aarch64 stubs answer none), e.crypto.aead takes the hardware path with the D1645 portable fallback; crypto_aead_hw passes vs portable GCM, OpenSSL and a bit-level GF(2^128) product on Windows and Linux x64; 16 KB seal ~1.8 GB/s vs OpenSSL ~5 GB/s on a quiet machine. Missing: 8-way interleave and fused CTR+GHASH, ARMv8 AES/PMULL, VAES.

### C150 — NeperOS storage remainder: per-app directories, Share, thumbnails, zip, external storage, large files (85%)

Split from C125 (D2382): the Files app is on the real filesystem with list, create, rename, move, copy, trash, search, recent and select, and hands a file to Document. Acceptance: (1) the capability model: the filesystem server tells its clients apart (badged endpoints from the kernel or a per-app request endpoint) so an app sees only its own directory and what Files shares to it; (2) Share to another app and the Camera, Wallet and Mail apps saving into Files once they exist (C121, C122, C128); (3) a grid view with image thumbnails (PNG/JPEG decode into e.gfx scenes); (4) browse and extract a zip with e.fmt.zip (the disk image seeded by scripts/make_fs_image.py so a fixture has one); (5) external storage: a second block device as a second root through a second filesystem server instance; (6) entries beyond sixteen a directory (files larger than 4 KB: done, D2387). Delivered by C125 and not to redo: everything in D2375-D2382. PART (D2446): zip archives are browsed (entries and sizes) in Document via Files' handover, e.fmt.zip, fixture document_zip. Remaining: extract an entry, per-app directories, Share, thumbnails, external storage. PART (D3806, D3803): Files grid with PNG/JPEG thumbnails and zip extraction of the whole archive into /<name> with zip-slip refusal; QEMU rows files_grid and document_zip_extract pass. Missing: per-app directories (no kernel badging), Share and saving from Camera/Wallet/Mail into Files, external storage, single-entry extract. PART (D4810-D4814): per-app directories (fs endpoint stamped, installed app 100-199 confined under /d<N>, row install_confined), Share sheet from Files (files_share), zip-entry extract (document_zip_entry), external storage as a second filesystem server (files_external). Remaining: per-app quota, sharing from installed apps, browsing into and writing to folders on the external card, Camera/Wallet saving beyond /DCIM, Downloads and /Wallet.

### C151 — NeperOS Dynamic, the server side: protocol, model, compile-and-repair, signing, many installed apps (50%)

Split from C124 (D2388): the device can verify, install, keep, ask about and launch a signed package and refuses what it did not declare. Acceptance: (1) the protocol over C117's TLS: a request carries the prompt, the app's identity and the device's API level; the answer carries the package (manifest, image, source, signature), streamed into the filesystem (a GET larger than httpc.e's 96 KB, with a request body); (2) a local test server with a canned model answer (no live model in the suite) that goes prompt to installed icon to launch to extension, as an installfixture; (3) the Dynamic app (D2238) calling it in place of its three templates and showing the stages from the server's progress; (4) the compile step on the server (the Neper compiler against the app kit, diagnostics fed back to the model until it builds or gives up readably), the scan before signing, a reproducible build, signing and revocation, an audit log; (5) many installed apps (the shell's single slot becomes a list from /apps), removal, update and rollback, and the manifest icon on the grid; (6) the NIR walk of the scanner (raw syscalls, undeclared capabilities, unbounded loops over input), with its report on the Details screen. Delivered by C124 and not to redo: D2383-D2388. PART (D4108): the build server streams stages, the 430 KB package is fetched without the httpc limit, checked and kept in /apps (dynamic_server); a restart adopts it and launches it (dynamic_server_again). Missing: many installed apps, update/rollback, removal, a live model. PART (D5103): many apps, update/rollback and removal pass. Remaining: live model, a fourth icon, the NIR scanner.

### C152 — NeperOS Document remainder: PDF images and vectors, Office layout, pinch zoom, attachments (75%)

Split from C123 (D2394): Document shows the text of PDF, Word and PowerPoint files, rendered Markdown and highlighted code from the disk, with paging, find and text size. Acceptance: (1) PDF pages painted, not only their text: vector paths, images (DCT through e.fmt.jpeg, Flate images), fonts with their own encodings, the outline and search with the match highlighted; (2) Word tables, images and styles and PowerPoint shapes laid out; (3) pinch zoom and a page or slide strip once the touch layer carries more than taps; (4) opening from Mail attachments and Wallet pages (C128, C121) and Share; (5) shebang detection and the TIOBE list refreshed from tiobe.com with the month recorded; (6) files over 16 KB paged from the disk, not read whole. Delivered by C123 and not to redo: D2389-D2394. PART (D3801, D3802, D3804, D3805, D3809): painted PDF pages (rects, segments, text, colours, q/Q, cm), Word tables as grids, shebang detection, 12000-byte windows for big text files; QEMU rows document_pdf_paint, document_docx_table, document_big, document_shebang pass; fmt_pdf (23) and fmt_ooxml (39) pass. Missing: PDF images/fonts/outline/search highlight, Word images/styles, PPTX shapes, pinch zoom, open from Mail/Wallet/Share. PART (D4800-D4809): PDF images (DCT, Flate), form XObjects, font widths, ToUnicode, outline, Find highlight, zoom steps and pan; Word styles and pictures, PPTX shapes; Mail attachment Open and Files Share; fmt_pdf +30 checks vs independent producers; rows document_pdf_image, document_pdf_zoom, document_word_pic, document_pptx_shapes, document_ods, document_html, mail_attach_open, files_share, document_zip_entry pass. Remaining: pinch zoom and page strip (one pointer, no two-finger gesture), opening from Wallet pages, PDF glyph outlines, clipping, Indexed images, soft masks.

### L048 — Reference drivers: k8s labels, AWS subset, SSH transport (90%)

Petcow k8s provider (petcow.io/managed labels must never be renamed), aws CloudControl uniform CRUD with s3/ec2/iam subset plus lightsail non-uniform gap, transport/ssh.rs with the Transport trait and lazy per-host PerHostTransport. Land as x.cloud.aws, x.cloud.k8s, x.ssh; local stays e.proc/e.os.shell, ssm/winrm stay cloud- and platform-specific. Plan: docs/petcow.md D3/D4. Follow-on (D1881): consul/vault/etcd/docker client scope (service discovery, secrets, registries). Follow-on (D1889): SFTP subsystem client once the queued SSH transport lands. Part one landed: x.cloud.aws (Cloud Control identity, tags, desired state, patches, catalogue merge) and x.ssh.args (ssh argument builder), 311 differential cases against Petcow's Rust on Windows and Linux (D2354). Remaining: the k8s kubectl provider's identity rules (label marker, last-applied), ec2/s3/iam/lightsail and the per-host transport table. PART (D2922): x.cloud.k8s (kubectl provider identity and drift rules), x.cloud.awssdk (pure S3/IAM/EC2/Lightsail mapping) and x.ssh.transport (per-host selection) checked against Petcow's own Rust functions (600 cases). NOT DONE: SDK-call bodies, Lightsail list mapping, SSM/WinRM/local transports, consul/vault/etcd/docker and SFTP. PART (D3400): x.ssh.winrm, x.ssh.exec (SSM run, local argv) and the Lightsail list mapping in x.cloud.awssdk, 239 new cases of x_cloud_drivers against Petcow's own winrm/ssm/local/lightsail code via a Rust reference (839 total; five mutations each fail). Missing: the SDK call bodies, consul/vault/etcd/docker clients, SFTP subsystem. PART (D4602-D4610): e.net.sftp v3 codec vs a real OpenSSH sftp-server (net_sftp 134 lines), x.cloud.awssig SigV4 vs botocore (1,500 requests), x.cloud.awsreq request bodies for query/ec2/json/rest-xml vs botocore serializers (450 parameter sets, 75 operations). Missing: response parsing, rest-json, S3 handlers, consul/vault/etcd/docker clients.

### T032 — MCP server, share-token, and audit-trail service surface (0%)

Appdor services/mcp-server (stdio NDJSON plus HTTP JSON-RPC, caller-JWT RLS scoping), src/sharing share tokens (b64url payload plus HMAC, distinct from jwt.e), src/audit record taxonomy with CSV export, src/templates workflow recipe catalog as data. Serve via e.net.http plus e.os.proc stdio and e.db; DB-poll worker shape (no AMQP) maps to e.task plus e.db.pool.

### L054 — HTTP fuzz and host-sweep helpers for authorized scanning (0%)

e.net.http plus e.fmt.html/xml and e.text.regex cover web-test transport and parsing, but the wfuzz/gobuster pattern (payload encoders, concurrent sweep runner, finding records) is rebuilt by every scanner. Add e.net.http extensions plus a recipe: payload-encoder table, sweep runner over e.task with e.ratelimit and e.cancel, stable-ID finding records via e.algo.hash; fixtures use fake HTTP only, target authorization stays caller policy. Plan: docs/ethical-hacking.md S4.

### L055 — Certificate issuance for authorized TLS-intercept testing (e.crypto.x509) (0%)

e.crypto.x509 parses and verifies only (parse/parse_pem/pool/verify_signature in lib/e/crypto/x509.e) -- the auto-CA plus forged-leaf half of the intercept-proxy story has no issuance path. Add CA generation plus leaf issuance/signing over e.crypto.sign (no new crypto primitives) with fixtures: issued chain verifies under a pinned CA, expiry/SAN/DNS-name goldens, fail-closed on wrong issuer. Plan: docs/ethical-hacking.md S5.

### L065 — Complete native code editor in e.ui.code_editor (CodeMirror 6 / JustCode parity) (30%)

PART (D3201): e.ui.code_editor model and engine only -- gap-buffer UTF-8 document with line index, atomic commit, multi-range selections, grapheme/word motion, undo/redo with coalescing, incremental tokenizer (neper, javascript, python, plain), indent/comment commands, literal search/replace; ui_code_editor fixture: 10 scenarios plus a 520-step generated script digest-checked against a flat-text oracle. Missing: widget, IME/accessibility, bidi/wrap layout, folds, regex search, completion, diagnostics, LSP, most language packs. PART (D3500): regex search/replace, bracket matching, folds, soft-wrap model, multi-cursor and rectangular selection, 13 language packs; ui_code_editor_ext 394 cases vs Python re and models. Missing: widget, IME/accessibility, bidi, decorations, completion, diagnostics, LSP. PART (D4401-D4403): 33 more language packs checked against Pygments (41 of 51 ids), per-view fold state through edits/undo, wrap-aware motion, completion and diagnostics models, bracket and JSON lints; ui_code_editor_svc 1,098 cases. Missing: widget, IME/accessibility, bidi, decorations, snippets, LSP, Scratch .sb3, embedded-language HTML.

### L066 — Safe structured Markdown viewer over e.fmt.markdown and e.ui.control (90%)

Planning only (D1812). Reference: JustCode src/replytext.js and its unit cases. e.fmt.markdown already provides caller-storage block/inline parsing; e.ui.control has text/rich-text primitives. Reuse these for a generic native viewer with headings, paragraphs, lists, quotes, rules, fenced/inline code, emphasis and selectable text. Not yet: the integrated viewer, explicit display-only versus host-activated link policy, accessible structure, bounded parsing/layout, literal raw-HTML and unknown-syntax fallback, and deterministic layout/input checks for malicious markup, links and code containing Markdown. Render source as data; no script execution, implicit network loads or hidden harness dependencies. P7 hover/docs and T034 may consume this viewer without duplicating parsers. PART (D2880): e.ui.markdown_view builds scene items, accessible nodes, links, selection text and control.RichSpans from a Markdown source (raw HTML and reference links literal, images alt text, link policy and scheme allowlist), 40 checks vs markdown-it-py. NOT DONE: a window-level check, shaped-text measurement (fixed one-advance grid), tables. PART (D3304): GFM pipe tables in e.ui.markdown_view (Table/Row/Cell nodes, alignment, selected_text, rich_spans); ui_markdown_view 12 documents match markdown-it-py. Missing: window-level check, shaped-text measurement, content-sized columns. PART (D3603): host text measurement callback and content-sized table columns; ui_markdown_view_fit 12 documents vs a markdown-it-py model. Missing: a real shaper behind the callback, window-level pointer/clipboard check. PART (D4607): ui_markdown_view_window drives the real widget runtime: safe link action once under HostActivated, DisplayOnly/javascript:/data: not pressable, selection to clipboard round trip. Missing: a real shaper, pointer-capturing draw region.

### L067 — Refresh-stable explorer tree adapter over e.ui.collection (90%)

Planning only (D1812). Reference: JustCode src/filetree.js, src/explorer.js and their unit cases. e.ui.collection already has TreeSource stable keys, expanded/selected key lists and virtual tree views; e.text.collate already offers numeric ordering. Reuse them for a generic file-tree adapter with folders-first natural ordering and expansion/selection/scroll retention across refresh, rename and removal. Not yet: integrated filesystem snapshots, collision-safe stable identities, loading/error rows, explicit locale comparator and path-identity policy, and deterministic refresh/rename/delete/large-tree fixtures. Preserve case-sensitive host distinctions; never copy JustCode's unconditional path lowercasing to Linux. Enumeration, path resolution, mutation authorization and recursive-copy containment belong to host filesystem services. No second tree widget or bespoke natural-sort implementation. P7-17's explorer hook consumes this adapter. PART (D2881): e.ui.tree_adapter, a refresh-stable explorer tree over collection.TreeSource (folders-first collation, loading/failed rows, stable keys under rename/refresh/collisions, retain/settle/anchor_offset; 51 checks, a 3,070-node refresh). NOT DONE: lazy loading, enumeration and mutation authorization with host services, locale collation beyond ASCII, a run against a real theme. PART (D3305): policy_unicode name order (NFD, lowering, base letters then accents) and lazy folders (Unloaded/Loading/Ready, keys kept); ui_tree_adapter_unicode 36 names vs a unicodedata model. Missing: host enumeration and mutation authorization, a run against a real theme, language tailorings. PART (D3604): language tailorings (sv/fi, da/nb/no, de, es, pl, cs, tr); ui_tree_adapter_tailored vs .NET ICU for 9 cultures. Missing: host enumeration and mutation authorization, real theme run, more languages. PART (D4608): eight more tailorings (sk, ro, hr, sl, lt, lv, et, is) and CLDR accent order, vs .NET ICU for 17 languages. Missing: hu/sq/mt/vi, host enumeration and mutation authorization, real-theme run.

### T033 — Project source metrics by language with snapshot deltas (90%)

Planning only (D1812). Reference: JustCode src/metrics.js and project_metrics in src-tauri/src/lib.rs. Not yet: a bounded, cancellable project scan counting code/comment/blank lines by language; language-registry/comment metadata reuse; configured ignore, binary/encoding and symlink policies; persisted snapshot comparison and machine-readable/human reports; string/comment/dialect and changed/deleted-file fixtures. Reports must not count themselves, and mixed-language or heuristic classification must disclose its limits. e.metrics is runtime telemetry, not this source-analysis command. Keep traversal, snapshot filenames and reports in tooling; extract a pure source-count helper into an existing text module only when another consumer actually needs it. No editor or project policy in the runtime standard library. DELIVERED (D2311): scripts/source_metrics.py and scripts/source_metrics_test.py (both suites run it): bounded, cancellable scan; per-language code/comment/blank; ignore, binary, encoding and symlink policies; snapshot and compare; JSON and human reports; heuristic languages disclosed. NOT DONE: reuse of a shared language registry (none exists), a Neper-native command.

### T034 — Reattachable harness journal and work-status panel (0%)

Planning only (D1812). Reference: JustCode src/perp.js. Not yet: a tooling panel composed from existing collection/overlay controls and L066's safe viewer, reading persistent journal/status through a supplied adapter; timeline/detail/filter views, follow-tail, path-specific watcher refresh with bounded fallback, absent-harness handling and close/reopen reattachment. Work lifecycle stays in the harness, so closing the panel cannot stop work and reopening cannot lose it. Validate truncated/partial records, journal rotation, stale refresh replies and bounded large-journal reads. Harness discovery, binding validation and typed run/pause/message actions stay outside e.ui; the panel must not invent a second task scheduler. Follow-on (D1898): parallel harnesses also need a claim protocol â€” queue-item checkout plus D-number reservation â€” after two live collisions between sessions sharing one JSON queue. Use generic library view primitives without baking Perpetum or .harness schemas into the standard library.

### T035 — UI resource and command consistency audits (50%)

Planning only (D1812). Reference: JustCode tests/consistency.test.js. Not yet: extend existing Neper validation tools to check icon/resource references, translation-key coverage and duplicate keys, locale placeholder agreement, command/menu callback contracts and mnemonic conflicts. Consume actual resource/command registries and generated manifests; do not claim arbitrary dynamic source references can be proven by regex. Include small malformed-registry cases proving each check fails and wire checks into the existing build/test entry point with actionable locations. Keep repository-specific manifests, rules and CI wiring in scripts/tests; add no runtime validation framework or standard-library dependency. DELIVERED (D2315): scripts/ui_audit.py and scripts/ui_audit_test.py (one malformed manifest per check, run by both suites). NOT DONE: running it against a real registry manifest; the repository has no resource, translation or command catalogue to emit one.

### L098 — Equation (math typesetting) rendering in e.text (98%)

Planning only (D1824). Office-equation parity missing: math-zone layout (fractions, scripts, roots, matrices, operators) over e.text.layout shaping into caller-owned glyph runs for scene/SVG adapters. Display layout first; interactive equation editing stays app-side. Fixtures for nesting, baseline alignment and refusal paths. Follow-on (D1891): LaTeX-math and MathML input formats ride the same layout. PART (D2842): e.text.math typesets a LaTeX-math subset (atom spacing, four styles, fractions, radicals with index, scripts, display limits, \leftight growth, matrices and cases) to a paint-ordered list of glyph and rule items, agreeing with fontTools metrics and TeXbook formulas to 0.01 (about 50 checks). NOT DONE: drawing and any pixel check, MathML, italic math letters, MATH-table constants, extensible-glyph assembly, cramped styles, align. PART (D3101): OpenType MATH constants, cramped styles, MathVariants/GlyphAssembly, italic alphanumerics, align/aligned/gather, typeset_mathml (bit-identical to LaTeX for 12 documents), to_layout; text_math agrees with a Python model over a generated MATH font to 0.02 and the scene pixel check is within 3/255 mean. Missing: \mathbf/\mathcal, accents and braces, MathKernInfo, horizontal variants, real MathML accents. PART (D3702): math alphabets, accents, over/under braces, horizontal variants, MathKernInfo, top-accent attachment, MathML accents; text_math 37 layout cases and 18 MathML pairs vs a Python model. Missing: \substack, equation numbers, ig sizes, composite-base kerning. PART (D4505): \substack, ig sizes, 	ag equation numbers and numbered align/gather, composite-base kerning; text_math 54 model cases, 18 MathML pairs. Missing: MathML input for the new constructs.

### L125 — SVG document rendering in e.gfx (95%)

Planning only (D1881). resvg parity gap (verified: SVG output exists, render does not): SVG path/shape/text document rendering into the scene backend over e.gfx.geometry and text layout. Fixtures against reference rasters with tolerance bounds; filters and scripting stay out. PART (D2843): linear/radial gradients (user-space and box units, gradientTransform, stop-opacity, href stops) on fill and stroke, defs/use/symbol, clip-path over the first shape, units (px pt pc mm cm in em, %), checked against cairosvg (10 documents, mean difference 3/255). NOT DONE: text, <style> sheets, pattern/mask/marker, dashes and even-odd fills (need a scene change: FillPath/StrokePath carry neither), spread other than pad, radial focal point, preserveAspectRatio other than meet. PART (D3100): <style> sheets (simple selectors, specificity), preserveAspectRatio, spreadMethod reflect/repeat, stroke-dasharray/offset, evenodd by nesting depth, pattern fills, markers; gfx_svg_render 22 cairosvg-referenced documents pass (mean diff <= 0.75/255). Missing: text, mask, filters, radial focal point, selector combinators, pattern viewBox/href, group opacity layers. PART (D3701): opacity layers, selector combinators, pattern viewBox/href, radial focal point, luminance masks, text via e.text.layout; gfx_svg_render 36 documents and gfx_svg_text 7 against FreeType. Missing: filters, mask units, font-family and weight, text on a path. PART (D4503-D4504): SVG filters (blur, offset, flood, blend, composite, colour matrix, merge, drop shadow) in scratch targets, mask units and region, font-family/weight/style, textPath; gfx_svg_filter 33 documents (mean <= 0.3/255 vs numpy over cairosvg), gfx_svg_text_faces 14 vs Pillow/FreeType. Missing: feMorphology/Turbulence/Image/Tile/ComponentTransfer/lighting/ConvolveMatrix/DisplacementMap, filter shorthand, nested filters in replays.

### L135 — Micro-slivers: s2, bincode-style codec, magic sniff, shell words, host lookups, signals, byte-unit, rational (95%)

Planning only (D1881). One small-completions item for individually tiny gaps: s2 block codec beside snappy, a bincode-style compact binary codec, magic-number sniff DB over mime sniffing, shell word-splitting, tilde expansion, hostname/users/locale/tz lookups, SIGINT/SIGTERM hooks, byte-unit parse/format and an exact rational type. Each lands with table fixtures; split out any that grows. PART (D2801): e.fmt.bincode, e.text.shlex, e.path.tilde, e.text.bytesize, e.fmt.magic and e.os.ident built, each against an independent model or library. NOT DONE: the S2 codec (no reference), MAC addresses and wider host lookups (hostname, user, locale and zone only); signals and exact rationals already exist in e.os and e.algo.bignum. PART (D3301-D3302): e.fmt.s2 block and framed stream codec vs Go klauspost/compress/s2 (fmt_s2 29 checks), e.os.ident.mac_address on Windows (matches ipconfig) and Linux (one-off WSL run only). Missing: user database (getpwuid), full locale-variable cascade.

### L136 — Terminal emulator engine in e.ui (80%)

PART (D3200): e.ui.terminal, a superset of e.text.terminal (C120) -- wide cells, DSR/DA replies, OSC titles, origin/insert/tab-stop modes, wrapped flags, DEC line drawing, 1049/47/1047 alt screen, snapshot viewport; ui_terminal fixture: 12 scenarios plus a 4 KB generated stream whose buffer hash, cursor and line count equal an independent Python model fed whole and in 7-byte pieces. Missing: PTY ownership, reflow on resize, mouse and key encoding, selection, the widget over e.ui.collection. PART (D3501): reflow on resize, xterm key/mouse/focus/paste encoding, selection model; ui_terminal_ext 1000 cases vs an independent model. Missing: widget over e.ui.collection, PTY ownership, keypad application mode, mouse 1005/1015, kitty/modifyOtherKeys. PART (D4500-D4502): keypad application mode, modifyOtherKeys, kitty keyboard protocol, mouse 1005/1015, selection edge cases, e.ui.terminal_view scrollback adapter over e.ui.collection; ui_terminal_proto 6,964 cases (model is the lane's reading of the protocol texts; no xterm/kitty on this host), ui_terminal_view. Missing: PTY ownership, per-cell colour drawing in the view.

### L148 — Scheduler control: day, week and agenda views (95%)

Planning only (D1890). DevExpress-style scheduler parity missing (pickers exist, no appointment surface): day/week/agenda views with drag-create and recurrence display over e.time.calendar plus L103 rules. Fixtures for layout, overlap columns and accessibility roles. PART (D2882): e.ui.schedule day, week and agenda layouts with recurrence over e.time.recur, all-day band, overlap lanes, hit, slot_at, drag_range and an accessible tree (18 checks vs datetime/dateutil). NOT DONE: month view, multi-day all-day bars, zones and DST, moving appointments, locale names, painting and pointer/keyboard model. PART (D3303): e.ui.schedule month view (build_month, +N more, hit_month, month_move), all_day_bars, move_target, resize_target, focus_next, localized names; ui_schedule_month vs an independent datetime/calendar model over three months and German labels. Missing: zones and DST, painting and pointer dispatch, multi-day bars in the month view, recurring-series moves. PART (D3602): zoned and DST views, multi-day month bars with hit testing, recurring-series moves with refusals; ui_schedule_zones vs zoneinfo, dateutil and a bar model. Missing: painting and pointer dispatch, single-occurrence exceptions. PART (D4606): EXDATE exceptions, cancel_occurrence, move_occurrence, move_series shifting EXDATEs; ui_schedule_exceptions 8 views vs dateutil plus 14 op checks. Missing: painting and pointer dispatch.

### L150 — NodaTime-style dates: non-ISO calendars, patterns, maps (99%)

Planning only (D1890). NodaTime parity gap (verified: TZif parsing present, non-ISO calendars absent): Japanese/Islamic/Hebrew calendar arithmetic over e.time.calendar, pattern-based text parsing/formatting and a Windows to IANA zone map. Fixtures against reference conversions. PART (D2800): e.time.calendars (Julian, Islamic civil, Hebrew vs convertdate; Japanese eras), e.time.pattern (runtime date patterns, 573 checks) and e.tz.winzones (Windows to IANA zone ids). NOT DONE: Persian, Coptic, Thai/Buddhist, Chinese and Umm al-Qura calendars; windows zone mapping beyond territory 001; non-English pattern names. PART (D2450): Coptic and Ethiopic calendars (time_calendars_african, 643 checks vs convertdate). Remaining: Persian, Thai Buddhist, Chinese, Umm al-Qura; zone mapping beyond territory 001; non-English pattern names. PART (D2451): Thai Buddhist calendar (Gregorian + 543; time_calendars_african, 765 checks). Remaining: Persian, Chinese, Umm al-Qura. PART (D3300): Persian (33-year rule, matches astronomical calendar 1278..1502 AP) and Umm al-Qura (1343..1500 AH) calendars; time_calendars_persian_uq 644 checks vs convertdate/hijridate. Missing: Chinese calendar, zone mapping beyond territory 001, non-English pattern names. PART (D3600-D3601): e.time.chinese 1900..2100 from Meeus astronomy vs lunar_python (201 years, 9 years daily), territory zone rows vs .NET and Babel, e.time.names CLDR names for 27 languages (868 vectors vs Babel). Missing: region variants, genitive month forms, Chinese outside 1900..2100. PART (D4605): e.time.names 52 rows (27 languages and 25 regional/script variants, 159 identifiers) with locale_index resolution and genitive/stand-alone month forms; time_pattern_locales 1,909 vectors vs Babel. Behaviour change: ru MMMM without a day is nominative. Missing: further locales beyond Babel's CLDR subset.

### T036 — OpenCode harness skill and agent routing (80%)

Planning only (D1898). No .opencode skill, no AGENTS.md route to the card or context-file (patch.exe only): OpenCode agents land without the context-file-before-reads and card-first discipline T026 requires elsewhere. Add the skill, the AGENTS.md pointers and a first-run smoke check that an agent reaches context-file, patch and check-fixture without full-file reads. DELIVERED (D2312): .opencode/skills/neper/SKILL.md, AGENTS.md OpenCode route, scripts/check_agent_routes.py run by both suites. NOT DONE: a live OpenCode first-run smoke (static routing check only).

### T039 — T2.0 foundations: snapshots, cache identities, bounded transport (80%)

Planning text of D1954; AUDIT (D2319, from decision titles, acceptance runs not re-executed): most of the slice has landed under earlier C-items -- H15: D369 policy identity, D398 compiler identity, D407/D436 snapshot named by results, D431, D502 overlays, D507 candidate keys, D1518, D1519 apply-plan transaction, D1526 batch snapshots/pins/eviction/stale keys; H16: D372, D399/D496 deadlines, D409/D410 batch, D558/D559 retained memory and 10,000 queries, D947, D1527; H18: D370 bounded run capture, D1525 chunked capture, D400 byte-bounded context pages, D432 fixes carry preconditions, D454/D561 progress ordering; H24: D341 fuzzing and nesting, D343 atomic publication, D368 corrupt artifacts named, D435 cache fault injection, D472, D474 whole-build budget. post-m2-llm-hardening T2.0 slice missing from the queue: immutable snapshots, complete cache identities, bounded request/result storage, cancellation, compact transport and hardened artifact publication (H15/H16/H18/H24). Pickup immediately after the chart cluster (L061, L068-L075). Versioned schema from the start; later slices extend it only by capability. FIRST SLICE (D2319): `info --json --capabilities` lists every command with its group, the stream versions, bounding flags and the snapshot field; golden in tests/conformance/tools/capabilities.expected.jsonl, both suites. NOT DONE: per-command schema versions and bounds, the versioned edit/fix schema with expected-source hashes, bounded run --json capture, H15/H16/H24 acceptance runs. ACCEPTANCE ROWS FOUND (D2319 follow-up): the suite carries fault injection for apply (--fault-apply), cancellation (--fault-cancel), hash collision (--fault-collision), a worker running dry (--fault-dry, six rows), an interrupted edit (--fault-edit) and cache writes (--fault-write), the ten-thousand edit/query/revert soak under a fixed budget (run.ps1 batch soak), -j 1 versus -j 3 --perturb byte equality, and the seeded Windows run reached them green (run 16, D2317). REMAINING GAPS, named: no test of a source file changing between the lazy read of two modules of one check (a mixed-version snapshot), no queued-request saturation test (there is no request queue to saturate: `query-batch` is one process, one request at a time), and package-resolution/generator-input identity waits on M6. SUITE (run 18): the capabilities golden and the schema validation pass on Windows.

### T040 — T2.1 understand and check: context, queries, provenance, diagnostics (5%)

Planning only (D1954). T2.1 slice missing: compiler-derived context, reusable semantic queries, generated provenance, compiled guidance, unsafe enumeration, tiered checks, optimization explanations and causal/recoverable diagnostics. Pickup immediately after the chart cluster. Freeze latency/startup/resource budgets before implementation. FIRST STEP (D2316): latency budgets frozen in docs/tooling-budgets.md from scripts/measure_tooling_latency.py (small program 55-90 ms; src/main.e check 450 ms, index 1.3 s / 11.8 MB, module context 1.6 s). NOT DONE: every other T2.1 obligation (compiler-derived context beyond context-file, reusable queries, provenance, compiled guidance, unsafe enumeration, tiered checks, optimization explanations, causal diagnostics) and memory budgets.

### T041 — T2.2 edit and test evidence: plans, contracts, structured tests (15%)

Planning only (D1954). T2.2 slice missing: transactional semantic plans, structured tests, change contracts, flaky-test semantics, runtime failures and compatibility diffs. Terminal state without T2.3 trust evidence is incomplete, never verified. Pickup immediately after the chart cluster. FIRST SLICE (D2320): `test-file`/`test-project ... --json --compact` leaves passing `test` records out of the v1 stream, summary unchanged; conformance row in both suites. NOT DONE: test plans with identities and selection reasons, executed/cached/not-run evidence, structured expected/actual, setup/cancellation outcomes, output artifacts, change contract, flaky semantics, runtime failures, compatibility diff. SECOND SLICE (D2321): `test-impact-file ... --why` adds `via`, the reason a test was selected; goldens impact_why and impact_local_why in both suites. THIRD SLICE (D2322): `--retries N` re-runs a non-passing test and reports `test_retry` for every test that ran more than once (H39); flaky fixture flaky_test.e, both suites. Still open: executed/cached/not-run evidence, structured expected/actual values, setup/cancellation outcomes, output artifacts, change contract (H35), runtime failures (H41), compatibility diff (H42). SUITE (run 18, seeded Windows, static gate and live-API assertion excluded): the --compact, --why and --retries rows, the flaky fixture and the capabilities golden all pass.

### T042 — T2.3+T2.4 trusted host: policy, verified receipts, durable tasks (60%)

Planning only (D1954). Reference host tools/neper-agent-host/ missing: policy and sandbox mediation, environment identity, scoped verified receipts (one exact change contract per receipt), isolated parallel change bundles and durable authorized tasks across reconnect and approval. First slice allowed to emit verified. Pickup immediately after the chart cluster; compiler declares facts, host owns authority. FIRST SLICE (D2323): lib/x/agent/contract.e, the H35 change contract (parse fail-closed, canonical form, SHA-256 identity, verdict, amendment link), fixture x_agent_contract (267 cases against an independent reference), both hosts. NOT DONE: policy and sandbox mediation, environment identity, change bundles, receipts, durable tasks, the host. SECOND SLICE (D2324): lib/x/agent/environment.e, the H37 environment manifest (secrets only as hashes, hermetic/observed/uncontrolled with named omissions, identity over the core, observation kept apart), fixture x_agent_environment (265 cases, the perturbation acceptance), both hosts. NOT DONE: replay description, the host that observes a real run, policy/sandbox mediation (H36), change bundles (H38), receipts and durable tasks (H44). THIRD SLICE (D2325): lib/x/agent/policy.e, the H36 action policy (most-specific decision, path classification, audit verdicts with fail-closed unenforced, HMAC approvals with expiry/replay/scope, redaction), fixture x_agent_policy (1259 cases), both hosts. NOT DONE: OS sandbox mediation and the executor that observes effects, replay description, change bundles (H38), receipts and durable tasks (H44). FOURTH SLICE (D2326): lib/x/agent/bundle.e, the H38 change bundle and integration verdict (stale/conflict/incomplete/clean with structured causes, combined identity, never verified), fixture x_agent_bundle (364 cases), both hosts. NOT DONE: identities derived from the compiler's index, candidate re-planning operations, OS sandbox mediation and the observing executor, replay description, receipts and durable tasks (H44), the host. FIFTH SLICE (D2327): lib/x/agent/receipt.e, the verification receipt (unbound/unsafe/unhermetic/failed/incomplete/verified, cached never fresh), fixture x_agent_receipt (364 cases), both hosts. NOT DONE: the host that runs obligations and observes effects, OS sandbox mediation, durable tasks (H44), replay description. SIXTH SLICE (D2328): lib/x/agent/task.e, the H44 durable task state machine (unguessable owner-bound handles, monotonic status, terminal results never rewritten, bound single-use input), fixture x_agent_task (381 cases), both hosts. NOT DONE: the transport that serves handles, retention/reclamation, the host that runs obligations and observes effects, OS sandbox mediation, replay description. SUITE (run 19, seeded Windows, static gate and live-API assertion excluded): the six x_agent_* rows pass in run.ps1 together with x_migrate, the capabilities, --compact, --why and --retries rows; the run stopped later at a NeperOS thread-order assertion (D-free fix in 9e3587d2, interleaved scheduler output).

### L163 — Fast, small PNG encoding: dynamic Huffman, lazy matching and table CRC (85%)

Backlog from the chart benchmark (D2108, D2110). On the same 360x240 chart raster, e.fmt.png at .Balanced takes about 18 ms and writes 14,004 B, while zlib level 6 with the same filter-0 rows takes 1.74 ms for 11,283 B; rasterizing takes 2.0 ms, so the encoder is the whole PNG gap to matplotlib. e.algo.deflate writes fixed-Huffman blocks only (zlib restricted to fixed Huffman gives 12,903 B, so dynamic trees are worth about 1.6 KB here), has no lazy matching and restarts its 16-deep hash chain at every 32 KiB block (about 1.1 KB more), and e.fmt.png computes CRC-32 bit by bit. Done when: e.algo.deflate writes dynamic-Huffman blocks with lazy matching and a window that spans blocks, round-tripping through its own decoder and Python's zlib on a corpus; e.fmt.png uses a table-driven CRC; the chart benchmark's PNG pass is at least as fast as matplotlib's with files no larger than zlib level 6 on the same rows; both suites pass. Adaptive per-row filters are optional: Pillow's heuristic made this chart larger. PART (D2840): e.algo.deflate is zlib's lazy matcher (levels 6 and 9, 64 KiB window across blocks, stored/fixed/dynamic Huffman per 16383-token block); round-trips against Python zlib on 15 inputs x 3 levels, byte-identical to zlib 6 on four inputs, benchmark chart IDAT 11,277 B vs 11,283; e.fmt.png table CRC and deferred Adler. NOT MET: encoder alone about 5x C zlib (9.6 ms vs 1.7 ms on the 345,840-byte raster); the 'at least as fast as matplotlib' criterion is met only by a same-day comparison, not the nine-run protocol; adaptive PNG row filters not built. PART (D3700): png.encode_adaptive with libpng min-sum row filters and indexed output; fmt_png_adaptive byte-identical to Pillow on non-indexed cases, smaller than zlib 6 plus 1%. Missing: the deflate matcher is still ~4x C zlib, the nine-run protocol. PART (D4400): deflate/PNG encode about 2x faster with byte-identical output (callgrind 2.97 G -> ~1.5 G instructions, 800x500 adaptive ~225 -> ~120 ms wall, 48-case old/new differential identical, algo_deflate/fmt_png/fmt_png_adaptive/fmt_zlib/fmt_gzip pass). Still ~1.5-2x C zlib; nine-run protocol not run.

### C153 — NeperOS Camera remainder: the sensor feed, video files, flash and exposure hardware, the QR reader (0%)

Split from C122 (D2397): the Camera writes photos and straightened scans as PNG files in /DCIM that Photos lists, with focus ring, exposure steps and a timer. Acceptance: (1) a camera driver server (virtio-video or USB video under QEMU, the Pixel camera later) delivering frames to the viewfinder at a steady rate, front and rear chosen from the devices found; (2) video recording with a codec from the library and audio from e.audio, written as a file Photos plays; (3) focus, exposure, flash and HDR stacking as far as the hardware has them; (4) Scan mode's QR reading (L137) opening the code's content, and a scan offered to Wallet documents (C121); (5) a fixture on QEMU against a test video source. Not queued here: portrait blur, night mode, RAW capture.

### C154 — NeperOS Wallet remainder: encrypted storage, MRZ from an image, editing, camera scanning (85%)

Split from C121 (D2402): Wallet draws real QR and Code 128 symbols, validates its form with e.valid, and shows the newest Camera scan on a document. Acceptance: (1) the cards kept encrypted at rest under the Secure vault's master password (the vault module's derive/seal over the filesystem server), with no card number beyond the last four digits unless the user asks, loaded at start and fixture-tested through an encrypted round trip on a disk; (2) editing an existing card or document with the same validation; (3) Camera Scan mode feeding frames to e.barcode.qr_scan and offering the decoded text (a pass, a URL) to Wallet or the browser; (4) a machine-readable zone read from a scanned page (the OCR-B glyphs) and checked by e.valid.mrz_td3; (5) a scan stored with its own document instead of the newest one; (6) expiry checked against the clock. PART (D2447): a card's expiry is checked against the clock (Expired status; fixture wallet). Remaining: encrypted storage under the Secure master password, editing, Camera Scan mode, MRZ from an image, a scan per document. PART (D3807, D3808): cards sealed under the Secure vault key with an unlock screen, edit card for payment/bank/document, scan stored per document; disk chain secure_vault -> secure_vault_more -> secure_vault_again passes (12 records, expiry edited) and camera_scan -> camera_scan_more passes. Missing: Camera scan mode feeding qr_scan, MRZ from an image (no OCR-B recogniser), password prompt when no vault exists. PART (D4810-D4814): Camera Scan reads a QR into /scancode and Wallet adds it as a card (camera_scan, camera_scan_later); master-password create flow when no vault exists (wallet_vault_create, wallet_vault_create_again); save a card code as PNG to Files (wallet_image); MRZ read from a scan (wallet_mrz; mrz_read matches the reference reader exactly; gfx_vision +3 page reads). Remaining: a real OCR-B passport page untested (font unavailable), Camera 186x300 scan sheet too small for MRZ, TD1/TD2 zones, vault password change, opening a QR URL in the Browser.

### C155 — NeperOS SSH remainder: Secure credentials and Keychain, saved hosts, port forwarding, SFTP, keys (50%)

Split from C120 (D2406): the SSH app opens a live session (password login, host key confirmation for the run, a terminal grid). Acceptance: (1) the password and ed25519 keys kept in Secure (C116) behind the master password, a Keychain tab to create and import keys, and key login from the app; (2) known hosts and saved hosts kept in storage (C125) with groups, tags and snippets, and a host key changed after it was saved refused; (3) Esc, Ctrl and a symbols row on the keyboard, a monospaced face and a scrollback view, the terminal answering cursor position requests; (4) port forwarding (local and remote) and SFTP (browse, download, upload); (5) aes-gcm and rekeying in e.net.ssh; (6) a fixture on QEMU against an OpenSSH server in WSL or a container. PART (D4104): saved hosts, trusted host keys on disk, changed key refused, AES-GCM and rekey in e.net.ssh; ssh_saved, ssh_saved_again, ssh_trust, ssh_trust_again, ssh_changed pass. Missing: keys in Secure/Keychain, port forwarding, SFTP, terminal key row and scrollback. PART (D5101-D5103): e.net.ssh subsystem and direct-tcpip verified by net_ssh against asyncssh; ssh_keys_novault/ssh_keys_vault pass; ssh_sftp, ssh_key, ssh_terminal_keys unrun on QEMU. Remaining: port forwarding screen, OpenSSH key import.

### C156 — NeperOS Weather remainder: the current location and weather alerts (75%)

Split from C119 (D2408): Weather shows live Open-Meteo forecasts for places the user adds, kept in storage with the unit. Acceptance: (1) the current location as a place by the user's choice once the location service exists (C131: GPS or network location, a permission the user grants); (2) alerts for a place from a source that has them (the Norwegian MET API's alerts, or a national feed), shown on the main screen and as a notification (C106), checked against recorded responses. PART (D2452): e.fmt.cap reads Common Alerting Protocol alerts (fmt_cap, 74 checks vs ElementTree). Remaining: the alert source and place-to-area match in Weather, the notification, and the current location (C161). PART (D3902): MetAlerts alert list and its CAP resource read with e.fmt.cap, headline in a red bar; weather_alert passes. Test server alert JSON is written from the documented shape, not captured. Missing: notification (no status-service grant), current location, other feeds. PART (D4930-D4932): NWS alerts for US places, MET for Oslo, the alert notification, current location as a place; rows weather_notify, weather_here. Remaining: other national feeds, location permission UI.

### C157 — NeperOS Call remainder: telephony and audio, shared contacts, voicemail, notifications (15%)

Split from C127 (D2409): the Call app keeps contacts as a vCard file with New, Edit and Delete. Acceptance: (1) a telephony server over the modem or a SIP/VoIP stack on C117 networking (needs UDP in the network server): dial, answer, reject, hold, mute, speaker, DTMF, call waiting and conference; (2) the in-call audio path through e.audio with the earpiece, speaker and Bluetooth routes; (3) the contact store read by Messages, Mail and Wallet, with favorites, search, and vCard import and export through Files; (4) recents kept across restarts, missed-call notifications through the status server, Do Not Disturb honoured; (5) voicemail and visual voicemail; (6) emergency numbers always dialable; (7) a fixture on QEMU against a loopback SIP server that dials, answers and ends a call and checks the audio frames. PART (D5005): recents kept in /recents across restarts, 112/911/999 shown as Emergency; rows call_recents(_again), call_emergency. Remaining: telephony/SIP and audio path, shared contact store for Messages/Mail/Wallet, favorites and search, missed-call notifications and DND, voicemail, SIP loopback fixture.

### C158 — NeperOS Mail remainder: accounts, folders and threads, HTML and attachments, notifications (70%)

Split from C128 (D2413): Mail syncs the INBOX of a fixed test account over IMAP and sends over SMTP, on TLS, and marks read and deleted on the server. Acceptance: (1) accounts added in the app (server, user, password kept in Secure, C116), OAuth for the large providers, several accounts, folder list and sync, IDLE or polling for push; (2) threads, labels, search, archive, mark unread and swipe actions done on the server; (3) rich messages: MIME multipart, HTML rendering through the Document engine (C123), inline images, attachments saved into Files (C125) and opened in their apps; (4) compose with attachments from Files, Photos and Camera, drafts, signatures and the contact picker (the vCard store, C127/C157); (5) notifications through the status server and a badge on the icon; (6) a fixture against the test IMAP and SMTP server that fetches, threads, searches, replies with an attachment and checks the sent message. PART (D2448): MIME bodies (multipart/alternative, HTML-only, quoted-printable) shown as text through e.fmt.extract; fixture mail_live. Remaining: HTML rendering through Document, inline images, attachments, compose with attachments, accounts/folders/threads, push. PART (D3903): Mail lists and saves multipart attachments (mail_attach, base64 menu.txt); verified on the pre-L125 image, and D2470 now lets the grown Mail image launch. Missing: HTML via Document, inline images, compose attachments, accounts, folders, threads, push. PART (D4900-D4906): mailboxes and folder switch, HTML newsletter with inline PNG, threads, accounts kept in /mail_accounts, compose with attachment, search/unread/archive on the server, polling plus notification, Open in Document; rows mail_html, mail_threads, mail_document, mail_open_attachment, mail_accounts(+_again), mail_attach(+_again), mail_actions, mail_push, mail_live_delete(_after) passed before the master merge (post-merge live rows unrun: CA mix-up with another lane host service). Remaining: OAuth, Secure-stored passwords (C116), drafts/signatures/contact picker, IDLE, Camera/Photos attachments, icon badge.

### C159 — NeperOS Browser remainder: CSS layout, images, forms, cookies, storage and downloads (70%)

Split from C129 (D2415): the Browser fetches an address over HTTPS and shows its HTML as lines of text with links. Acceptance: (1) HTTP/1.1 redirects, cookies, a cache, HTTP/2 and plain HTTP, the system proxy settings; (2) a CSS layout engine over e.fmt.css and e.fmt.html (block, inline, flex, grid, the common properties) painting through e.gfx.scene with shaped text, images (PNG, JPEG, SVG) and fonts; (3) forms and their submission, history, bookmarks, tabs that survive a restart (C125 storage), incognito, search suggestions and a chosen search engine; (4) downloads into Files and opening files in their apps; (5) permissions per site tied to Settings (C126); (6) a fixture against a local web server with a page that has an image and a form and a redirect. PART (D2455): e.net.cookie, an RFC 6265 cookie jar (net_cookie, 28 events vs an independent model). Remaining: the Browser using it (persisted store, request/response hooks), redirects and cache, CSS layout, forms, tabs, downloads. PART (D2456): the Browser keeps cookies in a jar that owns its strings and sends them (fixture browser_cookie, live); httpc.Reply carries the header block. Remaining: persisting the jar, redirects, cache, CSS layout, forms, tabs, downloads. PART (D2457): redirects followed (up to five hops, cookies kept at each; fixture browser_redirect, live). Remaining: persisting the jar, cache, HTTP/2, CSS layout, forms, tabs, downloads. PART (D2458): the persistent cookies are kept in /cookies across restarts (livediskfixture browser_jar and browser_jar_again). Remaining: cache, HTTP/2, CSS layout, forms, tabs, downloads, per-site permissions. PART (D3900): Browser fetches and draws an SVG <img>, submits a GET form (text and hidden fields), saves a non-page reply to /Downloads and reads it back; browser_form passes. Missing: POST, field editing, PNG/JPEG images, cache, HTTP/2, CSS layout, tabs across restart, permissions. PART (D4910-D4916): POST forms and field editing, PNG/JPEG images, ETag cache with 304, CSS cascade, tabs kept across restart, bookmarks, download opened in Document; rows browser_post, browser_images, browser_cache, browser_css, browser_tabs(+_again), browser_bookmark(+_again), browser_open_download. Remaining: HTTP/2, flex/grid layout, incognito, search engine and suggestions, per-site permissions.

### C160 — NeperOS Maps remainder: map data, location, search and turn-by-turn navigation (65%)

Split from C130 (D2417): Maps routes over a small road graph with the library's Dijkstra and draws the way. Acceptance: (1) map data on the device: vector tiles or OpenStreetMap extracts rendered through e.gfx.scene with labels, icons, zoom levels and rotation, offline regions kept in Files, and drag and pinch (the touch layer needs both); (2) a location service (GPS and network location on the Pixel, a simulated provider under QEMU) with its permission in Settings (C126); (3) search by name and category with suggestions, place cards with hours and photos from the network; (4) routing for walking, cycling, driving and transit over the road graph with turn-by-turn instructions, rerouting and voice; (5) saved places, recent searches and a Home and Work shortcut shared with Wallet and Weather; (6) a fixture that loads a small offline region, finds a place and routes to it, checking the route length. Data source (user, 2026-10-11): free, non-Google maps -- OpenStreetMap (ODbL, attribution shown in the app): regional extracts (Geofabrik) or Protomaps/OpenFreeMap vector tiles cached in Files, the road graph built from the extract's highways, search from the extract's names (Nominatim only for light, identified use under its policy), no heavy use of tile.openstreetmap.org. PART (D2454): e.fmt.mvt decodes Mapbox Vector Tiles (fmt_mvt, 36 checks vs an independent encoder). Remaining: drawing tiles with styles and labels, offline regions, the road graph from the highway layer, search, location, navigation. PART (D3904): Maps fetches a zoom-14 vector tile, decodes it with e.fmt.mvt and draws roads, water and POI names with the ODbL line; maps_tile passes against an independent tile encoder. Missing: tile pyramid and panning, offline regions, road graph, search, location, navigation. PART (D4920-D4923): tile pyramid with pan and zoom, offline regions in Files, Nominatim search plus OSRM route with steps, location via the sensor server; rows maps_pyramid, maps_offline(+_again), maps_search, maps_location. Remaining: road graph from an extract, walking/cycling/transit, saved places, rerouting and voice, rotation/pinch.

### C161 — NeperOS sensors remainder: a sensor server and drivers, the gyroscope, GPS and the location service (85%)

Split from C131 (D2420): the settings server serves a scripted magnetometer and accelerometer trace, the Compass computes its heading from it with calibration and the model's declination. Acceptance: (1) a sensor server of its own (not the settings server) for the magnetometer, accelerometer and gyroscope, with a scripted source under QEMU and the Pixel's sensor hub later, delivering readings at a fixed rate through its own capability, a rate per client and a permission per sensor; (2) the figure-eight calibration run on live data with the accuracy it reaches shown; (3) a location service (GPS and network) shared by Compass and Maps (C130/C160) with the permission in Settings and a simulated provider; (4) a fixture on QEMU feeding a recorded sensor trace and checking the heading to a degree. PART (D4000-D4007): sensor server with stamped requests, per-client stream rates and permissions; compass, compass_fix, compass_replay, level_stream, steps_replay, settings_permission boot rows pass (compass_replay flaked under load, passed quiet). Missing: real sensor hardware (the hub is scripted).

### C162 — NeperOS Level remainder: fast sensor stream, self-test, orientation modes, feedback (90%)

Split from C132 (D2421): Level filters the accelerometer and gyroscope of the sensor service with a complementary filter and keeps its calibration. Acceptance: (1) the sensors read at 50 Hz or better from the sensor server of C161 (the half-second tick of the scripted source is too slow for a real filter); (2) a Kalman filter in the library next to the complementary one, and a self-test on a flat surface that reports the sensor's noise and bias; (3) Level, Angle and an edge mode switched from the real orientation; (4) the readings in degrees, per cent slope and a ratio, and a beep or vibration when level; (5) a fixture feeding a recorded trace and checking the reading to a tenth of a degree. PART (D2444): e.control Kalman filter (kalman_new/start/step) and noise_bias self-test, checked against an independent 2x2-matrix implementation (control_kalman). Remaining: the 50 Hz stream from the sensor server, Level's modes, readings and feedback, a recorded-trace fixture. PART: level, level_stream, level_selftest, level_kept, level_kept_again boot rows pass.

### C163 — NeperOS Flashlight remainder: a finer timer, quick toggles, patterns, torch policy (80%)

Split from C133 (D2422): the Flashlight drives a simulated torch through the settings server. Acceptance: (1) a finer timer (a 10 ms tick or a timer capability in the kernel) so a Morse unit can be 100 ms and a strobe can reach 10 flashes a second, with a speed control; (2) a quick toggle from the status bar and the lock screen; (3) patterns kept as a list the user can add to; (4) the torch turned off when the camera opens (the camera server of C153) and on a timeout, and the flash-mode permission check; (5) a fixture that sends a message and checks the beat times against the unit. PART (D4014): flashlight, flashlight_beats, flashlight_strobe, flashlight_timer, flashlight_kept(_again), lock_torch, camera_torch and the new status_torch (status-bar Torch pill) pass; flashlight_timer flaked once under load.

### C164 — NeperOS Chat remainder: TLS, accounts and presence, history, files, encryption (55%)

Split from C134 (D2423): the Chat app talks to a loopback WebSocket server for the general room. Acceptance: (1) wss with a way to poll a TLS connection from an app (the network server's poll is plain TCP only), accounts, rooms and direct messages as the server has them, presence and typing indicators, delivery and read marks; (2) message history in storage (C125), search, threads, mentions, reactions kept on the server, edit and delete; (3) files and images from Files and Camera, link previews; (4) notifications through the status server with per-room settings (C126); (5) voice and video from a room opens Meet (C135); (6) end-to-end encryption with keys in Secure (C116); (7) a fixture across two clients. PART (D4105): wss with TLS polling, presence, typing, delivered marks, history on disk; chat_tls, chat_tls_again, chat_presence pass. Missing: accounts, search/threads/reactions, files, notifications, Meet hand-off, E2E, two-client fixture. PART (D5105, D5106): accounts, ids, reactions, threads, search and a second client are committed; chat_search and clipboard_long pass on QEMU, chat_two/chat_account/chat_account_bad unrun. Remaining: files and images, server history, notifications, E2E.

### C165 — NeperOS Meet remainder: media transport, capture, codecs, screen sharing (0%)

Split from C135 (D2424): Meet signals over a WebSocket and shows the people and the speaker the server names. Acceptance: (1) media over C117 (needs UDP in the network server): a WebRTC-style stack (ICE, DTLS-SRTP) or a simple SFU protocol; (2) capture: the camera frames from the camera server (C153) and the microphone from e.audio, encoded and sent with a codec from the library, the received streams decoded into the tiles; (3) the speaker and grid layouts follow the audio levels; (4) screen sharing from the compositor, raise hand visible to others, chat in the meeting (C134/C164), captions; (5) echo cancellation, noise suppression and bandwidth adaptation; (6) a fixture with two clients in one machine against a relay that exchanges test frames and checks them.

### C166 — NeperOS Recorder remainder: the microphone and speaker, transcription, background recording (40%)

Split from C136 (D2425): the Recorder keeps WAV files of a scripted microphone and plays their bytes back. Acceptance: (1) capture from the microphone and playback to the speaker through e.audio (an audio server with a device under QEMU and the Pixel's later), the level meter driven by the real samples; (2) Opus or a compressed format from the library, rename, share and delete, search by name; (3) a speech-to-text model on the device or on a server (C117) for the transcript with words timed to the playhead and tap-to-seek; (4) recording in the background with a notification and the lock-screen control; (5) a fixture that records from a scripted audio source and plays it back checking the bytes at the device. PART (D5003): microphone and speaker owned by the services process, a recording goes on without its app. Remaining: transcript with words timed to the playhead and tap-to-seek, lock-screen control, scripted-source record-and-play fixture.

### C167 — NeperOS Translate remainder: a real model, more scripts and inputs, history and speech (20%)

Split from C137 (D2426): Translate asks a dictionary server for text outside its phrase book. Acceptance: (1) translation by an on-device model from the ml modules or a real server, at least forty languages with auto-detect and offline packs kept in Files (C125); (2) fonts and shaping for Arabic, Devanagari, CJK, Cyrillic, Greek, Thai and Hebrew added to the font set the apps load; (3) input by voice (C166's speech engine), by camera (text recognition in e.gfx.vision on a Camera frame, C153) and by handwriting; (4) history and saved phrases, copy and share, speak the result through e.audio; (5) conversation mode with two languages on the two halves of the screen; (6) a fixture that translates a fixed sentence with a small test model and checks the output text. PART (D5004): Russian and Greek via DejaVu glyphs merged into Jost (8 languages), history of 8 and saved phrases in /translate, Copy to the clipboard; rows translate_scripts, translate_history(_again), translate_copy. Remaining: 40 languages and an on-device model, Arabic/Devanagari/CJK/Thai/Hebrew shaping, voice/camera/handwriting input, conversation mode, speech output, small-test-model fixture.

### C168 — NeperOS Steps remainder: background counting, history, profile, notifications (85%)

Split from C138 (D2427): Steps counts a walk with the library's pedometer from a scripted accelerometer stream and keeps today's total. Acceptance: (1) counting in the background at a low-power sensor rate from the sensor server (C161), with the run and walk classification shown; (2) the history of days, weeks and months in storage (C125), the goal, streaks and a weekly report; (3) calories from the user's height and weight (a profile in Settings, C126) rather than a fixed figure per step; (4) a notification when the goal is reached through the status server and a widget on the home screen; (5) a fixture that replays a recorded accelerometer walk and checks the count within two per cent. PART (D2444): e.algo.pedometer distance_m and calories_kcal from height and weight (algo_pedometer_energy). Remaining: the Settings profile, background counting, history, notification and widget, the recorded-walk fixture. PART (D2449): the week's history kept in /steps and rolled forward by the days passed (e.algo.pedometer.roll_week; fixtures algo_pedometer_energy, steps_kept, steps_kept_again). Remaining: Settings profile, background counting, month view, notification/widget, recorded-walk fixture. PART: steps, steps_kept(_again), steps_replay, steps_month pass. Missing: the home-screen step widget (built, reverted: it made the shell stall after an app returned; shell/compositor tick path suspected). PART (D5000): home-screen step widget refreshes every thirty seconds; the shell stall was scene storage taken from the arena the shell resets. Remaining: real sensor hardware (scripted hub).

### C169 — NeperOS Blocks remainder: fast fall, held keys and drags, score board, sound (95%)

Split from C139 (D2428): Blocks has hold, ghost, kicks and a saved best score. Acceptance: (1) a finer timer (C163) so the fall reaches 20 rows a second at high levels, and auto-repeat on held buttons plus drags and swipes (the touch layer needs press, move and release events); (2) a score board of the best games and the last game kept in storage; (3) sound effects and music through e.audio (C166); (4) a fixture that plays a scripted sequence with the fixed seed and checks the score and the lines; the name stays Blocks (never Tetris). PART (D2445): the score board (five best games and the last game in /blocks, game-over card, fixtures blocks_board and blocks_board_again). Remaining: the finer timer, held keys and drags, sound, the scripted-sequence fixture. PART (D4016): blocks, blocks_kept(_again), blocks_board(_again), blocks_script (score 286), blocks_drag, blocks_swipe, blocks_hold pass; Fall: manual restarts with the fixed seed, held keys repeat from the end of a frame. Missing: sound.

### C170 — NeperOS Secure remainder: HOTP, QR and export, clipboard and autofill, biometrics, breach check (70%)

Split from C140 (D2429): Secure has the encrypted vault, SHA-1/256/512 codes of 6 to 8 digits with their own period, and otpauth import from /otpauth.txt. Acceptance: (1) HOTP entries with a counter that advances on use; (2) the otpauth URI from a QR scan (L137, C122) and an export (an encrypted file and the common authenticator formats); (3) a clipboard service with a timed clear and autofill of a login into the Browser (C129) and other apps through a capability; (4) fingerprint and face unlock (C126 settings) with the master password as the fallback, and auto-lock on timeout; (5) a password generator with options and a breach check by hash prefix over C117; (6) Wallet's cards and Dynamic's API keys kept here; not queued: sharing a vault, passkeys. PART (D2442): HOTP entries (counter kept and sealed, Next moves it), several otpauth URIs imported from /otpauth.txt, fixture secure_import (TOTP SHA-256/8 digits/45 s and HOTP counter 3). Remaining: QR scan and export, breach check, fingerprint/auto-lock, Paste beyond AI (C175). PART (D4100-D4101): QR symbol shown, export and breach check by hash prefix over TLS; secure_export and secure_breach pass; auto-lock in code (no marker in a passing row). Missing: QR scan from the camera, fingerprint/face unlock, clipboard/autofill service, Wallet and API keys kept in Secure. PART (D5100): Secure Scan reads an otpauth QR from a Camera frame (row secure_scan passes). Remaining: fingerprint/face unlock, clipboard/autofill service, Wallet and API keys kept in Secure.

### C171 — NeperOS AI remainder: streaming, keys in Secure, conversations, files and tools (50%)

Split from C141 (D2430): AI sends a conversation to a provider and shows the answer. Acceptance: (1) the reply streamed (server-sent events) into the bubble, which needs the network layer to read a response incrementally and the compositor's ticks to keep arriving during a request; (2) the API key kept in Secure (C170's store), never in memory longer than a request, and a cheap key check on Save; (3) conversations kept in storage (C125) with titles, search, rename and delete, system prompts, and temperature and token limits as settings; a configurable host for the local server; (4) images from Camera and Photos, files from Files and documents from Document as inputs, and the reply's code blocks highlighted; (5) a tool-use loop so a conversation can call other apps through capabilities, each with a confirmation; (6) a fixture against a mock server that streams a reply and checks the error paths for each provider's status codes. Not queued here: voice mode, image generation. PART (D2453): e.fmt.sse, an incremental Server-Sent Events reader (fmt_sse, 46 checks vs the standard's algorithm on whole streams and every prefix). Remaining: incremental reads from the network server over TLS, streaming into the bubble, keys in Secure, conversations, files, tools. PART (D4102-D4103): reply streams into the bubble over TLS (ai_stream), key checked and sealed in the Secure vault (ai_secure, ai_secure_again), conversations and options kept. Missing: images/files as inputs, tool-use loop, per-provider error-path fixture. PART (D5101, D5102): attachments, tool loop and per-provider error words are committed with a host test server; rows ai_err_anthropic/openai/google, ai_attach, ai_tools are NOT yet run on QEMU. Remaining: those boots.

### C172 — NeperOS Document remainder: PDF painting, zoom, tables, HTML view, spreadsheets (75%)

Split from C142 (D2431): Document reads the text of PDF, Word, PowerPoint and OpenDocument files and renders Markdown and highlighted code. Acceptance: (1) PDF pages painted, not just their text: fonts and text positioning, vector paths and images through e.gfx.scene, with the outline, search and page jump; (2) pinch zoom and pan (the touch layer needs press, move and release events); (3) CommonMark with tables in the Markdown parser and an HTML view shared with Mail (C128) and the Browser (C129); (4) Word and PowerPoint tables, images and slide shapes, and spreadsheets (.ods, .xlsx) as grids; (5) open from Mail attachments and the Browser's downloads, an open-with and share sheet, and Dynamic's source view using the code view; (6) a fixture on QEMU that opens a real PDF, DOCX and PPTX and checks what is drawn. Not queued here: editing, annotation, signing. PART (D3800-D3802, D3809): PDF painting, Markdown tables, xlsx as a grid (sheet_names/sheet_grid), Word tables; QEMU rows document_sheet, document_mdtable pass. Missing: pinch zoom/pan, HTML view, .ods grid, PPTX shapes, Word images, open from Mail/Browser, share sheet. PART (D4800-D4809): PDF painting, outline and jump, Word and PPTX layout, .ods/.xlsx grids (fmt_odf +9), html.to_markdown HTML view (fmt_html +3), opening from Mail. Remaining: pinch zoom, Browser and Mail on the shared HTML view, Browser downloads and open-with sheet, Dynamic source view, fixtures on real PDF/DOCX/PPTX from independent producers (only hand-assembled, reportlab and generated samples so far).

### C173 — NeperOS Dynamic step-one remainder: the scanner, the versioned app kit, removal (60%)

Split from C143 (D2432): packages are signed, verified, revocable and installed. Acceptance: (1) the scanner as a library over the NIR of a built app: it rejects raw syscalls and MMIO, network or storage use the manifest does not declare, and unbounded loops over input, with a report the Dynamic Details screen shows; (2) the app kit as a stable versioned API (appkit, ui, text, scenes and the e.* subset the scanner allows) with the compiler's diagnostics made readable for a model and the card of traps in docs/llm-neper-card.md as a prompt prefix; (3) the revocation list signed by the server and fetched, not only read from disk; (4) removing an installed app (its package in /apps and its icon) from the home grid; (5) a fixture that builds one hand-written app to a package, signs it, installs it on QEMU, launches it from its new icon and removes it. The prompt and server pieces follow in C124. Not queued here: a store, sharing. PART (D4106-D4107): strict scan with report and app-kit level, signed revocation list fetched from the server; package_test and scan_test pass. Missing: NIR-level walk, app-kit versioning/diagnostics prefix, removal from the home grid, hand-built-app install/launch/remove fixture. PART (D5103, D5107): many installed apps, removal, update/rollback, api check and hello.e pass (install_many, install_remove(_again), install_update, install_api). Remaining: NIR-level scanner walk, signed revocation list fetched anew.

### C174 — NeperOS Clock remainder: a background ringer with the app closed (95%)

Split from C145 (D2433): the Clock's alarms, timer and stopwatch persist in /clock. Acceptance: (1) a background service started by the kernel in the unified boot reads /clock, owns the schedule and, when an alarm or timer is due, raises a notification through the status server (C111) and starts the ringer even with another app or the home screen in front; (2) Snooze and Dismiss from the notification, written back to /clock; (3) a fixture on QEMU that sets an alarm, leaves the Clock, and sees it ring. PART: clock_kept and clock_ring pass (ringing with the app closed via the background services process).

### C175 — NeperOS clipboard remainder: Paste in every field, a lifetime setting, clear on lock (80%)

Split from C148 (D2435): the clipboard holds text, Secure copies to it and AI pastes from it. Acceptance: (1) every ui.Field offers Paste when the clipboard holds text (a pill the keyboard draws, not a per-app one); (2) the lifetime (30 s by default) is a setting in Settings, and a fixture that checks a copy is gone after it; (3) the clipboard is cleared when its owner locks (Secure's lock) or leaves; (4) copy from Browser, Mail and Messages text. PART (D2443): a Paste key on the shared keyboard (shown beside space while the clipboard holds text, handled by ui.field_key); fixture clipboard_keyboard; secure fixture unaffected. Remaining: the lifetime as a Settings value, clear on lock, copy from Browser/Mail/Messages. PART (D4015): clipboard, clipboard_keyboard, clipboard_expired and the new messages_copy, mail_copy, browser_copy pass. Missing: Copy takes plain text only, 32 bytes at most.

### C176 — NeperOS settings recipients remainder: audio, fingerprint, radios, battery (80%)

Split from C149 (D2436): notification permission is enforced at the status service. Acceptance: (1) an audio server (virtio-sound or a software mixer behind e.audio) that takes the media, ring and alarm volumes and Vibrate from the settings server, with a fixture on QEMU; (2) a fingerprint or biometric unlock path on the lock screen, or a recorded sensor in the test boots, honouring the Fingerprint switch; (3) Bluetooth and Hotspot recipients in the network stack (a link layer that can be switched), gated like Airplane mode; (4) a real battery provider posting to the status service, and per-app permissions (camera, location, storage) as values per app; (5) apps hold a notification capability so they can post as themselves through OP_POST_APP. PART: lock_fingerprint, settings_permission and the audio mixer/ringer/notification paths exercised by clock_ring pass. Missing: Bluetooth/Hotspot recipients, a real battery provider (status_server takes a recorded 78 %). PART (D5001, D5002): Bluetooth and Hotspot are links of the network server gated by Airplane mode; a scripted battery provider posts to the status service. Remaining: a real battery driver and Bluetooth/Hotspot peers.

### L164 — gRPC remainder: server side, deadlines and stubs from .proto descriptors (95%)

Split from L101 (D2646): e.net.http2 and the e.net.grpc client protocol exist and are checked against hpack/h2 and recorded grpcio transcripts. Acceptance: (1) a server side over e.net.http2 (unary, then streaming); (2) deadlines, retries and message compression; (3) the gRPC-over-HTTP/3 binding on e.net.http3 frames; (4) a TLS dial helper; (5) stub generation from .proto descriptors (e.fmt.protobuf needs a descriptor reader first) with typed request and response messages. PART (D2923): e.net.grpcserver (preface, SETTINGS, HPACK, flow control, request events, flow-controlled responses, trailers-only, deadlines, resets) and e.net.grpccodec (gzip/deflate/identity decompression) checked with grpcio against a live loopback server (14 calls). NOT DONE: retries and backoff, gRPC over HTTP/3, a TLS dial helper, send-side compression wiring, stub generation (e.fmt.protobuf has no descriptor reader). PART (D3004-D3008): send-side compression (net_grpccompress, decoded by Python gzip/zlib), e.fmt.protodesc descriptor reader (32 cases vs protobuf MessageToDict), typed stubs e.fmt.protomsg/e.net.grpcstub (242 Python-serialised instances round trip), e.net.grpcretry (gRFC A6 vs a Python model), e.net.grpctls dial helper. Missing: gRPC over HTTP/3, retry wired into a transport loop, hedging, perAttemptRecvTimeout. PART (D3401): e.net.grpccall retry and hedging loop over e.net.grpc with deadline and per-attempt timeout; net_grpccall 331 runs, 60 against live grpcio, 271 against an independent A6 model. Missing: HTTP/3, transparent retries, a socket run; per_attempt_ns has no live oracle. PART (D4601): transparent retries (REFUSED_STREAM reset, GOAWAY below the stream id) first one per call, not counted or throttled; net_grpccall 401 cases (41 goaway scripts agree with live grpcio; the REFUSED_STREAM half is the gRFC model, grpcio treats it as UNAVAILABLE); 15/15 loopback socket scenarios agree with the model. Missing: HTTP/3 (no oracle), hedging combined with transparent retry has no vector, per_attempt_ns has no grpcio oracle.

### G001 — e.data.table: typed columns, null bitmaps, string dictionary + heap, bulk load, journal (70%)

Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: 150k × 24 load fixture; typed get/set round-trip; dictionary rank/fold correct; memory ≤ budget. PART (D3905): lib/e/data/table.e: typed I32/I64/F64/Bool columns, null bitmaps, Str heap and Dict (deduplicated, fold-order ranks via e.algo.sort), bulk load, tombstones, per-column version journal; tests/selfhost/fixtures/link/data_table: 150,000 x 24 loaded, every cell read back, ranks vs compare_fold, versions, capacity errors, 41 MiB (bound 45). NOT DONE: row compaction, a boxed Value accessor, u16 dictionary ids, the e.db cursor adapter, a Linux run, and the load/rank timings against the design targets (load <= 250 ms).

### G002 — e.data.tableview sort: key derivation, stable radix, multi-key, comparer slow path (60%)

Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: stable tie-break by row; null first; case-insensitive parity; ≤ budget at 150k (cachegrind). PART (D3906): lib/e/data/tableview.e: View over an e.data.table, stable LSD multi-key sort (numeric/bool/dict-rank/heap-string-rank keys, key function, comparer slow path, nulls first asc / last desc, row tie-break); tests/selfhost/fixtures/link/data_tableview: 22 sorts over 150,000 rows each checked against an independent reference ordering, mutation-checked; measured 8 ms (rarity) to 92 ms (35k-entry dictionary), heap-string rank build 644 ms then 16 ms cached. NOT DONE: the parallel driver, cachegrind budget check, Date/Enum kinds, single-row repositioning, a Linux run.

### G003 — filter tree compile + evaluate (dictionary fast path, narrowing, parallel) (70%)

Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: every operator in §4.2; */? wildcards; **text operators case-insensitive by default, match_case opt-in** (*creature* → 56,095 on the MTG pool); nested depth 6; ≤ budget. PART (D3907): e.data.tableview filter stage: flat node tree (And/Or/NotAnd/NotOr groups, leaves of 18 operators), dictionary columns evaluated once per entry, typed numeric compares, heap-string per-row text operators, ASCII-folded by default with match_case opt-in, `*`/`?` wildcards, order kept through a filter and a re-sort (matched bitset), refine mode; tests/selfhost/fixtures/link/data_tablefilter: ~60 filters over 150,000 rows against an independent evaluator, mutation-checked; measured 9 ms (dictionary like) to 26 ms (heap string contains) per apply. NOT DONE: parallel evaluation, relative-date operators, custom functions, the MTG 56,095 count (needs the real pool), a Linux run.

### G004 — group + summary engine, expansion keyed by path, group summaries/footers (70%)

Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: group boundaries equal golden; summaries equal; sort-by-summary. PART (D3908): lib/e/data/tablegroup.e: up to four group levels over a tableview (sort by levels then keys, neighbour comparison), flat pre-order group array, expansion by key path surviving re-sort and re-filter, visible list, f64 summaries (rows/values/sum/min/max) per group and footer, groups ordered by a summary within each parent; tests/selfhost/fixtures/link/data_tablegroup against an independent reference, four mutations caught; measured 27 ms (one level incl. sort), 31 ms (two), summaries 4 ms, order groups 26 ms at 150,000 rows. NOT DONE: group footers, date-part grouping, parallel passes, incremental upkeep under edits, a Linux run.

### G005 — search / locate / value list (70%)

Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: begins-with and within; next/prev with wrap; value list = dictionary. PART (D3909): lib/e/data/tablesearch.e: find (begins/within, fold or exact, forward/backward, wrap) over any display order with a per-entry verdict on dictionary columns, value_list (dictionary counts in fold order, merged case variants, nulls, filtered rows only); tests/selfhost/fixtures/link/data_tablesearch against brute force, four mutations caught; measured full-scan miss 2.3 ms (dictionary) / 8.4 ms (heap string), value list 1.4 ms at 150,000 rows. NOT DONE: search on numeric display text, binary search of a sorted dictionary, match highlighting, find-panel syntax, a Linux run.

### G006 — e.ui.datagrid v1: bands, footer, group rows, filter row, navigator, indicator, preview, no-data (95%)

Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: pixel-level offline screenshot fixtures (per neper offline UI screenshot recipe); keyboard/pointer fixtures. DONE in lib/e/ui/datagrid.e + tests/selfhost/fixtures/link/ui_datagrid (D3910-D3915; origin D2367-D2372): header with sort indicator and resize/reorder, virtual body over the grouping visible list, group rows with summaries, footer, no-data text, typed cells, custom cells (application builds the node; v5 paints mana badges), row roles, filter row (above the header), bands, row indicator, navigator, in-place editing (typed commit, invalid keeps editor, null, dictionary growth, Tab/Shift+Tab/Escape), preview row (table detail), column hide and move, layout save/load (widths, order, hidden, sort, flags, filter texts; unknown or repeated entries tolerated), pixel probes (band fill, selected-row fill, identical frames). Fixture: about 190 checks through the UI harness, 25 mutations caught, and the v5 sample (D:epos\mtg.studio.src5\cardgrid) running 150,000 rows. NOT DONE: whole-frame golden images (the harness has no fonts; glyph goldens need a font decision), a column chooser window, the filter row below the header, a Linux run.

### G007 — editing: cell kinds + editors + write-through + lock (80%)

D3916: tableview.reposition/refilter_row/row_matches (data_tablerow: 150k rows vs full apply_sort/apply_filter, every key kind, mutations caught); datagrid bool toggle, select editor (choice), can_edit lock, value_changed old/new, begin_batch/end_batch (ui_datagrid section 13, exits 310-337). Open: undo, paste helper, Linux run. Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: edit-then-commit fixtures incl. sort-key edit.

### G008 — custom painters + row style + conditional formatting rules (70%)

D3917: e.ui.gridrules (cell-is, text, blank, above/below, top/bottom with ties and percent, duplicate/unique, 2/3-colour scale, data bar, icon set; per-field priority, whole-row, refresh by column version) and datagrid set_rules rendering (fill, bar, icon, ink, bold); ui_gridrules fixture incl. 150,000 rows vs own count, ui_datagrid section 14 pixel probes, mutations caught (exit 83, 351); v5 cardgrid uses a data bar and a top-price rule; custom painters and row_role were G006. Open: rules manager UI, expression rules, MTG legality/foil painters, Linux run.

### G009 — layout + filter persistence, customization panel, quick customization (0%)

Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: round-trip; unknown/new column tolerance.

### G010 — export + clipboard (+ print hand-off) (0%)

Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: CSV/XML/HTML/XLSX of filtered+grouped view equals golden.

### G011 — MTG Studio reference app: card-pool/deck/collection views over a 150k fixture (0%)

Proposed by docs/grid.md section 9 (MTG Studio v3 migration grid, 150k records, DevExpress TcxGrid parity; measured Delphi baselines in section 6.1). Design: grid.md section 5, mapping and acceptance rows: section 7. Acceptance: all §7 rows exercised; benchmark table filled with measured numbers.

### G012 — pixel-perfect parity with the v3 grid: reference recordings, state catalogue, metric tokens, visual and behavioural diff ledger (85%)

Requirement added by the owner 2026-10-13 (docs/grid.md section 1.1): the grid UI and behaviour must be a pixel-perfect equivalent of MTG Studio v3 (many visual inconsistencies in v5/cardgrid). Record mtgstudio.exe (or owner-supplied screenshots) per state at 100/125/150% DPI; extract metrics into one token table; compare Neper offline renders region by region; replay recorded event traces for keyboard, mouse, timing and focus rules; keep a ledger. Acceptance: every catalogue state within recorded tolerance; traces replay with identical outcomes; no open ledger rows. Blocks G006-G011 from scoring 1. Progress 2026-10-13: states S01 (header+rows, v3 over v5), S02-S04 (header hover, sorted asc/desc), G3 (group rows + group box), F1 (footer), menus recorded from mtgstudio.exe at 150% DPI with docs/grid-parity/drive.ps1 and capture.ps1; metrics and colours extracted to docs/grid-parity/tokens.json; ledger docs/grid-parity.md has 20 differences (P001-P020, all open). Open: 100/125% scales, filter/preview/editors/scrollbar/no-data/drag/CF/deck/collection states, tokens read by e.ui.datagrid, comparison fixtures, behaviour traces. D3919: e.ui.gridlook Look (v3() from tokens.json) read by datagrid.set_look and collection TableLook: row 19, header 21, zebra, selected, column lines, group row, footer band; ui_datagrid s15 pixel probes (mutation caught); docs/grid-parity/S01-compare-after-look.png. P001/P002/P004/P005 closed; text face, indicator/star/ES columns, frame, navigator, group box, scrollbar still open. D3920-D3922: text size by ink width (P003 closed, P021 withdrawn), frame, indicator width, favourite star column + navigator arrows (screenshots S01-compare-after-*.png), SCENE_BYTES 1 MB. Open: ES column, scrollbar, group box, 100/125% recordings, body-string checks, behaviour traces. D3923: group box, group rows with +/- box, measured scrollbar, v3's own mana symbols and legality letters in the sample (screenshots S01-compare-group-box-rows/v3-images/scrollbar.png); widget Image source fixed (texels). Open: ES column (edition symbols), page-skip/filter buttons, 100/125% recordings, behaviour traces; sample to read the real Cards table of mtgstudio.db3 (owner request). D3925: v3 column set and widths in the sample, ES edition symbols from v3's SVG collection, navigator page buttons and funnel, keyboard-follows-focus with first traces (docs/grid-parity/traces.json). 100% and 125% recorded for both programs (S100-*, S125-*; row pitch equal at all three scales). Open: remaining behaviour traces, body-text checks on deck/collection views, per-state fixtures. D2383: sort traces recorded (S2: current card kept, minimal scroll, sort keys clicked+Edition+Name) and best-fit on a header-edge double tap (A1), both replayed in ui_datagrid sections 22-23; open: delayed filter, focus after filter/group/edit, deck and collection views. D2384: grouping/ungrouping keeps the current card current and opens its groups (G1, reveal_current, ui_datagrid section 24); filter trace F1 recorded as not applicable to the card pool (find box + dialog, no delayed filter row). Open: deck and collection views, focus after edit. D2385: row ink by the card colour from v3's own palette (set_row_ink, gridlook.card_ink / rarity_ink; P014 closed). D2386: collection and deck views in the sample with v3's own column sets and widths (code-read, tokens.json), collection footer Qty 310 / Used 19 / $0.00 as in the v3 recording (S01-compare-collection.png, S01-v5-deck-view.png). Open: v3's deck window as its own window, editing traces in these views. Editing trace E1 (collection Qty edit, Enter keeps the row, Down, Tab order) recorded and replayed (D3930, ui_datagrid section 25).

### L165 — UI looks: one widget set in a Windows (MTG Studio v3) look, then macOS/iOS and Android (40%)

Plan docs/ui/looks-plan.md, decision D5108, progress docs/ui/looks-progress.html (docs/ui/looks/status.json). Acceptance: (1) Profile.Windows and style.windows from the v3 captures; (2) e.ui.looks renders every control's states offscreen per look at 100% and 150% into docs/ui/looks/<look>/<control>.png beside the v3 reference; (3) the ~30 controls of the plan each reach ready (Windows PNG within tolerance of docs/ui/looks/ref/windows at both scales); (4) CupertinoLike and MaterialLike get tokens and idiom branches (later); (5) controls with no Neper equivalent are listed, not built. PART (D5108, D5109 to D5113; state at audit 2, 2026-10-16): items 1 and 2 done. All 30 controls render under Neper and Windows at 100% and 150% (45 sheet apps in examples/looks, scripts/render_looks_all.sh). The v3 reference is now captured live from a launched copy of v3 by posted window messages (scripts/grab_v3_*.ps1, about 250 state and dialog captures in docs/ui/looks/ref/windows). Audit 2 (docs/ui/looks/audit.md, an independent recompute against those captures, tolerance 2 levels per channel) counts 0 matched, 0 ready, 25 review and 5 started (date_edit, memo, token_edit, progress_bar, hint have no v3 capture); six controls self-reported matched were downgraded. Known gaps: hover and toolbar states cannot be captured without the real pointer (the optional GetCursorPos hook is not done), 81 of 200 captured states have no sheet cell, the baked button ring and edit chrome tiles go dotted at 1.5x, open-list sheets and the data grid are far off. IN FLIGHT: hover captures and round 5 matching. NOT DONE: any control at matched or ready, dark and high-contrast sheets beyond the button, Cupertino and Material.

### L166 — Browser M1: e.ui.browser shows a static page (no JS) (50%)

Plan docs/browser-progress.html, decisions D5114 to D5122. Acceptance: (1) tracker phase P0 (0.1 to 0.8): oracle frozen, html5lib, WPT reftest, pixel-probe and render-tool harnesses, Ahem asset, baselines; (2) P1 parse and style core: 1.1 to 1.14, html5lib at least Dart's 1549 of 1791; (3) P2 2.1 to 2.3 block and inline layout over e.text; (4) P3 3.1 to 3.6 and 3.11 display list, scene tiling, backgrounds, borders, text, images; (5) P4 4.1 and 4.2 loader and HTTP/1.1; (6) 7.0 lib/e/ui/html_view.e shows a static document over e.fmt.dom, e.fmt.css.style, e.fmt.css.layout and e.fmt.css.paint (D5123: reusable parts are library modules, not e.web); 7.1 lib/e/ui/browser.e builds on it, loads an HTTP(S) page, scrolls, follows links; Hacker News within the pixel tolerance of the Dart golden. Not yet: everything except 0.1, most of 0.3, 0.6a, 1.1 to 1.3, 1.7 and 1.13a to 1.13d. PART (2026-10-16): 0.6a html5lib runner done (tests/browser/html5lib/run.sh) 1.1 to 1.3 done (D5124) 1.7 done (D5125, e.fmt.dom with fixture fmt_dom) 1.13a to 1.13f done (D5126, D5127: sheet loader with all at-rules but nesting, user agent sheet; fixtures css_sheet, css_ua) and 1.13a to 1.13d done (D5126, e.fmt.css.style and e.fmt.css.expand with fixture css_style: expansion before ranking, typed computed values, inheritance, var()): e.fmt.html is the WHATWG tokenizer and tree builder, 1791 of 1791 html5lib cases against Dart's 1549 (it was 572), floor enforced by run.sh; the WPT reftest runner, pixel-probe and render tool wait for the layout and paint layers; 0.1 done (D5114 to D5123); 0.3 Dart oracle frozen: vaper tag dart-oracle-final at 8e0c4e9, a record/replay capture tool, six sites (Hacker News, example.com, Wikipedia Comparison_of_web_browsers with 12317 nodes, MDN, craigslist, abv.bg) captured with PNG, node and display-list goldens, each replay byte-identical twice, in tests/browser/oracle with a README; the jQuery page set and the licence decision before committing the stores remain. PART: landed pieces that M1 reuses, not yet checked against the oracle: e.fmt.html, e.fmt.css.syntax/selector/match/cascade/container, e.gfx.cssvalue (L038, L040), e.fmt.woff and woff2 (D2346), e.net.policy and ssrf (D2351). Status 2026-11-03 (branch browser-conformance, tracker rows of P0+P1): 10 done, 8 partial, 9 todo of 28; score is the mean with partial counted as half.

### L167 — Browser M2: modern CSS layout (35%)

Plan docs/browser-progress.html. Needs L166. Acceptance: (1) P2 2.4 to 2.15: floats, positioned and sticky, tables, flex, grid, multicolumn, intrinsic sizing, overflow, transforms, replaced elements, form controls, hit testing and geometry; (2) P3 3.4, 3.5, 3.8, 3.9 gradients, shadows, clip-path, mask, filters; (3) 9.2 WPT CSS reftests reproduce at least Dart's 116 of 122 and the six known failures are triaged; (4) the Dart layout pixel-probe expectations carried over as fixtures and green. Not yet: all of it. Status 2026-11-03 (branch browser-conformance, tracker rows of P2+P3): 4 done, 21 partial, 16 todo of 41; score is the mean with partial counted as half.

### L168 — Browser M3: the real web without JavaScript (25%)

Plan docs/browser-progress.html. Needs L167. Acceptance: (1) Wikipedia with its 12k-node table, MDN with web fonts, craigslist and abv.bg match the Dart goldens within the per-site tolerance; (2) P3 3.13, 3.15, 3.16 SVG, web fonts; (3) P4 4.3 HTTP/2 transport, 4.4 and 4.5 TLS 1.3 interop and TLS 1.2, 4.8 HTTP cache, 4.11 to 4.14 cookies, CORS, SSRF, CSP, 4.17 filter lists; (4) core N.1 and N.2 scene limits and glyph cache as measured by these pages; (5) 7.2 to 7.6 control API, input, thread split, form widgets, accessibility; (6) a shell with tabs, history and bookmarks (7.7). Not yet: all of it. Status 2026-11-03 (branch browser-conformance, tracker rows of P4): 1 done, 8 partial, 10 todo of 19; score is the mean with partial counted as half.

### L169 — Browser M4: JavaScript engine and DOM bindings (30%)

Plan docs/browser-progress.html, decision D5115. Needs L166; engine work (5.1 to 5.16) can start in parallel with L167. Acceptance: (1) P5 5.1 to 5.16: parser, compiler, VM, heap and GC, object model, builtins, ECMAScript RegExp, Promise and microtasks, modules, test262 runner with feature-gated pass targets, benchmarks against QuickJS; (2) P6 6.1 to 6.8 and 6.14 bindings: DOM, CSSOM, events, timers, fetch, storage, forms; (3) 6.17 iframes; (4) jQuery 3.5.1 initialises, AJAX re-renders, timers and events work, getBoundingClientRect feeds layout; (5) 9.4 test262 targets, 9.6 real-site sweep including JS-app pages. Not yet: all of it. Status 2026-11-03 (branch browser-conformance, tracker rows of P5+P6): 0 done, 26 partial, 15 todo of 41; score is the mean with partial counted as half.

### L170 — Browser M5: Dart parity reached, NeperOS Browser replaced (15%)

Plan docs/browser-progress.html. Needs L168 and L169. Acceptance: (1) every tracker row with track mig is done; (2) html5lib at 100 percent (1.3, 9.1); (3) 7.15 neperos/src/browser.e replaced by e.ui.browser and C159 closed; (4) 4.8 and 4.9 cache gaps, 4.10 encrypted cache, 7.8 to 7.12 shell items; (5) 9.7 performance and memory budgets met against the 0.7 baselines; (6) 9.8 fixtures registered in run.ps1 and run.sh, module-apis.md and modules.json current; (7) the Dart repository archived with the oracle artifacts. Not yet: all of it. Status 2026-11-03 (branch browser-conformance, tracker rows of P7+P9): 1 done, 4 partial, 19 todo of 24; score is the mean with partial counted as half.

### L171 — Browser M6: beyond Vaper (gap items) (0%)

Plan docs/browser-progress.html. Needs L170; individual gap rows may start earlier when nothing blocks them. Acceptance: every tracker row with track gap or core is done or explicitly deferred with a decision: Shadow DOM and custom elements (6.16), Workers and Service Workers (6.18, 6.19), contenteditable and Selection (6.11, 6.12), process isolation and OS sandbox (8.1 to 8.3, N.6), DevTools (7.13), WebAssembly (5.17), vertical writing modes (2.16, N.5), audio (3.19), backdrop-filter and blend modes (N.3), colour emoji and CFF (N.4), HSTS and clickjacking protections (4.15, 4.16), fuzzing (8.4). Not yet: all of it. Status 2026-11-03 (branch browser-conformance, tracker rows of P8): 0 done, 0 partial, 7 todo of 7; score is the mean with partial counted as half.

### C213 — e.ui in a browser: a real phone's virtual keyboard and IME (0%)

Android Chrome checked by hand (D5890, D5891: suggestion replacement, touch hold, drag selection, toolbar); iPhone simulator (iOS 17.5 Mobile Safari, .github/workflows/ios-sim.yml, D5900) passes typing, Backspace and the hold toolbar; a real iPhone and a composing keyboard are still unchecked. Needs a device. Prepared: `node scripts/serve-wasm.mjs --isolated --host 0.0.0.0` and open /tests/wasm/browser/phone_probe.html on the phone (a plain field that logs key, composition, paste, visualViewport and scroll events; Report copies the log) to answer checks 1-5 before touching ui_counter. D5821 lists what the mobile preset did and did not show (synthetic composition events, the textarea at 16 px not scrolling or zooming). Serve tests/wasm/browser/ui_counter.html over HTTPS or a LAN address with scripts/serve-wasm.mjs --isolated (a secure context is needed for crossOriginIsolated and the clipboard) and check on iOS Safari and Android Chrome: (1) tapping the Name field opens the keyboard and neither zooms nor scrolls the page; (2) typed letters, Backspace and Enter arrive once each; (3) composition with a CJK keyboard (pinyin or kana) delivers the committed text once, with no duplicate after compositionend and none while composing; (4) the clipboard: paste from the system menu reaches the program, and Ctrl+C in the program writes navigator.clipboard, with the permission prompt answered either way; (5) visualViewport resizes when the keyboard opens and the canvas stays usable (decide whether the window follows it); (6) a physical keyboard on a tablet still works. Fix what fails in lib/wasm/window.js; window_visible is separate.

### L176 — OpenGL 5: CGL context on macOS (GL 4.1 core, presentation only) (0%)

Design docs/opengl-plan.md, D5879, D5880. Needs L173. Acceptance: an NSOpenGLContext on the content view that window_native returns; follows the Retina backing scale; checked on the macOS CI runners. Metal (C193) keeps the Mac's compute.

### T048 — OpenGL verify 4 (verify-only): full suites for the shared compiler change (0%)

Verify-only turn, no edits. Needs T047. Run the full suites on both hosts for the glsl target change and report the tails.

### C219 — OpenGL 16: the Android target, executable form (90%)

Done 2026-10-27 (D5896, D5900): emit-executable ... x64 android and aarch64 android write the Linux image typed ET_DYN for /system/bin/linker64, with Bionic library names (libc.so) plus libdl.so and liblog.so; arm64 Android images always carry a dynamic segment, and arm64 atomics are LDAXR/STLXR loops (ARMv8.0). Android is linux to every module and variant, so no os.android.e was needed (neither Bionic nor SELinux refused anything run so far). scripts/run-android.ps1 [-Arch aarch64] runs hello, advanced, gpu_cpu, gpu_fault_bounds, x_khronos_gl_load, x_khronos_gl_headless, atomic_ops, atomic_threads and channel_threads on the SDK's Android 15 x86_64 emulator for both architectures, all passing, with GLES 3.0 drawing and reading back. Remaining: e.gpu compute on a device with GLES 3.1+. The emulator stops at 3.0 on this host: SwiftShader, -gpu host on the Iris Xe (draws there too) and -feature GLESDynamicVersion all report ro.opengles.version 196608, and -feature GuestAngle does not boot, so this needs a real phone. Design docs/opengl-plan.md, D5884. Needs T047. Acceptance: --target android-x64 and android-a64 emit a PIE ELF for /system/bin/linker64 with DT_NEEDED libc.so, libdl.so and liblog.so; os.android.e is os.linux.e without what Bionic and SELinux refuse; the executable runs under adb shell on the x86_64 emulator, and T047's fixtures pass there on GLES.

### T050 — Regression test for the heap-backed device-lost path (D5949) (0%)

D5949 keeps a device lost after a failed Metal or OpenGL command, but no fixture makes dispatch_wait fail, so nothing fails if the sticky flag or the state_of check is removed. Acceptance: a fixture that makes one launch's wait fail (a fault-injecting HeapDriver or a deliberate device loss on a Mac), then checks that info, has, queue creation and a later launch all report Lost whichever is called first, and that close still returns ok and frees the heap.

### C224 — x86-32 emitter: x86-windows and x86-linux targets (0%)

Opened 2026-11-03 from docs/roadmap.md:179 by the single-list audit; not previously a queue row. Acceptance: `neper build --target x86-linux` and `x86-windows` emit runnable 32-bit executables (cdecl/stdcall, one vector slot per spec section 5). The M1/M2 corpus and bidirectional C ABI fixtures pass on both. Size XL. Checked open: grep src/*.e for x86-linux/x86-windows/ia32/i386: no hits; only codegen_x64.e and codegen_a64.e exist; work-done has no x86-32 record; not a queue.tsv row.

### C225 — aarch64-windows target: ARM64 PE emitter, linker and runtime (0%)

Opened 2026-11-03 from docs/roadmap.md:178 by the single-list audit; not previously a queue row. Acceptance: `--target aarch64-windows` links a PE32+ ARM64 executable with the own linker and runs hello plus the conformance corpus on a Windows-on-ARM host or emulator. Spec section 13 lists the target, so it stops being an option error. Size L. Checked open: aarch64 exists for linux/macos/none/neperos (codegen_a64.e, link_elf_a64.e, link_macho.e) but grep 'aarch64-windows' in src/*.e is empty and link_pe.e has no ARM64 machine type.

### C226 — PTX emitter and CUDA compute backend for e.gpu (.Cuda devices open and launch) (0%)

Opened 2026-11-03 from docs/roadmap.md:180 by the single-list audit; not previously a queue row. Acceptance: A kernel compiles to PTX and `e.gpu.open` on a `.Cuda` device launches it through the driver API. GP-10 kernels are bit-identical with the CPU backend, or within their stated ULP bound for the approximate builtins. Size XL. Checked open: grep -i ptx across src/lib/tests/docs/work-done.jsonl: no hits. lib/e/gpu/cuda.e header says 'Only enumeration lives here: there is no CUDA compute backend yet'.

### C227 — PDB writer in the own PE linker (MSF, DBI, module, symbol and line streams) (0%)

Opened 2026-11-03 from docs/roadmap.md:183 by the single-list audit; not previously a queue row. Acceptance: A `--linker=own` Windows build writes a `.pdb` that WinDbg and Visual Studio symbolicate with function names and lines, with no type stream. Output is byte-deterministic. Size L. Checked open: grep -i pdb in src/ and lib/: no writer; src/link_pe.e writes .text/.idata only; the work-done PDB hit is the CodeView record emitter (C084), not the PDB container.

### C228 — neper-format debug side table in .em (types, locals, scopes, variable locations) (0%)

Opened 2026-11-03 from docs/roadmap.md:185 by the single-list audit; not previously a queue row. Acceptance: The `.em` Debug section carries a side table over the serialised type table, beside the DWARF/CodeView subset and never replacing it. A conformance fixture reads back the locals and locations of a function and they agree with the standard-format locations. Size L. Checked open: grep src/em.e and binary.e for a debug side table: only line/symbol tables and .nepersym; spec section 11 'from M4, the neper-format side table' still future; no work-done record.

### T051 — Native debug engine: process control, breakpoints, single-step, stack walking, location rendering (0%)

Opened 2026-11-03 from docs/roadmap.md:188 by the single-list audit; not previously a queue row. Acceptance: A library (Windows and Linux hosts) launches a Neper program under control, sets and hits a breakpoint, single-steps, walks the stack and renders locals from the side table. A fixture asserts the stop locations match `lldb` on shared programs. Size XL. Checked open: grep for ptrace/DebugActiveProcess/breakpoint in lib/ and src/: only lib/e/debug/dump/host.linux.e (post-mortem dump) and a UI style hit; no live-process control.

### T052 — `neper dap`: framed-JSON debug adapter plus VS Code and Zed extensions (0%)

Opened 2026-11-03 from docs/roadmap.md:190 by the single-list audit; not previously a queue row. Acceptance: `neper dap` speaks DAP over stdio with Content-Length framing and rejects `--json` and `--absolute-paths`. VS Code and Zed extensions launch it and a scripted session hits a breakpoint and reads a local. Size L. Checked open: grep '"dap"' src/main.e: no dispatch; no dap record in work-done beyond decision text; spec.md:4245 lists it as M4.

### C229 — Optimiser depth: inlining heuristics, load/store forwarding and instruction scheduling (0%)

Opened 2026-11-03 from docs/roadmap.md:194 by the single-list audit; not previously a queue row. Acceptance: A release build forwards stores to later loads in a block and schedules independent instructions, and cross-.em inlining uses a cost heuristic below the 40-NIR cap. The GP-09 and compiler-build benchmarks improve against benchmarks/baseline budgets with identical output. Size L. Checked open: grep -i 'forward' and 'schedul' in src/nir.e, lower.e, regalloc.e, codegen_x64.e: no matches; C079 only covers the fixed 40-NIR inlining cap.

### C230 — Vector register class: pass Vec/Mask in xmm/ymm per spec section 5 (0%)

Opened 2026-11-03 from docs/roadmap.md:196 by the single-list audit; not previously a queue row. Acceptance: `Vec[T,N]` and `Mask[T,N]` live in vector registers across calls and spills instead of copied storage (D786/D1524). GP-09 improves measurably and the ABI fixtures for sysv and win64 pass. Size L. Checked open: src/codegen_x64.e:849 and :883 state 'not yet a vector register class'; regalloc.e has no vector class; decisions D786 and D1524 defer it to M4.

### T053 — neper pacman CLI group and e.* namespace-reservation enforcement (0%)

Opened 2026-11-03 from docs/roadmap.md:363 by the single-list audit; not previously a queue row. Acceptance: `neper pacman init|add|remove|resolve|sync|upgrade|build|run|task|vendor|publish|cache|info` exist with versioned JSON output, shared diagnostics and schema validation. A registry package exporting under a toolchain-reserved `e.*`/`e.algo.*`/`e.ui.*` prefix is rejected and `x.<owner>.*` is accepted. Size L. Checked open: grep 'pacman' in src/main.e: none; no namespace check in src/project.e or resolve.e.

### T054 — One shared usage text for --help, -h, help and E-CLI-9999; info.commands lists every dispatched command (0%)

Opened 2026-11-03 from docs/roadmap.md:435 by the single-list audit; not previously a queue row. Acceptance: `neper --help`, `-h` and `help` print the same text the two E-CLI-9999 sites use, naming all dispatched commands, and `info.commands` matches. A conformance check fails if the three disagree with the dispatcher. Size S. Checked open: grep '"--help"' in src/main.e: none; src/main.e:1115 usage names only tokens|parse|fmt-file|info; no work-done record.

### T055 — `neper eval EXPR`: fold a const initialiser and print it (comptime interpreter, no codegen) (0%)

Opened 2026-11-03 from docs/roadmap.md:440 by the single-list audit; not previously a queue row. Acceptance: `neper eval "1usize << 40" . x64 windows` prints 1099511627776 and a module-scope call such as `table_sum()` folds in its module. No code is generated or linked and a non-constant expression is a diagnostic. Size M. Checked open: grep '"eval"' in src/main.e: no dispatch; docs/tooling.md:1063 documents the examples but nothing implements them; no work-done record.

### T056 — Rename the prose name for the standard library to `e.lib` across the docs (0%)

Opened 2026-11-03 from docs/roadmap.md:444 by the single-list audit; not previously a queue row. Acceptance: spec section 1 and 2, modules.md, module-apis.md, tooling.md, README.md and render_progress.py row text use `e.lib` for the lib/e modules, with a D-row recording the term. A grep for 'stdlib', 'core library' and 'standard library' in those files finds none outside quotes. Size S. Checked open: grep 'e\.lib' in src/ hits only unrelated identifiers; docs still say 'standard library'/'stdlib'.

### C231 — Windows resources part 1: link a precompiled .res into a .rsrc section; os.resource(kind,name) (0%)

Opened 2026-11-03 from docs/roadmap.md:450 by the single-list audit; not previously a queue row. Acceptance: `project.yaml` names a `.res` per Windows target and the PE carries a byte-deterministic `.rsrc` directory (type, name, language order; icon and group-icon split; manifest at id 1). `os.resource` reads a custom RCDATA entry at run time. A Linux build records the resource as not applicable. Size L. Checked open: grep -i 'rsrc' in src/ and lib/: no hits; link_pe.e emits .text and .idata only; no os.resource in lib/e/os.windows.e.

### T057 — Windows resources part 2: `neper rc FILE.rc -o FILE.res` compiler (0%)

Opened 2026-11-03 from docs/roadmap.md:456 by the single-list audit; not previously a queue row. Acceptance: The compiler accepts ICON, CURSOR, BITMAP, VERSIONINFO, STRINGTABLE, RCDATA, RT_MANIFEST, LANGUAGE, user-typed `NAME TYPE "file"` and `#define NAME integer`, and rejects #include and expressions. Its .res output links to the same bytes as a reference .res and the build manifest records path, size and SHA-256. Size M. Checked open: grep 'neper rc' and '"rc"' in src/main.e: none; depends on the .rsrc linking item.

### T058 — `build --subsystem gui`: PE subsystem 2 behind a flag, recorded in the build manifest (0%)

Opened 2026-11-03 from docs/roadmap.md:469 by the single-list audit; not previously a queue row. Acceptance: `neper build --subsystem gui` writes IMAGE_SUBSYSTEM_WINDOWS_GUI so no console window opens, and the build manifest records the subsystem. The default stays console. Size S. Checked open: grep -i subsystem in src/*.e: no hits; the PE header writer has no flag, and ui windowed apps on Windows still open with a console.

### T059 — `neper run --watch`: rebuild and rerun on a source change using e.fs.watch (0%)

Opened 2026-11-03 from docs/roadmap.md:472 by the single-list audit; not previously a queue row. Acceptance: `neper run --watch` rebuilds and restarts the program when any module in its graph changes, stopping the old process first. A fixture edits a file and observes the new output. Size S. Checked open: grep -n 'watch' src/main.e: none; lib/e/fs/watch.e exists as the prerequisite.

### T060 — TextMate grammar neper.tmLanguage.json generated from grammar.ebnf (0%)

Opened 2026-11-03 from docs/roadmap.md:475 by the single-list audit; not previously a queue row. Acceptance: A script beside render_progress.py generates the grammar from keywords, literal suffixes and the // trivia rule in grammar.ebnf. A test tokenises the conformance token corpus and the scope spans match `tokens --json`. Size S. Checked open: grep -ri 'tmLanguage|textmate' across the repo (src, scripts, tests, docs/work-done.jsonl): none.

### L183 — Chart PDF: embedded TrueType text, FlateDecode streams, multi-page reports; SVG font subsetting (0%)

Opened 2026-11-03 from docs/charts.md:1716 by the single-list audit; not previously a queue row. Acceptance: e.gfx.chart.pdf writes TrueType-embedded text and FlateDecode content streams and can emit a multi-page document; pypdf parses it and text extraction returns the labels. SVG embed_font writes a glyph subset, and the gradient_font SVG shrinks versus the full 610 KB font with identical raster output. Size M. Checked open: lib/e/gfx/chart/pdf.e line 7 ponytail comment (uncompressed, Helvetica only); no subset code in svg.e; not in queue.tsv or work-done

### L184 — Chart widget: legends, multi-layer views, keyboard zoom/orbit, single-axis zoom, cross-chart filter state (0%)

Opened 2026-11-03 from docs/charts.md:1740 by the single-list audit; not previously a queue row. Acceptance: chart.widget View holds a list of layers and an interactive legend, zooms one axis, and zooms/orbits from the keyboard. A selection in one View filters another through shared selection state; a headless-harness fixture checks each interaction. Size M. Checked open: lib/e/gfx/chart/widget.e:28 ponytail one layer per view; only wheel/drag zoom_about; charts.md:436 cross-chart filtering planned; no queue row

### L185 — Chart layout: automatic legend placement/wrapping, layout-aware margins, label and strip collision avoidance (0%)

Opened 2026-11-03 from docs/charts.md:929 by the single-list audit; not previously a queue row. Acceptance: A layout pass sizes margins from measured tick, title and legend text, wraps and places legends without overlap, and omits or flips colliding tick labels and facet strips. plot_grid gets spanning cells and shared legends; free-scale and categorical facets map geoms beyond Scatter. Fixtures on Windows and Linux show no label overlaps on a dense case. Size L. Checked open: chart.e has only legend_items (caller places) and category_facet_scatter (Scatter only); charts.md:929,1222,1239,1547 say these remain planned; no queue row

### L186 — Chart label leader lines and optimising placement; curved labels for sunburst/pie (0%)

Opened 2026-11-03 from docs/charts.md:1771 by the single-list audit; not previously a queue row. Acceptance: label_placement can draw leader lines from displaced labels to marks and optionally runs a conflict-graph or annealing pass that places more labels than the greedy Imhof order. A fixture compares placed counts on the 25-city case and checks determinism. Size M. Checked open: lib/e/gfx/chart.e has only greedy 8-slot placement; charts.md:1771 and :1007 say optimising placement and curved-label placement remain open

### L187 — Chart downsampling and scene batching for very large series (0%)

Opened 2026-11-03 from docs/charts.md:1667 by the single-list audit; not previously a queue row. Acceptance: A min/max or LTTB downsampler reduces a 1M-point line or scatter to a bounded number of vertices keeping extremes, and the scene display list batches same-brush marks. A benchmarks/charts case records layout time for 1M points under a stated budget. Size M. Checked open: grep downsample/lttb in lib/: none; charts.md:1667 (L062 item 6) names progressive downsampling and GPU batching as open

### L188 — Chart color accessibility: Machado anomalous-trichromacy tables and automatic marker shapes (0%)

Opened 2026-11-03 from docs/charts.md:1784 by the single-list audit; not previously a queue row. Acceptance: simulate_color_vision supports anomalous trichromacy (Machado 2009) at severity steps with reference values from the paper, and a helper assigns distinct marker shapes per series so series stay distinguishable when palette_separation is low. Size S. Checked open: chart.e has simulate_color_vision (dichromat only) and no marker-shape selector; charts.md:1784,1807 say both remain open

### L189 — Geographic charts: quantile and Jenks classes, TopoJSON reader, polygon clipping, antimeridian splitting (0%)

Opened 2026-11-03 from docs/charts.md:1751 by the single-list audit; not previously a queue row. Acceptance: class_of gains quantile and Jenks natural-breaks classes; a TopoJSON reader beside e.gfx.chart.geojson yields the same region arrays; the map window clips polygons to its bounds and splits rings crossing the antimeridian. Fixtures compare breaks to a reference implementation and render a seam-crossing region. Size M. Checked open: lib/e/gfx/chart/geojson.e has equal-interval classes only; grep jenks/topojson: nothing; charts.md:380 and :1751 list these as planned

### L190 — Gantt dependency links, CPM working calendars, leads/lags, resource levelling and duration uncertainty (0%)

Opened 2026-11-03 from docs/charts.md:1270 by the single-list audit; not previously a queue row. Acceptance: gantt draws dependency arrows between tasks; pert_cpm_schedule honours working calendars and lead/lag; a resource-levelling pass and a Monte Carlo project-duration distribution are exposed. Fixtures check the critical path and dates against a reference scheduler. Size L. Checked open: chart.e gantt (line 5698) has no link input; pert_cpm_schedule has no calendar; charts.md:1270,1280 say links, calendars, levelling and uncertainty remain planned

### L191 — Diagram auto-layout: flowchart, state machine, ER, org chart and dependency-graph routing (0%)

Opened 2026-11-03 from docs/charts.md:1319 by the single-list audit; not previously a queue row. Acceptance: Flowchart, state-machine and ER diagrams accept unplaced nodes and place them automatically with orthogonal mixed-axis port routing and collision-safe edge labels; the layered layout reduces crossings, bundles edges and inserts dummy nodes for long links; org chart accepts multiple roots and dotted lines. Fixtures count crossings and overlaps. Size L. Checked open: charts.md:1313,1319,1326,1337,1686 say placement, routing and crossing reduction remain planned; chart.e flowchart/state_machine take explicit placement; no queue row

### L192 — UML and decision diagram depth: sequence fragments, activation inference, BPMN gateways, influence diagrams (0%)

Opened 2026-11-03 from docs/charts.md:1332 by the single-list audit; not previously a queue row. Acceptance: Sequence diagram supports alt/opt/loop fragments, destruction markers and inferred activation bars; process maps draw BPMN gateways and events; decision trees extend to influence diagrams with utility functions. Each has a scene/SVG fixture. Size M. Checked open: charts.md:1190,1302,1332 list these as planned; no matching fn names in lib/e/gfx/chart.e; no queue row

### L193 — Chart statistics follow-ons: adaptive histogram bins, weighted counts, STL/multiplicative decomposition, robust fit (0%)

Opened 2026-11-03 from docs/charts.md:828 by the single-list audit; not previously a queue row. Acceptance: Histogram supports Freedman-Diaconis/Scott bin rules and weighted counts; the decomposition chart accepts e.algo.timeseries stl and a multiplicative model with missing data; a robust (Huber/Tukey) fitted line is available. Results match numpy/statsmodels references. Size M. Checked open: lib/e/algo/timeseries.e has stl but chart decomposition is classical additive only; grep freedman in chart.e/stat.e: none; charts.md:539,828,1107 say these remain planned

### L194 — Chart layout follow-ons: squarified treemap, streamgraph wiggle, Sankey/alluvial crossovers, word-cloud packing (0%)

Opened 2026-11-03 from docs/charts.md:998 by the single-list audit; not previously a queue row. Acceptance: Treemap uses caller-scratch squarified layout; streamgraph offers wiggle offsets and automatic layer ordering; Sankey/alluvial handle missing categories and curved crossovers; word cloud normalises case and packs large clouds. Aspect-ratio, area and overlap checks pass in fixtures. Size M. Checked open: chart.e:7633 comment defers squarification; charts.md:998,1040,1045,1119 say these remain planned

### L195 — Report compositions: page breaks, print layout and tabular export for cross-tab and matrix reports (0%)

Opened 2026-11-03 from docs/charts.md:388 by the single-list audit; not previously a queue row. Acceptance: Cross-tab and grouped matrix reports paginate with repeated headers, lay out for a page size, and export the underlying table as CSV equal to the displayed cells. A fixture compares page count and CSV against goldens. Size M. Checked open: charts.md:388 states these remain follow-on work; no pagination or export symbol found in the report chart functions

### L196 — Motion framework: curves catalogue and tweens (P6-01, P6-02) (0%)

Opened 2026-11-03 from docs/animation-plan.md:1 by the single-list audit; not previously a queue row. Acceptance: e.ui.animation gains CubicBezierCurve, IntervalCurve, StepCurve, curve transforms and a named catalogue, plus value, colour, geometry and transform tweens and TweenSequence. Fixtures check curve samples against Flutter reference values. Size M. Checked open: docs/widget-plan.json P6-01/02 delivered lists empty; lib/e/ui/animation.e is 125 lines with four quadratic curves and one bezier; not in queue.tsv

### L197 — Motion framework: controller v2 and physics simulations (P6-03, P6-04) (0%)

Opened 2026-11-03 from docs/animation-spec.md:235 by the single-list audit; not previously a queue row. Acceptance: Controller reports Status (Dismissed/Forward/Reverse/Completed), is driven forward/reverse/repeat with velocity, and supports time dilation; closed-form Spring (three regimes), Friction and Gravity simulations replace hand-written scroll overshoot. Spring done-times match an mpmath reference within 1 ms. Size L. Checked open: lib/e/ui/animation.e has no Status or Spring; animation-spec.md:722 test table; widget-plan P6-03/04 undelivered; no queue row

### L198 — Motion framework: implicit animations and explicit transitions (P6-05, P6-06) (0%)

Opened 2026-11-03 from docs/animation-plan.md:30 by the single-list audit; not previously a queue row. Acceptance: AnimatedValue, AnimatedOpacity, AnimatedLayout, AnimatedDecoration, AnimatedSwitcher and AnimatedCrossFade retarget smoothly when a property changes, and Fade/Scale/Rotation/Slide/Size transitions run compositor-only. Harness frame sampling shows start, mid and end values. Size L. Checked open: widget-plan P6-05/06 delivered lists empty; animation-plan.md says only loaders call e.ui.animation; no queue row

### L199 — Motion framework: choreography, animated list changes, shared-element and route transitions (P6-07, P6-08) (0%)

Opened 2026-11-03 from docs/animation-controls.md:389 by the single-list audit; not previously a queue row. Acceptance: Staggered and sequence groups, animated list/grid insert-remove-move in e.ui.collection, and Hero, shared-axis, fade-through, container-transform and predictive-back route transitions in e.ui.navigation. Headless fixtures sample intermediate frames and assert final layout equals the non-animated result. Size L. Checked open: widget-plan P6-07/08 undelivered; grep Hero/SharedAxis in lib/e/ui finds only scroll springs; no queue row

### L200 — Motion framework: fake-clock testing, reduced-motion policy, migration of hand-rolled motion (P6-09) (0%)

Opened 2026-11-03 from docs/animation-spec.md:722 by the single-list audit; not previously a queue row. Acceptance: e.ui.testing provides a fake-clock pump and frame sampling; one reduced-motion policy collapses all durations; press ripple, scroll overshoot, tooltip timing and reorder feedback move onto the framework with frame-stat counters. A test fails if any widget animates under reduced motion. Size M. Checked open: widget-plan P6-09 undelivered; animation-plan.md says ripple, overshoot, tooltips, reorder are hand-written in widgets; no queue row

### L201 — Screen-reader bridge: value/name/live-region events, RangeValue and Selection/Table patterns, AT-SPI extents (0%)

Opened 2026-11-03 from docs/ux/accessibility-bridge.md:251 by the single-list audit; not previously a queue row. Acceptance: A changed value, name or live-region text raises UIA and AT-SPI events; sliders and progress bars expose RangeValue/Value; containers expose Selection and Table; AT-SPI reports screen-space extents and per-granularity text. Verified with the existing accessibility audit fixtures. Size L. Checked open: accessibility-bridge.md 'Not yet' section; grep RangeValue in lib: none (only SelectionItem); macOS NSAccessibility is C190 so excluded

### L202 — Build the unbuilt TcxGrid parity grids on e.ui.datagrid (prices, editions, messages, shortcuts, statistics, import) (0%)

Opened 2026-11-03 from docs/grid-parity/tcxgrid-plan.md:7 by the single-list audit; not previously a queue row. Acceptance: Each grid marked 'not built' (dbgPrices x2, dbgAbilitiesPreview, dbgEditions, dbgPreview, dbgMessages, gdShortcuts, dbgSelectEdition and the eight statistics grids) exists on e.ui.datagrid with the v3 columns, read-only flags and widths, and is compared against its v3 capture. Size L. Checked open: grep dbgPrices/dbgMessages/gdShortcuts/dbgSelectEdition/dbgProbability in lib and examples: only docs; G011/G012 cover the pool/deck views and the metric ledger, not these grids

### T061 — Promote e.ui/e.gfx from experimental: multi-window keyboard-accessible app workload on three desktops (0%)

Opened 2026-11-03 from docs/ui-framework.md:283 by the single-list audit; not previously a queue row. Acceptance: A general-purpose application workload (multi-window, keyboard-accessible) runs on Windows, Linux and macOS and records memory, frame-time and compatibility results in a committed report; GP-15 then lists the UI modules as promoted or names the blockers. Size M. Checked open: docs/general-purpose-verification.md:330 says experimental UI modules have not passed GP-15; grep GP-15 in work-done.jsonl: 0; no queue row

### C232 — GP-09: lower simd.shuffle/interleave to punpck/pshufb so the Base16 codec stops using scalar lane loops (0%)

Opened 2026-11-03 from docs/gp-performance.md:29 by the single-list audit; not previously a queue row. Acceptance: benchmarks/gp/neper/gp09.e encodes with a vector interleave (no per-lane scalar store loop) and benchmarks/gp/run.py reports runtime p50 within 3x of C (now 1576 ms vs 50 ms) with the identical checksum 534775349. A link fixture pins the interleave/unpack lowering for Vec[u8,16]. Size L. Checked open: lib/e/simd.e:108 shuffle is lane-by-lane (comment says a register class would select one shuffle); gp09.e still has `while lane < 16usize` store loop; not a queue row (M4-08 has no row); grep work-done for SIMD/interleave found only C029 Vec lowering.

### C233 — Direct argument-to-register call lowering in codegen_x64 (finish db-perf item 1 acceptance) (0%)

Opened 2026-11-03 from docs/db-perf-plan.md:60 by the single-list audit; not previously a queue row. Acceptance: A call moves an argument already in a register straight to its parameter register and the result straight to its destination register, with the outgoing-slot path kept only for stack args. benchmarks/db/run.py shows the SQLite scan at >=70% of C (now 56-59%) on both hosts, no cell slower, stage 2 = stage 3 fixed point re-baselined. Size L. Checked open: regalloc.e already has crosses_call preference (D1607) but doc records acceptance missed; load_call_arguments path still the rule in src/codegen_x64.e; no queue row mentions call lowering or db scan ratio.

### T062 — Native `neper mcp` stdio server exposing symbol, diagnostics, references and AST-subtree tools (0%)

Opened 2026-11-03 from docs/llm-mcp-server.md:57 by the single-list audit; not previously a queue row. Acceptance: A Neper binary speaks MCP JSON-RPC over stdio (reusing lib/x/mcp/protocol.e framing) and serves get_symbol_definition, get_build_diagnostics, get_symbol_references and get_ast_subtree from the existing index/check/parse JSONL, with a per-request arena that stays flat across 1000 calls. A conformance test drives it from a scripted client and compares payloads to the CLI output. Size M. Checked open: lib/x/mcp/protocol.e exists but is Appdor table-oriented; no compiler-query MCP binary under tools/ or src/; T032 is the Appdor services/mcp-server only; grep work-done mcp: only L049 builders.

### T063 — Add --no-trivia to `neper tokens` and `neper parse` (parser-core trivia suppression) (0%)

Opened 2026-11-03 from docs/llm-mcp-server.md:68 by the single-list audit; not previously a queue row. Acceptance: `tokens --no-trivia` and `parse --no-trivia` emit no space/comment/newline-trivia records and still validate against the v1 stream schema; byte offsets of remaining records are unchanged. A conformance fixture compares output against the full stream with trivia filtered out. Size S. Checked open: grep no-trivia in src/*.e returns nothing; not in queue.tsv or work-done.

### T064 — H33: per-component token-pressure report over whole verified agent trajectories (0%)

Opened 2026-11-03 from docs/post-m2-llm-hardening.md:1289 by the single-list audit; not previously a queue row. Acceptance: A harness script reproduces, from archived traces, tokens per component (card, context, edit plan, diagnostic, test view, retrieval, schemas, retries, verification) per tokenizer, keeping failed/abandoned trajectories in the denominator, and enforces frozen default byte/token budgets for the card, context projection, successful check, root diagnostic, all-pass test result and final verification. Re-running on the archive gives byte-identical totals. Size L. Checked open: grep H33 in work-done.jsonl = 0; queue T027/T040/T041 text does not mention token budgets; only C051 tokenizer profile (H26) is done.

### T065 — H43: performance-regression obligations with pre-registered statistics bound into receipts (0%)

Opened 2026-11-03 from docs/post-m2-llm-hardening.md:1549 by the single-list audit; not previously a queue row. Acceptance: A change contract can name a benchmark obligation (baseline artifact, workload/data hashes, metric, threshold, repetitions, warmup) and the runner returns pass/regression/inconclusive/invalid from a distribution, never a best run. Fixtures for a known regression, noisy data, changed baseline, background disturbance and cherry-picked samples never produce a pass; result artifacts and environment identity enter the receipt. Size L. Checked open: grep H43 in work-done = 0; not named in T039-T042 queue text; benchmarks/baseline/gate.py judges fixed budgets only, not contract-bound obligations.

### T066 — H45: export H34 receipts and H35 contracts into a signed release-provenance envelope (0%)

Opened 2026-11-03 from docs/post-m2-llm-hardening.md:1586 by the single-list audit; not previously a queue row. Acceptance: A command exports receipt, change contract, environment identity, lock and artifact digests into the selected external provenance schema; an independent verifier accepts it and rejects altered source, dependency, builder, artifact, receipt or signature. Unsigned output is labelled local traceability and an export claiming more than its inputs is refused. Size L. Checked open: grep H45/provenance in work-done = 0; M6-01..06 milestone files do not mention it; hardening-tracks.json M6-provenance status planned; no SLSA/in-toto reference in repo docs.

### L203 — GP-02/GP-03/GP-06 workloads: cross-platform CLI, parallel build executor, streaming parser with designs and oracles (0%)

Opened 2026-11-03 from docs/general-purpose-verification.md:147 by the single-list audit; not previously a queue row. Acceptance: Each has a written design (arenas, ownership, concurrency, errors, module graph) and a runnable Neper program with a Go/Rust/C oracle, passing on Windows and Linux in both suites, covering Unicode args, cancellation/timeouts/graceful shutdown, and malformed/partial input with bounded buffers. Size XL. Checked open: grep 'GP-0[2-8]|GP-1[1-4]' across repo finds only docs/roadmap.md and the verification doc; benchmarks/gp contains only gp09.e and gp10.e.

### L204 — GP-07/GP-13 workloads: persistent bounded cache and binary format reader/writer (0%)

Opened 2026-11-03 from docs/general-purpose-verification.md:152 by the single-list audit; not previously a queue row. Acceptance: A bounded cache with eviction/fragmentation control under concurrent access and a binary format reader/writer (endianness, packed layouts, zero-copy slices, malformed-file rejection, round trips) each ship with design, oracle and fixtures on both hosts, with RSS flat over a soak run. Size L. Checked open: no gp07/gp13 program in benchmarks/gp, tests/ or examples/; not a queue row.

### L205 — GP-04 workload: long-running HTTP service with bounded steady-state memory and graceful shutdown (0%)

Opened 2026-11-03 from docs/general-purpose-verification.md:149 by the single-list audit; not previously a queue row. Acceptance: An e.net.http service with request arenas, backpressure, logging and concurrent shutdown runs a soak with many connections where RSS stays within a fixed bound and every worker joins on shutdown; Windows and Linux; compared against a Go or Rust oracle on the same script. Size L. Checked open: no GP-04 program in repo; roadmap.md:988 says it waits on e.async/e.net.http; not in queue.tsv.

### L206 — GP-05/GP-08 workloads: e.db client over a C library and a plugin-style C ABI (0%)

Opened 2026-11-03 from docs/general-purpose-verification.md:150 by the single-list audit; not previously a queue row. Acceptance: A database client built on an existing driver and a stable exported-ABI plugin (callbacks with context pointers, version checks, foreign ownership, failure isolation) each have a written design and fixtures that pass under both linkers on both hosts. Size L. Checked open: no GP-05/GP-08 program; drivers exist in lib/x but no plugin-ABI workload; grep GP-05|GP-08 only hits roadmap and verification doc.

### L207 — GP-11/GP-14 workloads: interactive terminal application and image/audio transform pipeline (0%)

Opened 2026-11-03 from docs/general-purpose-verification.md:156 by the single-list audit; not previously a queue row. Acceptance: A terminal app (incremental input, redraw, resize, signals, state restore on exit) and a media pipeline (large buffers, staged arenas, native library interop, parallel stages, sustained memory bound) each pass with a design record, oracle output and a no-leak soak. Size L. Checked open: no GP-11/GP-14 program in repo; roadmap.md:992,994 names dependencies only; not in queue.

### L208 — GP-12 workload: multi-package application with reproducible vendoring and clean-room rebuild (0%)

Opened 2026-11-03 from docs/general-purpose-verification.md:157 by the single-list audit; not previously a queue row. Acceptance: A multi-package application resolves transitive dependencies from a lock with checksums and licences recorded, and a clean-room rebuild on Windows and Linux yields byte-identical artifacts from the same manifest and signed registry snapshot. Size L. Checked open: no GP-12 program; M6-01..03 milestone files exist without queue rows; grep GP-12 hits roadmap.md:970 only.

### C234 — Containers that hold obligated or borrowed values: failure-safe insert and dynamic retention checking (0%)

Opened 2026-11-03 from docs/m25-h01-ownership.md:389 by the single-list audit; not previously a queue row. Acceptance: A generic container can own an affine/obligated element across growth and failed insert (value not lost, cleanup run exactly once), and a pointer-bearing value stored into a dynamic container is checked against @noescape/region rules (currently only a documented limitation, E-SAFETY-0020 for module stores only). Fixtures cover relocation, insert failure and reset-before-use. Size XL. Checked open: m25-h01-ownership.md:389-393 and m25-h02-regions.md:443 state both as remaining; grep work-done for container retention/obligated resource finds nothing; not a queue row.

### L209 — Add e.algo.approx: vertex cover, knapsack FPTAS, LPT and greedy makespan, half-approx max-cut (0%)

Opened 2026-11-03 from docs/algos-2.md:86 by the single-list audit; not previously a queue row. Acceptance: Each routine returns a solution plus its proven ratio bound and is checked against a brute-force optimum on small instances (cost <= ratio * OPT). Set-cover and bin-pack wrappers reuse e.algo.combopt (set_cover_greedy, bin_pack_ffd, Christofides) instead of reimplementing. Size M. Checked open: grep lib for vertex_cover, fptas, lpt, makespan, longest processing: no hits; combopt only has set_cover_greedy/bin_pack_ffd/tsp_*; not in queue.tsv or work-done.jsonl

### L210 — Add e.algo.online: ski rental (with predictions), Belady/marking paging, move-to-front, online facility location (0%)

Opened 2026-11-03 from docs/algos-2.md:127 by the single-list audit; not previously a queue row. Acceptance: Each online policy runs over a request sequence and reports its cost next to the offline optimum; fixtures assert the stated competitive ratio on adversarial sequences (ski rental <= 2x, MTF <= 2x, marking <= k x). Size M. Checked open: grep lib for ski_rental, belady, competitive ratio, facility_location: no hits; move_to_front exists only inside coding.e/brotli as a codec step; not in queue or work-done

### L211 — Add iterative linear solvers (CG, GMRES with restart) to e.algo.linalg over a matrix-free operator (0%)

Opened 2026-11-03 from docs/algos-2.md:171 by the single-list audit; not previously a queue row. Acceptance: cg and gmres solve SPD and general nonsymmetric systems given an operator callback, converging to a stated tolerance and agreeing with the dense LU solution on fixtures. gfx.mesh's private conjugate_gradient is replaced by the shared one. Size S. Checked open: grep lib for gmres: none; only conjugate_gradient is lib/e/gfx/mesh.e:1331 (mesh-private) and math/opt.e (nonlinear CG); linalg/matrix.e has qr/eigen/svd but no iterative solver; Strassen was explicitly skipped in algos.md:878

### L212 — Add classical MDS and Johnson-Lindenstrauss random projection to e.ml.reduce (0%)

Opened 2026-11-03 from docs/algos-2.md:244 by the single-list audit; not previously a queue row. Acceptance: mds embeds a distance matrix with stress matching scikit-learn on fixtures; jl_dimension(n, eps) and Gaussian/sparse random_projection preserve pairwise distances within (1+-eps) on a seeded test set. Size S. Checked open: grep lib for multidimensional scaling, johnson-lindenstrauss, random_proj: only an LSH note in algo/sketch.e; e/ml/reduce.e fns are pca, tsne, umap, frequent_directions only

### L213 — Add e.algo.discrepancy: Beck-Fiala, Spencer-style balancing, derandomized max-cut by conditional expectations (0%)

Opened 2026-11-03 from docs/algos-2.md:290 by the single-list audit; not previously a queue row. Acceptance: Colouring routines return a +-1 assignment whose discrepancy meets the Beck-Fiala bound on bounded-degree set systems; the conditional-expectation max-cut returns a cut >= half the edges. Fixtures compare with brute force on small inputs. Size M. Checked open: grep lib for beck.fiala, spencer, discrepancy, conditional expectation: only unrelated mentions in rand/quasi.e and csp.e; no module e.algo.deterministic/discrepancy

### L214 — Add WireGuard packet framing over e.crypto.noise (MAC1/MAC2, TAI64N, cookie reply, transport messages) (0%)

Opened 2026-11-03 from scripts/algos/decisions-pending.md:743 by the single-list audit; not previously a queue row. Acceptance: A wireguard module builds and parses initiation, response, cookie and transport messages over noise initialize/write_message/read_message, interoperating byte-for-byte with a reference WireGuard implementation's captured handshake vectors, with replay-window and malformed-packet tests. Size M. Checked open: lib/e/crypto/noise.e:15 ponytail note names the framing as deferred; grep lib for wireguard: only noise.e; not in queue or work-done

### L215 — Harden e.dist.consensus: Raft pre-vote and config revert, Multi-Paxos accepted values, VR out-of-order (0%)

Opened 2026-11-03 from scripts/algos/decisions-pending.md:457 by the single-list audit; not previously a queue row. Acceptance: Seeded message-loss/reorder fixtures check safety (one leader per term, committed entries immutable) with pre-vote on, a truncated config entry reverted, Paxos promises carrying accepted values, and VR Prepare buffered when out of order. Size M. Checked open: lib/e/dist/consensus.e ponytail notes at lines ~260, 680, 814, 886 still present; grep pre_vote: none

### L216 — Add a secure wipe primitive and apply a zeroization policy across e.crypto key-holding APIs (0%)

Opened 2026-11-03 from docs/algorithm-format-conformance.md:31 by the single-list audit; not previously a queue row. Acceptance: A non-elidable wipe(buf) exists and every crypto API holding key material (aead, kdf, kx, sign, noise) wipes its scratch/state on done/error, with a test reading the buffer back to prove it is zero. Each module header documents its zeroization and nonce rules. Size M. Checked open: grep lib/e/crypto for zeroiz|wipe|secure_clear: none except kdf.e:9 comment stating nothing wipes caller buffers

### L217 — Hostile-input, limit and differential sweep for compression/archive/media decoders (A0 matrix) (0%)

Opened 2026-11-03 from docs/algorithm-format-coverage.md:64 by the single-list audit; not previously a queue row. Acceptance: For gzip, zlib, zstd, bzip2, lzw, zip, tar, png, jpeg, webp, wav, mp3, an e.test.fuzz fixture feeds truncated/corrupt/bomb inputs and asserts distinct errors, bounded memory, traversal/symlink rejection (tar, zip), and differential agreement with a native reference on valid vectors. Size L. Checked open: all 37 rows of docs/algorithm-format-coverage.json have status planned; e.test.fuzz is used by only tests/selfhost/fixtures/link/test_fuzz and test_gaps; no per-format hostile fixtures found under tests/

### L218 — Nesting, entity-expansion and limit tests for text parsers (json, xml, yaml, html, csv, ini, mail, mime, uri, protobuf) (0%)

Opened 2026-11-03 from docs/algorithm-format-coverage.md:53 by the single-list audit; not previously a queue row. Acceptance: Each parser has fixtures proving configurable max depth/members/bytes, duplicate-key policy, billion-laughs/entity expansion rejection, invalid-UTF-8 behaviour, and an incremental-parse equivalence check against the one-shot result. Size L. Checked open: fmt/json.e has max_depth/Options but no per-format limit fixtures exist; matrix rows format.json..format.yaml all status planned; grep fmt for expansion/bomb hits only brotli, opus, pdf, xml

### L219 — Crypto and statistics conformance evidence: vectors, nonce rules, NaN/inf contracts (A0 matrix) (0%)

Opened 2026-11-03 from docs/algorithm-format-conformance.md:26 by the single-list audit; not previously a queue row. Acceptance: Each crypto.* and statistics matrix row links golden vectors, malformed-input and constant-time notes, and e.algo.stat tests pin NaN/infinity/overflow behaviour per function. check_algorithm_format_matrix.py then rejects any row still marked planned without linked evidence. Size L. Checked open: docs/algorithm-format-coverage.json: 37 of 37 rows status planned; scripts/check_algorithm_format_matrix.py only validates schema and evidence names, not links

### T067 — Regenerate the repo rewrite-coverage inventory against the delivered widget and module set (0%)

Opened 2026-11-03 from docs/rewrite-coverage-verification.md:10 by the single-list audit; not previously a queue row. Acceptance: scripts/audit_repo_coverage.py is rerun and its status column resolves names to delivered widgets/modules, so the 'implemented' count is no longer zero and the 8,435 missing/extension names are reduced to real extension work or explicit aliases. Size M. Checked open: doc status table shows 0 implemented and 8,435 missing/extension; snapshot predates the e.ui/e.fmt deliveries; no queue row or work-done record for re-auditing

### T068 — pacman P0: strict project.yaml parser, canonical project.lock writer, SemVer ranges and PubGrub resolver (0%)

Opened 2026-11-03 from docs/pacman.md:410 by the single-list audit; not previously a queue row. Acceptance: A `neper pacman` command group resolves a manifest into a byte-canonical project.lock with module-export validation and PubGrub conflict explanations. Golden fixtures cover the manifest/lock formats, resolution ties, conflicts and yanked versions; tests/conformance/package/p0.package.json is produced by the real emitter rather than hand-written. Size XL. Checked open: grep -ril pacman src lib tests scripts: only src/assets.e (comment) and generators; no PubGrub/project.lock/project.yaml producer in src or lib; queue.tsv and work-done.jsonl have no pacman row; work-queue.json T012 says 'Missing: the producer (M6 pacman P0)'.

### T069 — pacman P1: immutable content-addressed cache, path dependencies, frozen/offline sync and virtual module map (0%)

Opened 2026-11-03 from docs/pacman.md:412 by the single-list audit; not previously a queue row. Acceptance: A clean machine populates its cache from project.lock, then builds byte-identically under --frozen --offline with path deps resolved through a virtual module map and build-manifest integration. Concurrent syncs never expose partial store entries and a mutable Git ref cannot change a locked sync. Size XL. Checked open: No pacman store/cache/sync code in src/ or lib/; src/project.e only does project-root and source-root discovery; no queue row.

### T070 — pacman P2: signed registry client, Git adapter, mirrors, publish/yank, cache verify and GC (0%)

Opened 2026-11-03 from docs/pacman.md:415 by the single-list audit; not previously a queue row. Acceptance: Registry metadata and release archives verify against signing keys and tree digests, Git deps resolve to full commits with submodules rejected, and publish rejects path/unpinned deps. A fake registry fixture covers tamper, yank, mirror failover and network failure leaving lockfile and store unchanged. Size XL. Checked open: No registry/publish/yank code in src or lib; docs/pacman.md sections 6 and 10 unimplemented; absent from queue.tsv.

### T071 — pacman P3: controlled generation tasks with hash, scratch execution, capability policy and source maps (0%)

Opened 2026-11-03 from docs/pacman.md:418 by the single-list audit; not previously a queue row. Acceptance: A declared task runs in a scratch directory under a denied-by-default capability policy and produces byte-identical declared outputs with generated-source maps and JSON records. Denied capabilities fail before the task starts and no dependency runs code at resolution or install time. Size L. Checked open: grep for pacman task/capability code in src and lib returns nothing; absent from queue.tsv and work-done.jsonl.

### T072 — Embed dependency-package assets and external runtime assets in pacman builds (0%)

Opened 2026-11-03 from docs/pacman.md:156 by the single-list audit; not previously a queue row. Acceptance: A package dependency's declared assets enter the root link identity and e.ui.asset lookup with the same name, metadata and SHA-256 rules as root assets. External runtime assets are declared and verified without being embedded. Size M. Checked open: src/assets.e reads only the root project manifest ('version 1 embeds only declarations in the root project'); no dependency asset code; no queue row.

### L220 — Constant-time P-256 ECDSA, BIP-340, FFDHE, ML-DSA and RSA-PSS signing to replace the fail-closed stubs (0%)

Opened 2026-11-03 from docs/security-audit-2026-09-24.md:H3 by the single-list audit; not previously a queue row. Acceptance: p256_public_from_secret, schnorr_public_from_secret/schnorr_sign and the other secret-key operations in e.crypto.sign return real results with fixed-schedule control flow and masked selection, verified by emitted-control-flow inspection and a timing-independence fixture. Known-answer vectors pass on Windows and Linux. Size L. Checked open: lib/e/crypto/sign.e lines 1299, 1337, 1520, 1530, 1645, 2173 still `ret ..., Unsupported` before the old bodies; audit text says these fail closed; no queue or work-done row for constant-time restoration.

### C235 — Contain module source selection to the project root: resolve symlinks and re-stat at open (0%)

Opened 2026-11-03 from docs/security-findings.md:407 by the single-list audit; not previously a queue row. Acceptance: A symlink in the source tree whose resolved target escapes the project root is rejected with a diagnostic, and the entry is re-checked at open time. A fixture with an escaping symlink and a swap-after-readdir case fails before the change. Size S. Checked open: src/project.e lines 411 and 463 still accept entry.kind == .Symlink as a source candidate with no realpath containment; security-findings 'Deferred' list names it; no queue row.

### L221 — e.fmt.macho: read-only Mach-O headers, load commands, segments and symbol tables (0%)

Opened 2026-11-03 from docs/ethical-hacking.md:42 by the single-list audit; not previously a queue row. Acceptance: Parses thin and fat Mach-O files into headers, load commands, segments/sections, symbol tables and dyld info with hand-built fixtures cross-checked against otool/nm text goldens. Truncated and malformed inputs return errors, never panics. Size M. Checked open: ls lib/e/fmt shows elf.e and pe.e but no macho; ethical-hacking P9 says the Mach-O read-only slicing is 'an S2 follow-up, not queued'; absent from queue.tsv.

### L222 — TLS 1.3 server and client with P-256/RSA credentials, client-certificate auth and PSK session resumption (0%)

Opened 2026-11-03 from docs/tls-p256-openrouter.md:40 by the single-list audit; not previously a queue row. Acceptance: e.net.tls serves with P-256 and RSA server keys (not only Ed25519), requests and verifies client certificates, and resumes sessions through PSK tickets; 0-RTT stays refused unless replay-safe. Loopback fixtures and an external interop probe cover each mode. Size L. Checked open: docs list client auth, resumption and 0-RTT as unsupported; lib/e/net/tls.e line 1297 'resumes nothing'; validate_server_credentials returns an Ed25519 key only; grep for CertificateRequest/psk finds nothing.

### T073 — Android validation matrix: 4 KiB/16 KiB pages, API-level symbol resolution, APK upgrade and wrong-key rejection (0%)

Opened 2026-11-03 from docs/android-cross-compilation.md:64 by the single-list audit; not previously a queue row. Acceptance: A script runs the counter APK on emulators with 4 KiB and 16 KiB page sizes across supported API levels, checks Bionic symbol resolution, and verifies upgrade under the same key and rejection under another. Results are recorded as pass/fail rows. Size M. Checked open: grep for 16384/page-size/upgrade in scripts/*android* and scripts/build-apk* finds nothing; doc lists these under 'remaining validation'; C219 and C104 cover other work.

### L223 — Apply safe-area insets in the Android counter app and edge-to-edge windows (0%)

Opened 2026-11-03 from docs/HANDOVER-OPENGL.md:40 by the single-list audit; not previously a queue row. Acceptance: The counter app's content no longer sits under the status bar on a device with insets, using e.ui.window safe_insets. An emulator screenshot check compares the top content offset against the reported inset. Size S. Checked open: examples/android/counter/src/main.e has no inset/safe reference while lib/e/ui/window.e exposes safe_insets; handover lists it under limits; no queue row.

### T074 — Get both full self-host suites green from a clean worktree, including the unreached NeperOS fixture rows (0%)

Opened 2026-11-03 from HANDOVER.md:40 by the single-list audit; not previously a queue row. Acceptance: tests/selfhost/run.ps1 on Windows and run.sh on Linux each finish with zero failures from a clean detached worktree. The previously unreached rows (sheetfixture through diskfixture) pass or their table expectations are fixed. Size L. Checked open: HANDOVER.md says the suite was 'never yet green end-to-end' and Linux run.sh never run; work-done notes repeat 'full suites not run'; queue T048 covers only the OpenGL shared-change verify.

### T075 — neper-tooling: make a comptime parameter a symbol and reference target in index and uses output (0%)

Opened 2026-11-03 from docs/tooling.md:293 by the single-list audit; not previously a queue row. Acceptance: index-file lists a comptime parameter as a parameter symbol and a body use is a read reference targeting it, with schema and golden updates. Existing local and parameter output stays byte-identical. Size S. Checked open: docs/tooling.md line 293 still says 'A comptime parameter is not yet a symbol'; no work-done record for comptime parameter symbols; not in queue.tsv.

### L224 — Browser: ad and tracker blocking on every request (95%)

PART: e.net.fetch.Config.block_hosts and allow_hosts (from e.net.policy.parse_filter_list: ||host^ rules and @@||host^ exceptions) refuse any request that has a referrer (a subresource) to a listed host or its subdomains with BlockedByFilter before connecting, count them in Client.blocked, never filter the document, and an empty list blocks nothing; examples/browser reads an optional neper-browser.filters list; net_fetch_filter pins listed host, subdomain, unlisted host, document, exception and no list. `$third-party` rules block only requests from another site (hosts equal or one a subdomain of the other count as one site) and page.blocked_count reports the refusals since a page began loading; net_fetch_filter pins both. Request-type options (`$script`, `$image`, `$stylesheet`, `$xhr`, `$font`, `$document`, and `~type` negations) apply too: Request.dest is set by the page for script, stylesheet, image, font and xhr fetches and a typed rule blocks only those types (net_fetch_filter pins script-only, ~image and untyped). `$domain=a.com|~b.com` limits a rule to pages on the listed domains (net_fetch_filter pins listed, unlisted and excluded pages). `||host/path^` limits a rule to URLs under that path (net_fetch_filter pins both). Still open: a profile switch to turn blocking off. e.net.policy already parses Adblock Plus filter lists (parse_filter_list). Nothing applies them when a page loads. Acceptance: e.web.page asks the parsed rules before each subresource and script fetch (document, script, image, stylesheet, xhr, font types and the third-party flag known to the loader), a blocked request fails as blocked and is counted per page, the main document is never blocked, rules load from the profile and can be switched off, and a fixture with a blocked tracker script, an allowed first-party script and an exception rule pins all three outcomes.

### L225 — Triage and fix the open GitHub issues of nebosa-company/neper (687 on 2026-10-31) (0%)

Backlog only, nothing to start now. `gh issue list --repo nebosa-company/neper --state open` listed 687 open issues on 2026-10-31 (numbers up to #1620; labels: bug 205, SEO 25, internal 2, the rest unlabelled), most of them against the e.web modules (CSP, page, iframes). Acceptance: every open issue is either fixed with a regression test that fails if it comes back and closed, or closed with a reason; work them in groups by module (read the titles first with `gh issue list --json number,title,labels`), group duplicates, and re-run the issue count at the start of each session because new ones keep arriving.

### C236 — Android target: Bionic ELF executables, then a NativeActivity APK built by Neper (0%)

Backlog only; blueprint is docs/os/android.md. First acceptance: an aarch64-android ELF (x18 never allocated, 16 KiB PT_LOAD alignment, BTI note, no DT_TEXTREL, PT_INTERP /system/bin/linker64) pushed to /data/local/tmp runs under adb and prints through __android_log_write; then e.mem/e.io/e.fs/e.time fixtures pass on the emulator or a device. Later phases per the document: AXML manifest encoder, APK v2 signer verified by apksigner, NativeActivity with ANativeWindow, JNI by table slot, pthread-based e.thread. Needs an emulator or device, neither is on this machine yet.

### C237 — iOS target: signed arm64 Mach-O, UIKit through the Objective-C runtime, IPA packaging (0%)

Backlog only; blueprint is docs/os/ios.md. First acceptance: a platform-7 (iOS simulator) Mach-O main with an ad-hoc CodeDirectory runs under xcrun simctl spawn and codesign --verify accepts it; then AppDelegate defined through objc_allocateClassPair, UIApplicationMain, a CAMetalLayer view drawing a frame through the existing msl.e backend. Reuses the macOS Mach-O writer and Metal work. Needs a Mac; App Store identity keys and Assets.car are the last milestone and the highest risk.

### C238 — FreeBSD target: ELF with the FreeBSD identity, carry-flag syscalls, per-OS constant tables (0%)

Backlog only; blueprint is docs/os/free-bsd.md. First acceptance: an x86_64-freebsd static ELF (EI_OSABI 9, .note.tag ABI note) runs under a FreeBSD 14.x VM, writes and exits; then e.mem/e.io/e.fs/e.time fixtures where each differing constant (CLOCK_MONOTONIC 4, O_CREAT 0x200, EAGAIN 35) has a fixture that fails if the Linux value is used, and a syscall failure fixture proving the carry flag becomes an err. Later: thr_new and _umtx_op threads, kqueue, aarch64, dynamic linking via /libexec/ld-elf.so.1. Syscall numbers come from the target release headers, generated, never hand-typed.

### C239 — FreeRTOS target: Thumb-2 back end, relocatable ELF output, C shim for the kernel API (0%)

Backlog only; blueprint is docs/os/free-rtos.md. Blocked first on whether the linker can write ET_REL objects (check before sizing). First acceptance: a thumbv7m object whose main prints through semihosting and exits runs under QEMU (lm3s6965evb or mps2-an385) linked with the FreeRTOS ARM_CM3 port; then known-answer fixtures for __aeabi_uldivmod/ldivmod and memcpy, then the neper_freertos.c shim with e.thread/e.sync/e.time fixtures, then neper size and neper stack-report. Thumb bit, branch range and literal pools are the traps. Later: standalone image with a memory map, thumbv6m/v7em, RV32.

### C240 — Zephyr target: Neper as an out-of-tree Zephyr module with a C shim (0%)

Backlog only; blueprint is docs/os/zephyr.md, and it depends on C227 for the Thumb-2 back end (native_sim needs only the existing x86-64 emitter). First acceptance: a neper-zephyr module (zephyr/module.yml, CMake import of libapp.a, Kconfig, neper_zephyr.c) builds for native_sim/native/64 under WSL or Linux CI, and a Neper main prints through the shim and exits; then e.thread/e.sync/e.time fixtures including the reversed-priority and cooperative-priority checks, then qemu_cortex_m3 once C227 delivers the Thumb-2 back end. No Zephyr API is called directly; everything goes through the shim.

### C241 — z/OS and CICS target: z/Architecture back end, GOFF linker output, EBCDIC literals, CICS bridge (0%)

Backlog only; blueprint is docs/os/z-os.md. Largest item of the six: a new ISA back end (R1 parameter list, R13 DSA, LE prologue/epilogue), GOFF record output (ESD/TXT/RLD/END) with 8-character member name mangling, IBM-1047 string lowering, e.mem over GETMAIN/FREEMAIN, e.io over CICS queues, and a CICS command wrapper mapping EIB RESP/RESP2 to err. No mainframe or emulator (Hercules, z/PDT) is available here, so the first acceptance is a GOFF byte-level check against IBM's documented record layout and a decision on how code is ever run.

### C242 — float/vector register class: allocate xmm registers, floats stop living in general registers as raw bits (x64 first, a64 after) (0%)

Opened from docs/compiler-optimizations.md. Acceptance: regalloc has a second register class; a scalar float and a Vec[T,N] stay in xmm across operations and calls under the System V and Win64 conventions; D786 copied-storage convention replaced; fixtures for float loops, Vec arguments and returns and callee/caller-saved xmm pass on both hosts; stage2==stage3 holds; cachegrind instruction count of benchmarks/cpu float workloads drops and is recorded.

### C243 — Vec shuffle, interleave, pack and movemask selection so GP-09 stops using scalar lane loops (0%)

Opened from docs/compiler-optimizations.md. Needs C242. Acceptance: punpck/pshufb/pack/movmsk (and a64 zip/tbl equivalents) selected for the Vec interleave and pair-assembly operations; GP-09 Base16 output unchanged and runtime p50 within 3x of C (was 1576 ms against 50 ms); a fixture compares every shuffle against the scalar lane loop.

### C244 — scalar replacement of aggregates and copy elision (struct copy was 16% of all instructions, D930-D933) (0%)

Opened from docs/compiler-optimizations.md. Acceptance: a non-escaping struct or tuple local is split into scalar locals before promote_locals; a copy whose source is dead afterwards, and a returned aggregate built in place, emit no copy; fixtures prove aliasing and address-taken aggregates are left alone; cachegrind instruction count on the records and db-scan workloads drops and is recorded.

### C245 — value numbering, instruction simplification and division by constants in NIR (0%)

Opened from docs/compiler-optimizations.md. Acceptance: dominator-based value numbering removes repeated pure computations and repeated loads with no intervening store; rule-driven simplification covers identities (x+0, x*2^k, x^x, compare folds); unsigned and signed division and modulo by a constant use a multiply sequence, checked against the division instruction over edge values; compile time on GP-01 grows less than 3%.

### C246 — loop-invariant code motion and induction-variable strength reduction (0%)

Opened from docs/compiler-optimizations.md. Acceptance: loop detection and rotation on NIR; pure invariant computations hoist to a preheader; i*scale address arithmetic in counted loops becomes a pointer bump; fixtures prove no hoist across a store that may alias, a call, or a trap; sieve, sort and hash in benchmarks/cpu improve and are recorded.

### C247 — bounds-check elimination from range facts, extending elide_null_checks (0%)

Opened from docs/compiler-optimizations.md. Acceptance: an index proven below len by a loop bound, a dominating compare or a slice split emits no check in the checked release build; a check that can fail is kept and a fixture traps on it; counted-loop checks hoist out of the loop; checked-release cost on benchmarks/cpu is measured before and after.

### C248 — likely/unlikely edge hints on trap paths and basic block placement (0%)

Opened from docs/compiler-optimizations.md. Acceptance: trap, check-failure and error paths are marked cold; blocks are laid out with the likely successor falling through and cold blocks at the function end; branch folding removes empty blocks and jumps to jumps; stage2==stage3 holds and the instruction count on GP-01 is recorded.

### C249 — register allocator: interval splitting, copy coalescing, loop-depth spill weights and rematerialisation (0%)

Opened from docs/compiler-optimizations.md. Start after C242 since both change regalloc data. Acceptance: a value may live in a register for part of its range and in memory for the rest; two-address and call-argument moves coalesce; the spill choice weighs use count by loop depth; constants and frame addresses are rematerialised instead of spilled; the allocator self_test and the emit sweeps pass; spill count and instructions on GP-01 are recorded.

### C250 — inliner cost model replacing the flat 40-instruction cap (0%)

Opened from docs/compiler-optimizations.md. Acceptance: the decision weighs callee size against bonuses for constant arguments, a single call site and a call inside a loop; validated with benchmarks/baseline/inline_cap.py on GP-01 and the CPU workloads for image size and runtime, with the result recorded; the compiler still builds itself to the same bytes.

### C251 — tail calls, switch lowering (jump tables, bit tests) and branch folding (0%)

Opened from docs/compiler-optimizations.md. Acceptance: a call in tail position with matching stack arguments becomes a jump under both conventions, and a deep recursion fixture runs in constant stack; dense integer switches compile to a bounded jump table and sparse ones to a binary search; fixtures cover the edge values of each.

### C252 — decide whether regions and value semantics guarantee non-aliasing, and emit noalias facts in NIR (0%)

Opened from docs/compiler-optimizations.md. First step is a decision row after reading docs/m25-h02-regions.md and docs/m25-h05-value-semantics.md. Acceptance: if the spec guarantees it, NIR carries a no-alias fact on region and by-value pointers, and C245 value numbering and C246 LICM use it with a fixture that fails if a possibly aliased store is ignored; if it does not, the decision row says so and the item closes.

### C253 — a64 Linux CI job running the aarch64 differential check on an arm runner or under QEMU (0%)

Opened from docs/compiler-optimizations.md: CI has macos-14 for native macOS a64 but no Linux a64 job, so a64 codegen changes (C242, C243, C249) are checked only in WSL. scripts/a64-differential.sh runs prebuilt x64/aarch64 pairs named in build/a64/out/names.txt, which scripts/a64-differential.ps1 builds on Windows, so the job needs a Linux step that builds the pairs itself. Acceptance: a workflow runs the differential on ubuntu-24.04-arm (native) or ubuntu-latest with qemu-user, libc6:arm64 and aarch64-linux-gnu-gcc, builds both architectures of every fixture in the list, and fails when any pair differs outside the five expected ones (when_target, os_fs, fs_basics, os_gaps, debug_dump); a deliberately broken a64 select_binary makes the job fail; the job is triggered by workflow_dispatch and by pushes touching src/codegen_a64.e, src/regalloc.e or src/nir.e.

### C254 — capacity limits name themselves: every fixed pool, arena and token table reports its own exhaustion (0%)

Opened from the weakness review: arena, bootstrap tokens and resolver tokens each filled up and the diagnostic blamed the change, and MAX_LOCALS 256 truncated silently. Acceptance: an inventory of every fixed capacity in src/ and the C bootstrap (constant, file, what fills it); each exhaustion raises one code E-CAP-nnnn naming the limit, its value and the current use; no capacity truncates silently; one generated fixture per capacity that fills it exactly and one past it, the first compiles, the second reports its code; the inventory is the fixture list, not a second document.

### C255 — generic deferral probe matrix: instances over instances at every site that can hold a deferred value (0%)

Opened from the weakness review: three generic-deferral bugs in a row (data.map, e.bytes, e.data.iter) and the D163 instance-over-instance case, each found by a module hitting it. Acceptance: a generated fixture set crosses {return, assign, let, call argument, field, index, annotation, comptime branch} with {T, Inner[T], Outer[Inner[X], Y], Vec[T]} and checks the value at run time on both hosts; every combination passes or is a named refusal with a code; the checker has no site that reads a still-generic type as concrete.

### C256 — miscompile net: narrow-width and constant edge values through every call, return and store path, run against two back ends (0%)

Opened from the weakness review: unwidened narrow extern returns, negative narrow constants (lower_constant), uncleared mem.alloc under neper-self and a local shadowing a module-scope function each shipped silently and were found late. Acceptance: a generated fixture covers i8/i16/i32/u8/u16/u32 at min, max, -1 and 0 through extern return, extern argument, struct field, constant, comparison and shift, with the expected value computed in the generator; each case runs x64 and a64 and under the bootstrap and neper-self, and any pair disagreeing fails; the emit sweep runs it; reverting any of the four past fixes makes a case fail.

### C257 — extern call path: register arguments and caller-saved-only spills instead of stack slots and spill-all (0%)

Opened from the weakness review: extern calls cost about 15 ns over C (D1597) because arguments pass through stack slots and every live value is spilled. C249 owns the allocator; this item owns the call sequence. Acceptance: a call to a leaf extern with up to six integer arguments emits register moves only, and only values live across the call and held in caller-saved registers are spilled; the db-scan microbenchmark of D1597 is within 5 ns of the C baseline; struct-by-value (D1675) and variadic calls keep their fixtures; cachegrind instruction count for the benchmark drops and the number is the test threshold.

### L228 — WASI e.os surface so the WASM target runs e.fs, e.io, e.time and e.proc-free programs (0%)

Opened from the weakness review: the WASM design (D5213) and the browser engine are blocked on a missing WASI e.os; node 22/24 run WASI here. Acceptance: os.wasi.e adds the per-target variant for files, clocks, random, args, environment and exit through wasi_snapshot_preview1; unsupported operations (threads, processes, dynamic linking) return a named error, not a trap; fs_basics, time and the e.str, e.fmt and e.math fixtures run under node on WASM with output equal to the native run; the browser engine builds for WASM and loads a static page.

### L229 — operating-system accessibility preferences: reduced motion, high contrast, text scale, screen reader presence (0%)

Opened from the 2026-09-27 accessibility audit: the AT bridge (D1602-D1604) exists but OS preferences are unread. Acceptance: e.ui exposes one prefs() record read from Windows (SystemParametersInfo, UISettings), macOS (NSWorkspace accessibility display options) and Linux (portal settings over D-Bus) with a change notification; reduced motion disables the D1412-D1450 motion paths, high contrast selects a token set, text scale multiplies font tokens; a fixture sets each preference through a test hook and checks the frame differs; every preference unreadable on a host returns the default and a flag saying so.

### T076 — suite runner that finishes: bounded workers by free memory, per-fixture timeout, resumable, stderr tolerant (0%)

Opened from the weakness review: Windows suites hit the stderr trip and WSL crashes, WSL is short of RAM, and the Linux suite needs GitHub (linux-suite.yml). Acceptance: the runner picks -j from free commit before starting and lowers it on pressure; a fixture past its timeout is killed and reported, not left hanging; an interrupted run resumes from the last finished fixture; stderr output never fails a fixture whose exit code and stdout match; a deliberately hanging fixture and a deliberately stderr-writing fixture are the tests; scripts/check_suite_parity.py keeps both hosts' fixture lists equal.

### T077 — land script for the shared tree: stage listed paths only, merge queue and decision rows by id, allocate D-numbers under a lock (0%)

Opened from the weakness review: peers' uncommitted decision rows and queue edits live in the same files, a peer commit swept hunks and a D-number, and landing needs foreign-commit checks before push. Acceptance: one command takes explicit paths and a message, refuses git add -A, takes only this session's hunks from docs/decisions.md and docs/work-queue.json, allocates the next D-number from a lock file so two sessions never share one, refuses to push when git log origin/master..HEAD holds commits not made by this session, and regenerates progress.html and the digests; a two-session fixture on a scratch repo shows no lost row and no duplicate number.

### C258 — language: a local may shadow a module-scope function and a builtin type name (reopen D66's reserved set) (0%)

Opened from the 2026-11-04 language design review. Problem: E-NAME-0003 ended 35 of the 134 builds that failed on a compile code in 2026-09-20..27, more than any other code (D1678), and its largest slice is the rule that a local or parameter may not reuse a module-scope function (`text`, `row`, `cell`, `level`, `width`, `at`) or a builtin type name (`target`, `Vec`, `i8`). That makes the legality of `let width = 3` depend on declarations elsewhere in the module, which is exactly what a generated line may not depend on (spec section 1, goal 1); D1678's rename fix mitigates it but does not change the design. Proposal: reserve only `use` qualifiers and the `target` namespace. A local or parameter may shadow a module-scope fn, const, var or type name and the builtin type names, because spec section 2 already resolves types and values by position. Module scope keeps one definition per name, so `grep -n ^fn dot` still returns one line, and a call through a shadowed name is a local type error (E-NAME-0004), never an ambiguity. D1678's machine-applicable rename stays for qualifier collisions and duplicate locals. Token and cost: this deletes a repair class. No new syntax, no extra token on any line, a shorter trap section on the card, and it removes one failed build plus one repair turn per occurrence, which is the most expensive failure mode measured. Guard: the five implicit operations, the no-overloading rule and the explicit-cast rule are untouched, and the index, tokens and parse streams keep their shape. Not done: fixtures that shadow a module fn, a const, `i8`, `Vec` and `str` as a value name accept and format; a call through the shadowed name rejects E-NAME-0004; the card re-renders without those two traps; lang-stats repeat rate is re-measured on transcripts written after the change.

### C259 — language: cross-module pointer facts come from the declaration, never from the callee's body (0%)

Opened from the 2026-11-04 language design review. Problem: the lexical region subset in section 11 plus `callee_keeps` reads another module's body through any number of modules to decide whether a container retains a borrowed pointer. D1677 records the consequence as found and not fixed: a warm build writes an image the clean build refuses with E-SAFETY-0013, and the documented fix adds a body edge per foreign function, so every body edit invalidates its callers and both section 12 and section 15 pay for it. Proposal: a call that hands a region value or a view across a module boundary is legal only against a declared contract on the parameter (`@noescape`, `own`, or `@borrows` for the result direction), which is the fact the interface already serializes in artifact format 14. Nothing outside the function's own lexical scope is read; an unannotated callee gives no answer, so it cannot be inferred from. Token and cost: one attribute line per boundary function that hands region values, in exchange for a warm build that equals a clean one. A silently wrong image costs a rebuild, a bisect and a debugging turn, the most expensive repair class measured, and the checker loses the alias-chain cases that only the body walk accepted, so its own context shrinks. Guard: the single-function rules (move at most once, cleanup on every exit, a view of a mutated container) stay as they are. Not done: D1677's warm and clean builds agree by a fixture; the alias-chain fixtures the walk alone accepted are annotated or moved to @unsafe; both suites pass.

### C260 — language: make the zero value total - every enum and union enum declares a member at 0 (0%)

Opened from the 2026-11-04 language design review. Problem: section 7 carries a carve-out. A type that holds, at any depth, an enum with no member at 0 has no zero value, so `= zero`, a module-scope `var` without an initialiser and `try` in a function returning it are compile errors naming the outermost type and the offending field. A generator must therefore read the whole type graph before it knows whether a line is legal, the same unseen-context dependency as C258. Proposal: an `enum` or `union enum` declaration must name a member whose backing value is 0, the mirror of the existing rule that renames an error whose FNV-1a hash is 0. Then every type has a zero value, and the carve-out, its three error sites and the exceptions in the zero table go. `err` = ok, a slice = nil and the null resource already fit. Token and cost: one member on an enum that starts at 1 (`None = 0`), against a rule and three diagnostics that leave every future context, and generated code writes `= zero` and `try` without first resolving the type. Guard: `= undef` and E-SAFETY-0017, the refusal of a value that can only be invalid, are unchanged. Not done: the section 7 table and rule rewrite, the declaration-time diagnostic naming the enum and the member it needs, accept fixtures for `= zero` and `try` over such an enum, a reject fixture for the declaration without a 0 member, and the card's zero section re-rendered.

### C261 — language: protocols are found by an explicit marker, not by a derived snake_case name (0%)

Opened from the 2026-11-04 language design review. Problem: `K.hash(v)` resolves to `fn sensor_hash` by deriving the name from the type's name through a Unicode snake_case algorithm (`HTTP2Client` becomes `http2_client`), plus a separate rule for a generic type's stem, a rule for which alias spelling keeps the nominal declaration, and a recorded lookup edge when a supplied fallback is used (section 9, D48). Every implementation must reproduce the algorithm byte for byte, and a reader cannot tell from `fn sensor_hash` that it is the protocol for `Sensor` without running the algorithm in their head. Proposal: `@proto(Sensor)` on the function, and the same fact in `neper index`. Lookup matches a marker rather than a spelling. The five resolution rules, the supplied fallbacks and the call-site syntax stay. Token and cost: one attribute line per protocol function, nothing at any call site, and the spec loses the case algorithm with two name-resolution rules that an agent otherwise has to load to predict a resolution. A typo becomes a missing marker refused with one code, instead of a silent fall back to the supplied hash. Not done: the attribute in the grammar and the checker, the index edge, diagnostics for a duplicated or mismatched marker, and conformance fixtures for a generic type's protocol and the str fallback.

### C262 — docs: one normative home per fact (section 13 versus tooling.md, section 11 versus the H-track files) (0%)

Opened from the 2026-11-04 language design review. Problem: the same fact is written twice, so a tooling change is read and edited in two places. Section 13 Toolchain is 603 of the spec's 5149 lines and restates docs/tooling.md; section 11's region and concurrency rules restate docs/m25-h02-regions.md and docs/m25-h04-concurrency.md. Three smaller self-contradictions sit on top: `unreachable` is a keyword although section 14 calls it the one builtin that is a keyword rather than a core function; `usize` and `isize` are keywords although they are only type names; section 8 allows copying an `Arena` to transfer it while section 11 makes it affine. Proposal: each fact lives in exactly one document and every other mention links to it. The spec keeps semantics, tooling.md keeps the command and stream contracts, and the H-track files keep their measurements as evidence rather than as normative text. Token and cost: this is the largest context win in the list. An agent landing a tooling change pays for both copies today, and the card, the digest and the tasks page inherit the duplication. Guard: no semantic change; a moved fact gains a link where it was; the card stays generated, never hand-edited. Not done: the split, the three contradictions resolved, and a link check so a moved fact cannot be silently unlinked.

### C263 — bootstrap: the card carries the language, not the C bootstrap's defects (0%)

Opened from the 2026-11-04 language design review. Problem: docs/llm-neper-card.md tells an author that code under `src/` must also build with the C bootstrap, which refuses `-=` and `x > CONST {` and truncates a function past 256 locals silently. Those are bootstrap defects printed as language rules. A generator avoids legal syntax and still cannot know when the truncation bites, and a clean bootstrap build is not proof of anything. Proposal: the card carries the language and nothing else. The bootstrap either accepts the surface the grammar defines or it is gone, which is C088, the first queue row. Until then the card carries one sentence pointing at C088 instead of a list of shapes to avoid. Token and cost: the card is loaded on nearly every edit turn, so a `src/`-only exception list is tokens spent on a defect the self-host build would catch anyway, and a silently truncated function costs a debugging session. Not done: the card source edit and re-render, and either the three bootstrap fixes with a fixture per shape or C088's closure.

### C264 — language: labelled break and continue (0%)

Opened from the 2026-11-04 language design review; this is the one addition the review recommends. Problem: v1 has no labels, so a generated loop that must leave two levels writes a flag local, an `if` guard at every level and a check after the inner loop. That is three lines and a mutable binding per nesting level, all of which a reviewer follows to see where control goes. Proposal: an optional label on `for` and `while` with `break outer` and `continue outer` resolved at parse time, no dynamic behaviour, no new keyword. Token and cost: measured rather than assumed. Add the shapes to benchmarks/tokens/profile.py and to the card's token table before the grammar revision; the labelled form must be no worse than the flag form per nesting level, which it should beat by roughly ten tokens at depth two, and the tokens and parse streams gain a label field. Guard: `break` and `continue` without a label mean what they mean today, and a label that names no enclosing loop is a compile error. Not done: the grammar revision, the parser, the checker, the formatter and the card re-render; two fixture programs at depth two and three, checked against the flag spelling; the token profile updated.

### C265 — a syntax error exits with its diagnostic: the error path must not consume the machine (0%)

Found while porting x.duckdb.duckdb to DuckDB v2 and trying to build the Linux self-hosted compiler: a parse failure in lib/e/str.e (mem.bitcast[f32], syntax the September bootstrap does not know) did not report and exit. Measured in a freshly restarted 5GB WSL instance with nothing else running, RSS went 3148 kB at t=3s to 4352956 kB at t=6s, then 4550256 kB at t=9s, with MemAvailable down to 15MB, the process in D state, and exit code 1 only after the allocator had exhausted the VM. The diagnostic printed correctly (E-SYNTAX-9999 at four sites); the defect is that emitting it retained 4.5GB and stalled on swap for minutes instead of returning. Acceptance: a program with a syntax error reports every diagnostic it currently reports and exits 1 with peak RSS within a small fixed multiple of the source size (measured, and stated in the fixture); the same failure on Windows and Linux; a fixture that parses a file with many errors and asserts the exit code and a bounded peak; and no error path allocates per-diagnostic state that is never released.

### C266 — the bootstrap builds the tree again: refresh it, or make the seed path the contract (0%)

Found while getting tests/selfhost to reach its DuckDB fixture. build/windows/neper.exe and build/linux/neper are both 0.0.96-neper0 and neither can parse the current tree: lib/e/str.e:13 stops at a function type as a struct member, src/check.e:924 at a type-member limit. The bootstrap is a fixed point -- it must parse what it builds -- so once the language gains syntax it cannot build src/main.e, and the suite fails at selfhost.ps1:39 'self-hosted compiler slice did not build'. Windows only appeared healthy because a self-hosted compiler from 6 Nov sat in build/; Linux had nothing until run.sh gained the NEPER_SEED path run.ps1 already had (83bc973bb), and a compiler cross-emitted from the Windows self-host works as that seed. Acceptance: a bootstrap that builds the current src/main.e on both hosts with no NEPER_SEED set, and a suite run on a clean checkout that reaches its fixtures; or, if the seed becomes the contract, both runners require NEPER_SEED and fail with one message naming how to produce it; plus a check that asserts the bootstrap parses the tree so this cannot rot silently again.

### C267 — emitted binaries are reproducible: no field may depend on which compiler binary ran (0%)

Found while verifying 18 bootstrap-lint fixes by differential build. Two compilers built from the same command line, from source states that differ only by the fix, emit binaries that differ in exactly 8 bytes on many fixtures and match on others. The 8 bytes sit inside an ASCII field `!003d88c0<8 hex>:...` in the image, and the control proves they track the compiler binary rather than the code: the untouched Nov 6 self-hosted compiler differs from a current build in the same 8 bytes at the same offset on the same fixture. Emitting the same source twice with the SAME compiler is byte-identical, so this is not general nondeterminism. The consequence is that byte-identical output cannot be used to check a codegen change, which is the cheapest and strongest regression test available: masking the field is required before any build comparison, and that masking is knowledge held outside the tree. Acceptance: identify what the 8 hex digits hash (candidate: the compiler image, its build id, or a toolchain signature), make the field a function of the translation unit and not of the compiler that performed it, or document it as an intentional stamp in the binary format's spec; a check that builds one source with two different compiler binaries and compares the images byte for byte, so this cannot regress silently; and the header comment in the emitted image's format doc stating whether reproducibility across compiler builds is promised.

### C269 — the artifact path emits the same debug info as the whole-program path (0%)

Found once crew_windows could finally be reached: 'crew_windows at -j 1 is not the image linked from its artifacts (--time)'. Repro: emit-em-all over crew_windows then link-em the twelve artifacts, and separately emit-executable the same fixture at -j 1, both in the default (debug) mode. Sizes 75560 linked against 76072 direct. A PE section compare (dumpbin /headers) shows every section identical except .debug_info: 3FFA virtual / 4000 raw linked, against 4068 / 4200 direct -- the whole 512-byte file difference is that section's rounding. The code is byte-identical: 0 differing bytes across 0x400..0xB000, which is the headers' payload, .text (A8F5/AA00) and .idata (1B0/200). Inside .debug_info the first four bytes are the unit length, 0x3FF6 linked against 0x4064 direct, and the streams diverge at +0x10A6: the linked copy lists `e.os.PollRegistration`, the direct one `e.text.utf8.Iterator`, so the subprogram DIEs are in a different order and 110 bytes differ in total. In --release the two paths are byte-identical (E5321649... both), which is why this has never been seen: release emits no debug info to disagree about. Pre-existing and not this session's: the untouched Nov 6 self-hosted compiler produces the same two hashes (C1E733B0... linked, FE538AEC... direct). Acceptance: the artifact path and the whole-program path emit the same .debug_info for the same program in the default mode, so the two images are byte-identical there as they already are in --release; crew_windows' artifact comparison then covers both modes again; and a check pins the two images byte for byte in a debug build, which is what would have caught this before a suite run had to reach line 1067 to notice. Where the order comes from, located for the fix: the PE path assembles the debug rows in `assemble_vars` (src/em_link.e:558, D1582: 'The named locals of every copied function, placed where its code landed, in code order: what the image's DWARF describes'), reached from `link_artifact_image` (src/main.e:7744). Code order is already the stated intent, so the artifact path is ordering its subprogram DIEs by the function table it builds from artifacts rather than by where the code landed, while the whole-program path emits them in source order. So the fix is to sort both by code offset, not to reorder the CU. Deferred rather than attempted here: it is an emitter change on a path that only a debug build exercises, the code itself is already byte-identical, and crew_windows now asserts byte-identity in --release where it holds.

## Implemented

### C001 — Lexer over the closed token registry

src/lex.e

### C002 — Parser and syntax tree

src/parse.e; a grouped return value may carry a binary operator (D247) -- after `ret` the tuple `ret (a, b)` and an ordinary `(expr)` are told apart by a scanner-copy lookahead for a comma at depth one, pinned by link/ret_group

### C003 — Module graph and import resolution

src/graph.e

### C004 — Order-independent name resolution

src/resolve.e

### C005 — Integer arithmetic, bitwise, shifts, division

link/bitwise, link/shifts, link/division

### C006 — if / while, break / continue, block scopes

link/control; `else if` chains lower as the nested if they are (D245), pinned by link/else_if

### C007 — when over target.arch / target.os

Section 6's conditional compilation (D216): `when` takes a condition over `target.arch` and `target.os` compared with their members, under `!`, `&&`, `||` and parentheses, settled at compile time; both blocks type check and the taken one is emitted; any other condition is a bool the interpreter evaluates (D220), and one it cannot is refused under E-COMPTIME-9999 (link/when_target on both platforms, check/when_condition). `target.arch` and `target.os` are values of `target.Arch` and `target.Os` anywhere (D223): compared, switched over exhaustively, held and passed

### C008 — for over ranges, arrays and slices

tests/neper0

### C009 — Fixed arrays, zero / undef, .len

link/storage

### C010 — Slicing and mutability propagation

link/storage

### C011 — Structs: layout, literals, field places

link/aggregate

### C012 — Pointers, & / *, *const, auto-deref

link/aggregate

### C013 — Aggregate copies and ABI pass / return

link/advanced

### C014 — Enums, bare unions, union enum

link/variants

### C015 — switch, exhaustive and non-fallthrough

fixtures/variants

### C016 — defer, both forms

tests/neper0

### C017 — err / try / ok and named errors

link/error_collision

### C018 — Multi-return and destructuring

link/scalar

### C019 — const and integer comptime folding

link/generic_folding

### C020 — Generic functions [T: type], [N: usize]

link/generic_instances

### C021 — Generic aggregate types

link/generic_same_name; check/generic_instance_field and link/generic_instance_alias pin one used as a field type, named directly and through an alias; link/data_iter pins a nested instance as a type argument -- `Filter[Map[Iter[i64], i64, i64], i64]` -- which read its inner argument as the outer's until the argument block was claimed before it was filled (D145)

### C022 — Protocol resolution, spec 9 rules 3 and 5

check/protocol_*

### C023 — Iterator protocol <t>_next

tests/neper0; link/data_iter calls it through a type parameter as `I.next(&it)`, on a generic iterator whose `_next` is instantiated from the receiver's own arguments (D145)

### C024 — Supplied cmp (rule 4)

link/sequence_cmp, tagged_union_cmp

### C025 — Supplied hash (rule 4)

link/supplied_hash, folded_hash

### C026 — Supplied eq (rule 4)

link/supplied_eq; link/test_assert pins the floats, which rule 4 always listed and the compiler had not supplied: every NaN equals every other and the two zeros are one (D142)

### C027 — Supplied format (rule 4)

link/str_format, link/io_printf expand scalars, str, bool and err; slices and arrays recurse an element at a time as `[a, b]`, nesting included (D189); an enum prints its variant name (D190); a type's own `<t>_format` is called with the builder, inside a sequence too (D191); check/format_compound_argument pins the struct without one

### C028 — Scalar floating point f32 / f64

link/float_scalar; f16 / bf16 still unlowered. link/math_exact pins `math.sqrt` as the one float intrinsic -- `sqrtss`/`sqrtsd` behind a NIR opcode of its own, correctly rounded and checked by its bits (D146). `fma` is exact by integer arithmetic on the significands, and the thirteen transcendentals are fdlibm's over f64 with a Payne-Hanek reduction of its own, each measured within 1 ULP against mpmath at 200 bits in the four link/math_* fixtures (D147)

### C030 — Atomic[T] and memory orderings

link/atomic_ops runs all thirteen across every width and both signs; link/atomic_threads proves the lock prefix under contention; check/atomic_* pin the ordering rules. e.sync and e.channel are unblocked

### C031 — extern with @import / @cc and the C ABI

link/extern_import binds and calls foreign symbols on both platforms: a PE import directory with one descriptor per library, and a dynamic ELF with PT_INTERP, DT_NEEDED and GLOB_DAT slots. It also pins a narrow signed return being widened, which the convention leaves undefined above the declared width -- an unwidened -1 read as 0xFFFFFFFF made every `< 0` check on a foreign call pass. Section 5's closed table of which types cross is enforced at every extern declaration (D192): check/extern_slice_parameter and check/extern_slice_return pin a slice and a tagged union refused. A trailing `...` is a C variadic (D193): link/extern_variadic prints through snprintf with an f64 past the fixed parameters on both conventions, and check/variadic_narrow_argument pins that an i16 there is refused rather than promoted

### C034 — Unsafe boundaries enumerable (v1 precursor for T2 H27)

The build manifest's `unsafe` array lists every declared and trusted boundary with module, function and line (D355, D371), including every dereference inside `@nocheck` (D497); symbol indexes carry the boundary kinds (D513). Context queries now describe an intended `--unchecked` image as `checks: off` plus one whole-image boundary for every subject (D555), and query batches preserve that policy across every context and catalogue answer (D556). `manifest-em ARTIFACT... --json` completes the source-free path: it reads required Inventory sections, preserves checked/unchecked policy and hashes every artifact, with exact source-manifest parity on both hosts (D557).

### C037 — Semantic search and safe change planning (v1 precursor for T2 H17)

`uses-file --json --symbol module.name` (D362): every use the checker resolved -- calls of the function and its instances, dispatches that chose it, instantiations, its name as a value -- with the enclosing function and span, the roots that keep it alive, the count of calls through values that no name can trace, and a completeness flag; the contract says what a safe-delete claim and a rename plan may conclude. A rename is a plan with file-hash preconditions and a re-check postcondition, applied by nothing but the harness (D376); the signature-change plan -- a parameter added last at the declaration, its argument at every resolved call, refused with the site where the function is a value or a protocol's choice -- round-tripped by both suites (D406); a field's uses -- every access and literal naming it, recorded by the checker -- and its rename plan, round-tripped by both suites (D420). `plan-change-signature-file --order` reorders and removes, a removal refused while the body names the parameter, applied and re-checked by both suites (D415, D439). an error's uses and rename (D451). A resource's moves are facts of its function's context page (D486): every site the checker consumed a local -- closed, returned, rebound, handed to an `own` parameter -- is a compiler-proved `move` fact with its span, and a folded `if` a `phase` fact (which D463 had written as a record with no kind); pinned per host by `context_moves`; a local bound to a view of another (`&x`, `x[a..b]`, `x.items`, a literal holding `&x`) is a `borrow` fact naming both (D487), the relation D393's rules hold the body to. The alias and same-spelling fixture (D509): `uses_alias` imports `deep as d` and `other`, both declaring `pick`, with a local spelled `pick` too; `uses-file` of `deep.pick` reports the two calls through `d` alone, `other.pick` its own two, and the rename plan rewrites those sites and the declaration and nothing of `other` or the local, applied and run on both hosts -- and found that a module beside a `src/main.e` operand was spelled under `operand` in every record and the manifest, now `project-src`. The comptime-only reference (D510): a call in a constant's initializer is evaluated by the interpreter and no body check sees it, so `uses-file` reported no use of a function only a constant reaches and the rename plan carried the declaration alone, leaving the call behind; the evaluation now records the call at its site, `uses_comptime` pins the use and the plan per host, applied and run. The callback fixture (D511): `uses_callback` binds a function to a local and passes it as an argument, called only through a parameter; `uses-file` reports the two `value` sites and one indirect call, the plan rewrites both and the declaration, applied and run on both hosts. The generated reference (D512): a plan's edit inside a range the operand's map marks as the generator's names its owner and where in the generator's input the text begins, and `apply-plan` refuses the plan whole, nothing applied; `plan_generated` pins the plan per host and the refusal. The index names every reference of a large module (D528): its tables are sized by the tree, where a cap of four thousand had dropped the rest of `check.e`'s references without a word, and renaming the compiler's own locals through it holds in both suites. A type's rename plan (D515): the subject names a type, every module's index is taken in memory and each reference whose target is the type gives a site, through a qualifier or bare, in an annotation or a literal, with the declaration; `plan_rename_type` pins the plan per host, applied and run; `uses-file` of a type reports the same sites as `type` uses (D516), pinned by `uses_type`; the functions spelled with the type's name -- its `cmp`, `eq`, `hash`, the protocol lookup's spelling -- are renamed with the type (D517), which the probe found the plan leaving behind: `sort.in_place` over the renamed type no longer found its `cmp`; and the rename of such a function on its own is refused, naming whose protocol it is by its spelling (D518), where the plan had been made and broke the program applied; only the protocol's spellings follow a type (D537), where a helper merely named for it had, and both suites rename `check.same` at five hundred and forty sites and the type `check.Type` at nearly four hundred by plan, apply, and build the stable stage from the result. `index-project` over the compiler and its library -- a hundred and forty-two modules, two hundred thousand records -- answers in seven seconds where it took a hundred and eighteen, its stream buffered, and the project walk that `check-project`, `test-project` and `index-project` share leaves another target's variant out, where `os.linux.e` on windows had failed the whole index (D544). A generated reference inside a dependency's map carries its generator ownership and original into every edit plan (D563)

### C038 — GPU contracts frozen before M3 (M2.5-core H13)

Design scope closed by D664 (`m25-gpu-closure.md`): D660 freezes the typed fault ABI and H01-H07 mapping; the checked manifest keeps three CPU/Vulkan fault fixtures pending for M3 rather than reporting runtime evidence

### C039 — Explicit CPU/GPU dependency composition (M2.5-core H21)

Design scope closed by D664: D661 freezes past-only completion tokens, cross-queue visibility, whole-buffer use/release tracking, failure/discovery state tables and twelve pending M3 fixtures. Runtime implementation remains M3

### C040 — End-to-end GPU cost and artifact lifecycle (M2.5-core H22)

Design scope closed by D664: D662 freezes `StagingLimits`/`queue_with`, the two-clock timeline, complete cache identity, bounded wait-on-full staging and five pending M3 fixtures; batching, graphs, pinned transfer and optimized CPU execution remain deferred

### C041 — Executable numerical and capability contracts (M2.5-core H23)

Design scope closed by D664: D663 serializes and validates 21 CPU/SPIR-V/PTX matrix rows, six launch-precondition classes and twelve pending CPU/Vulkan fixtures. Device modes and measurements remain M3/M4 evidence

### C046 — Compiler responsiveness and correctness (v1 precursor for T2 H10)

Phases separated so a check links and generates nothing (D314, D320); artifacts keyed by source, mode and interface hashes and published atomically (D205-D214, D343, D369); mutation fuzzing and a nesting bound (D341); deterministic failure codes for every exhausted limit (D344); images byte-equal across worker counts and perturbed schedules (D331); stage-2 == stage-3 and clean == incremental in both suites; one-shot query latency measured -- 25 ms for a small check, 269 ms for the whole compiler -- and no daemon adopted on it (D372), a batch of queries over one check instead (D409: twenty queries 447 ms, not 6.6 s); the crew's workers set themselves up on their own threads, the body phase of the compiler's cold release build 134 -> 69 ms at eight workers (D402). `test-impact-file --changed m1,m2` names the tests an edit reaches over the resolved call graph, pinned by the corpus over the test project (D423), and `test-file --only n1,n2` runs those alone (D424). `benchmarks/metamorphic/metamorphic.py` checks two transformations that must change nothing -- comments removed through the token stream build a byte-identical image in both modes, declarations reversed behave the same -- over three fixtures in both suites (D438), and (D477) two more over four: every local renamed to a name of the same length through the index's `local` and `parameter` symbols and their references (D484; the token scanner of D477 is gone) builds a byte-identical image in both modes, and every struct's fields reversed behaves the same; every function and type renamed through the index's spans (D478) builds the same image once the names the trap messages carry are put back. `benchmarks/differential/differential.py` runs the library's SHA-256, SHA3-256 and base64 over random inputs and holds every answer to Python's hashlib and base64, both suites (D449). `benchmarks/differential/bootstrap.py` builds seventeen neper0 programs with the C bootstrap and with the compiler and holds their exits and output alike, both suites (D456). A sixth transformation (D508): every typed integer literal outside a `const` or a `case` label becomes a module-scope `const` named to the literal's length, and the image is byte-identical in both modes over the four fixtures -- a constant folds into its uses. A seventh, `formatted` (D525): the root through `neper fmt -`, idempotent and the same behaviour; and both suites format every module of the compiler, build a compiler from the result and require the compiler it builds from the original sources to be the stable stage byte for byte -- the formatter's contract over sixty-five thousand lines; and the compiler built from its own sources with every comment blanked to spaces is the stable stage byte for byte (D526), `benchmarks/metamorphic/strip_comments.py` blanking them through the token stream, and so is the compiler built with every typed literal hoisted to a constant (D527, `hoist_constants.py`), which found the proofs reading literals alone, and with every local renamed through the index (D528, `rename_locals.py`), which found the index dropping every reference past four thousand in a module; and the compiler built with every function and type renamed through the index of every module (D529, `rename_symbols.py`) builds the original sources to the stable stage byte for byte, as does the compiler built with every struct's fields reversed (D530, `reverse_fields.py`), twelve hundred fields moved, and the one built with every module's declarations in reverse order (D531, `reorder_declarations.py`) -- the seven transformations of the harness, all but the two that hold an image byte-identical by construction, turned on the compiler itself; and the library too (D532): the compiler built against `lib/` with every comment blanked, then every literal hoisted, is the stable stage, and the one built against `lib/` formatted -- a hundred and four of its hundred and twelve modules moved -- builds the stable stage (D549); the library's twelve thousand locals and parameters renamed is the stable stage too (D550), which found the index making parameter symbols of a function type's entries; the compilers built against the library with its twelve hundred struct fields reversed and its thirty-six hundred declarations reordered build the stable stage (D551), the foreign modules and `e.mem` keeping their layouts for the other side of an `extern` and for the embedded runtime; and every turn holds in release as well (D533), against a release self-build the suites now build twice byte for byte. Cancellation reaches inside a function (D540), every statement a tick. A compiler-wide structured turn reverses a conflict-free set of 1,571 parameter lists and reproduces the stable stage in debug and release (D562)

### C049 — Compiled LLM cards (v1 precursor for T2 H28)

`docs/llm-neper-card.md` is the current alias of the render of `scripts/render_card.py`: the grammar's own productions, its keyword set, the diagnostic registry's families and the stream versions, around the prose of `llm-neper-card.src.md`, stamped with the grammar revision and a content hash, and both suites refuse a card that is not the render (D374). per-symbol API records are `context-file --module` (D397), the card's examples are checked by both suites (D404), and its tool section names every semantic command, plan and the edit loop they make (D425). every diagnostic code the card lists carries its standing -- `verified` by a golden or a suite, `present` in the compiler's source alone, `planned` in the registry alone -- read from the repository at render time (D440); the sixteen documented commands use the same evidence rule (D566), and every displayed grammar production is marked `present` without claiming a fixture map that does not exist (D567). The same render is archived at `docs/llm-neper-card-0.1.md`; the current alias and language-qualified card are both checked, and a future language version writes a new qualified path without overwriting the old one (D569)

### C054 — Error detail and partial failure (M2.5-core H07)

Closed by D659. D360 preserves a primary failure across cleanup; D417/D443, D479 and D480 carry caller-owned provenance through host, filesystem and process paths; D614 makes concurrent byte I/O independent; D655-D658 preserve generic stream progress, nested provenance and both allocation-failure steps. Existing compact callbacks remain compatible through additive `DetailReader`/`DetailWriter` types. The normative behavior, measurements and remaining legacy boundary are recorded in `m25-h07-error-detail.md`

### C055 — Protocols, generics and compile-time context (M2.5-core H06)

Closed by D730. `explain-file --json` reports every dispatch, failed candidate, generic argument, selected requirement, requesting site, compile-time phase and target layout (D359, D430, D463, D667, D670). Comptime calls, recursion, specializations and diagnostics have explicit structured budgets (D218, D344, D426), while every instance reports NIR and machine-byte cost (D453). Exact function-typed parameters provide explicit strategy selection and preserve operation identity through dependent generic forwarding (D668-D669). Spec section 9 now states equality/hash coherence; exhaustive supplied and declared property fixtures pin reflexivity, symmetry, transitivity and equal-hash agreement, including a harness that detects an intentionally incoherent declaration (D726-D727). Equivalent implicit and explicit strategies agree across a module while a reverse strategy remains distinct (D728). A recursive strategy chain reaches its finite comptime base and is accepted at exactly 66 instances but refused at 65 with E-COMPTIME-0001 (D729). Reproducible five-run Windows and Linux reports over 256 equivalent nominal types find identical instance bytes and image sizes, with no measured explicit-strategy check-time penalty (D730, `benchmarks/protocol_strategies`)

### C056 — By-value ABI and alias semantics (M2.5-core H05)

Closed by D654. D358 defines snapshots and reports copy/elide statistics; D650 covers generic aggregates, D651 hidden multiple-return storage, D652 foreign C writes, and D653 cross-module calls in debug plus release inlining. Format 11 prevents snapshot-semantics objects from linking with the former format-10 ABI. The closure record is `m25-h05-value-semantics.md`; callee-effect proof remains an optional optimization, not a correctness gap

### C061 — e.meta reflection

link/meta_scalar answers kind, array_len and type_name; link/meta_reflect walks fields and members through comptime Field and Member values, an unrolled for and get/set at the named offset; link/meta_types answers element_type and backing_type, whose result is a type usable as a comptime argument, nested in the other question, or instantiating a generic. link/meta_field_param hands a comptime Field across a call, so the callee is instantiated per field with a return type that depends on which one it got. A type-valued answer stands where a type is written, including a local's annotation: the type grammar takes a trailing call and name resolution classifies it (D126). A comptime `Field` parameterises a function or a type, and link/meta_field_param pins each instantiation's layout to the field it was built around (D127). link/meta_generic asks the same questions from inside a generic function, where the subject is a type parameter: the template body is checked once with nothing bound, so the question stands there and the instance settles it, which is the deferral `mem.size_of` always had (D136); a `let` initialised by such a protocol call follows its declared type the same way (D143). A call whose callee is a binding's `.ty` is a conversion, the same one a written `u8(x)` is, which is how a walk over `meta.fields` puts a parsed value into the field it belongs to -- every parser answers in one width and every field has its own (D139). A bare type parameter is a conversion the same way, `T(bits)`, and its operand may itself be of a type parameter's type; a `bitcast` to `T` stands in the template pass and is checked per instance (D144)

### C063 — Root arena sized by --arena

`emit-executable --arena SIZE` (D225): the size, with k/m/g, is patched into the image -- a word in the PE runtime the entry reads, the four immediates of the ELF startup stub -- so a self-hosted compiler built with `--arena 1g` compiles the compiler in release, which the default 512 MiB does not hold. link/arena_size pins eight mebibytes refusing twelve on both platforms

### C064 — Debug fills 0xCD / 0xDD

Section 11's two fills (D217): a debug build calls `neper_mem_alloc_fill` and `neper_mem_reset_fill`, which fill what an allocation hands out with 0xCD and what a reset gives back with 0xDD; a release build calls the plain entry points and `@nocheck` changes nothing, since the fills are not checks. link/debug_fills pins both fills in debug and their absence in release, on both platforms

### C067 — @reorder opt-in struct packing

D239 built (D746): `@reorder` above a `type ... = struct`/`union` makes `layout` place that struct's fields one alignment class at a time, highest first, declaration order inside a class -- one deterministic function of the type. The declaration-order C default is untouched, and the fields are still stored and reflected as written. `@reorder` on an enum or tagged union, and a reordered aggregate reaching an `extern`/`@import`/`@cc` signature, are refused as E-TYPE-9999; the crossing walk is behind one checker flag, so a program with no `@reorder` pays nothing. `@packed`, `@align(N)` and `@gpu` do not exist yet, so D239's exclusions against them have nothing to refuse. Pinned on both hosts by link/reorder -- 16 bytes where declaration order pads the same three fields to 24, every field read and written through its own offset, one reordered struct nested in another -- and check/reorder_extern

### C068 — NIR, typed SSA-lite

src/nir.e

### C069 — Linear-scan register allocator

src/regalloc.e; a call saves and restores only the registers whose values are live across it, from the allocator's ranges (D226): the compiler's own image is seven per cent smaller. The pool is ten registers (D235): five the calls clobber and five the callee keeps, saved once at entry and restored at the returns, so a value in one of the second five costs nothing at a call. A scalar `var` whose address is used for nothing but loading and storing it is a value with one range and one register, defined again at every store (D236), a loop's own temporaries no longer share one live range with everything the loop touches, and a fixed-register sequence saves only the registers it clobbers that hold a live value. Measured on `e.fmt.json` over the standard files, best of three interleaved against D235: eleven to ninety-nine per cent faster; a byte-counting loop 2.4 times. A comparison whose only use is the branch after it sets the flags and the branch jumps on them, with no materialised bool, and a branch to the next block in code order is dropped (D237); an integer constned under 2^32 is a five-byte load. Measured on `e.fmt.json` over the standard files, best of three interleaved against D235: forty-eight to a hundred and twenty-eight per cent faster, a byte loop 3.3 times. Not in a register still: an aggregate's fields, and a load whose use lies in another block

### C070 — x64 emitter, System V and Win64

src/codegen_x64.e

### C071 — ELF object writer

src/object_elf.e

### C072 — COFF object writer

src/object_coff.e

### C073 — Own ELF linker

src/link_elf.e

### C074 — Own PE linker with kernel32 imports

src/link_pe.e

### C075 — Host runtime intrinsics, both platforms

runtime_pe_x64.asm, runtime_elf_x64.s

### C076 — os.syscall and mem.address_of: the raw kernel path

link/os_syscall carries a path and a stat buffer through getcwd and newfstatat; link/mem_address pins the address itself and D96 keeps it one-way. It is what lib/e/os.linux.e is written over -- six filesystem primitives in neper rather than asm. Linux only by design; the name does not resolve on Windows

### C077 — `.em` module format with Deps edges

src/em.e, fixtures/em

### C078 — Dead-function elimination

only what `main` reaches is emitted, following calls and taken addresses. Both link paths drop the same functions from the same sequence, so an image linked from `.em` artifacts stays byte-identical to one compiled from source -- which link/function_values compares by hash. A minimal e.os binary went from 221 KB to 8 KB and is freestanding again; the compiler's own stage 2 from 4,170,240 to 3,930,624 bytes (D130). Both runtimes are ordered so a function calls only what precedes it and are cut after the last one the program reaches, and the ELF code segment starts where the headers end: and the PE import table declares only what the kept runtime reaches: an empty program is 366 bytes on Linux and 2,048 on Windows, hello world 3,984 and 6,144 (D149, D150, D151)

### C081 — os.thread_create / join / detach

link/os_thread runs and joins a real thread on both platforms: CreateThread on Windows, clone(2) over a self-allocated stack with a futex join on Linux. detach leaks its mapping, wanting a reaper

### C085 — Self-hosted compiler emits its own source

run.ps1:623, run.sh:760

### C086 — Stage 2 == stage 3, byte-identical, both platforms

SHA-256 compare / cmp

### C087 — Bootstrap recovery path archived

docs/bootstrap-archive.md (D208): the SHA-256 of stages one to four on both platforms at the archived revision, stage three the stable one, and the commands that reproduce them from a clean checkout of the tag `bootstrap-archive-1` with no neper binary present

### T017 — Module-plan validation in CI

check_module_plan.py 150 modules; check_module_surfaces.py 28 compiler-resolved sources

### T018 — Build statistics (`--stats`)

`emit-executable --stats` and `run --stats` (D308): the program by files, lines, functions, types and attributes; the build by mode, host, target, reached and unreached modules, image size, wall time and every phase; the run by its time, exit code and peak working set (D311); `--stats-full` adds every pool's capacity beside its use. The link's drop count (D334): reached and unreached functions and the code bytes dropped, from the linker's own reachability walk at no cost to the build

### T019 — `--stats` as a stream record

With `--json`, `--stats` is one flat `stats` record on stdout before the result (D476): one snake_case key per table row with the unit as its suffix, scalars only, phases as `phase_<name>_ms`, `--stats-full`'s pools as `pool_<name>_capacity` and `_used`, rendered by the same row helpers as the stderr table; `build --json --stats` printed nothing before. Schema entry; both suites validate the record

### T020 — Image digest reused on a warm build

D332: the executable's SHA-256 was the one hash a warm build still ran, sixty milliseconds of the compiler's 189. Before the write, `source.matches` compares the packed image with the file at the output path -- the size from a seek to its end first, the way `load` sizes its buffer, and only then the bytes a chunk at a time, stopping at the first that differs -- and, equal, `save_executable` is not called, so the file's mtime stays and nothing watching the binary wakes. `tool.manifest_previous_digest` then takes the artifact's `sha256` from the existing `.neper/<mode>/build-manifest.json` when its one artifact is this path, by the key scan the manifest's other readers use (D255); a manifest missing, unreadable or naming another artifact hashes as before, as does any image that differs. The answer rides `report.build.image_unchanged` rather than a local: `dispatch` is at the bootstrap's 256-local ceiling. Pinned beside the reproducible-build check (D261) in both suites: a third build of the same source into the same output leaves the mtime untouched and its manifest carries the image's digest

### T024 — Self-host regression suite, both platforms

305 fixtures, run.ps1 + run.sh

### T025 — Bootstrap and self-host build scripts, both platforms

scripts/build-*

### C029 — Vec[T,N] / Mask[T,N] and SIMD lowering

`Vec[T, N]` and `Mask[T, N]` are builtins seeded into e.simd with section 4's closed table, width-aligned layout and `meta.kind/element_type/array_len` answers; every `simd.*` intrinsic but `shuffle` is library source lowered lane by lane over scalar code (D148); section 4's operator table -- IEEE `+ - * /` on float lanes, only `+% -% *%`, the bitwise ones and a scalar shift on integer lanes, `& | ^ ~` on masks -- is checked and lowered lane by lane, plain `+` on integer lanes and every comparison refused (D158); `Vec[T, N]{ ... }` is N positional lanes and `v[i]` reads or writes one, bounds-checked (D159); `shuffle`'s `IDX: [N]u8` is a comptime array parameter, bound from a literal of literals and forwardable by name (D160). a `Mask[T, N]` is register-only (D750): a field, an array element, a slice element, a pointee -- `*Mask` or `&m` -- a module-scope `var`, `mem.alloc`'s element type and `mem.size_of`/`mem.align_of` are each refused under one diagnostic kind naming the position and pointing at `simd.bits(m)`, with a check fixture per position in both suites, but for the written `[]Mask`, which shares `mem.alloc`'s sentence, and the module-scope `var`, which the builtins' seeding order already refuses before the guard is reached. a sixteen-byte lane-wise binary operator lowers to one SSE2 instruction instead of a lane loop (D751): IEEE `+ - * /` on `f32`/`f64` lanes, `+% -%` on every integer width, `*%` on sixteen-bit lanes and `& | ^` on all of them, with section 11's canonical NaN produced lane by lane without a constant pool, checked bit for bit by the `link/simd_lanes` fixture in both suites. `~` on a sixteen-byte integer vector is packed too (D752), as the two instructions no unit has one for: `pcmpeqd` against itself for the all-ones operand and `pxor` against that, carried as `VectorBinary` with the one operand given as both, with a sixteen-lane fixture check whose lanes are all distinct. a sixteen-lane mask's `& | ^` are packed too (D753): its lanes are sixteen bytes of `0` and `1`, so the byte lanes' `pand`, `por` and `pxor` answer them bit for bit with nothing new in the back end, and the sixteen lanes belong to `Mask[i16, 16]` and `Mask[i32, 16]` as well as to a byte vector's mask, all checked in the `link/simd_lanes` fixture over two patterns that differ in every nibble. `~` on a sixteen-lane mask is packed too (D754), and is the one operator that cannot reuse the byte vector's form: a mask lane is a byte of `0` or `1`, so `pxor` against all ones leaves `0xfe` where `0` is wanted and the answer is `pcmpeqb` against zero -- all ones in exactly the lanes that were `0` -- subtracted from that zero, which is the `1` those lanes want. It rides on operation rank 11 with the one operand given as both, loads into `xmm1` so the subtraction is the table's own `psubb` into the register the store reads, and `pcmpeqb` is the only new opcode, with the fixture checking both patterns and that a flipped lane still reduces as a mask lane. an eight-lane mask is packed too (D755): a mask is a byte per lane, so eight of them are the register's low half, which every instruction in the table already operates on and `movlps` -- a quadword in both directions -- loads and stores without reading past the slot; the back end multiplies the immediate's lane code by its lane count for the width, and the closed table keeps a `Vec` from ever being eight bytes, so `Mask[i16, 8]`, `Mask[f32, 8]` and `Mask[u64, 8]` are packed while the thirty-two and sixty-four byte vectors they come from are not, checked over two alternating patterns in the `link/simd_lanes` fixture in both suites. a four-lane mask is packed too (D756): four lanes are four bytes, which `movd` -- the first of these moves to need a mandatory prefix -- carries in both directions, so the same four instructions answer `Mask[i32, 4]`, a sixteen-byte vector's mask, and `Mask[f64, 4]`, a thirty-two-byte vector's, checked over two patterns that agree in two lanes and differ in the other two in the `link/simd_lanes` fixture in both suites. a two-lane mask is packed too (D757), and is the one width the vector unit cannot carry to and from memory on this baseline -- `pinsrw` reads a word but SSE2's `pextrw` only writes one into a general register -- so both directions go through r11, the scratch no value is allocated to: a zero-extending word load and the scalar float path's own `movq` in, that `movq` and a word store out, with the packed operation between them unchanged, which makes `Mask[i64, 2]` and `Mask[f64, 2]` packed and leaves only the masks of more than sixteen lanes on the loop, checked over two patterns that agree in the high lane and differ in the low one in the `link/simd_lanes` fixture in both suites. the masks of more than sixteen lanes are packed too (D758), and want no second register: a packed operation reads no lane it is not given, so an operand wider than one is the same instruction once per sixteen-byte chunk over the chunk's own addresses, which lowering names with the `FieldAddress` its lane loop already uses and the back end never sees -- every instruction it is given is still sixteen bytes -- which packs `Mask[u8, 32]`, `Mask[i16, 32]` and `Mask[u8, 64]` and leaves every mask the closed table has packed, checked over patterns that differ in every chunk in the `link/simd_lanes` fixture in both suites. the thirty-two and sixty-four byte vectors are packed too (D759), which is the chunk loop's condition and nothing else: the wide widths are admitted for every lane type and not for a mask's byte lanes only, so a `Vec[f32, 8]` is two instructions and a `Vec[u8, 64]` four, each canonicalising its own NaN lanes and each loaded by the unaligned move a chunk at offset 16 needs, checked in the `link/simd_lanes` fixture over lanes written in every chunk in both suites. a lane-wise shift by a constant count is packed too (D760), and is the first packed form whose right operand is not a vector: the baseline carries the count inside the instruction -- `psllw`/`psrlw`/`psraw`, their thirty-two-bit three and `psllq`/`psrlq`, with the modrm register field saying which -- so lowering takes the form only when the count folded to a `ConstInteger` it can read and is below the lane's width, which leaves every other count on the lane loop and with it the check that traps on a count the width does not admit. The count rides above the immediate's three fields, where everything written before it is zero, and passes through the chunk loop unchanged, so a thirty-two-byte vector is two instructions with the one count. a shift by a count in a register is packed too (D761), which is the shape D760 left on the lane loop and the baseline does have an instruction for: the count rides in the low quadword of a second register instead of a byte of the encoding, flagged by a bit above the immediate's count field, and the third operand the constant form already named keeps it live for the allocator. Section 11's two halves run in order -- a `cmp` against the width guards a trap naming the count and the width in debug, an `and r10, width - 1` masks in every mode -- through `r10` and `r11`, the registers the allocator never hands out, so the check needs no spill and cannot reuse the scalar path's helper, which shifts through `rcx`. A count the width does not admit is no longer a constant either: it takes this form and traps. The signed sixty-four-bit right shift stays on the lane loop, as there is no `psraq`, and a wide vector reloads the count per chunk, since the back end sees one chunk at a time. Checked in both suites by the `link/simd_lanes` fixture, over all three widths in both directions and across a thirty-two-byte vector's two chunks, and by `link/trap_arithmetic`'s new `vshift` mode, which reads the vector trap's own line, column and message. `*%` on thirty-two-bit lanes is packed too (D762), out of the instruction the baseline does have: `pmuludq` multiplies the low half of each sixty-four-bit lane into the whole lane, and `*%` wants a lane's low thirty-two bits, which are the same bits whichever width the product was taken at -- so two of them, one on the operands as given and one on each shuffled by `0xb1`, cover all four lanes, `pshufd` by `0x08` gathers the low doubleword of each pair of products and `punpckldq` puts the four in order. Seven instructions, nothing new in the allocator, the same selection for `i32` and `u32` since a low half has no sign, and once per chunk for a wider vector, checked in the `link/simd_lanes` fixture over four distinct lanes that each need a high half dropped and eight lanes with one written in each chunk, in both suites. Sixty-four-bit lanes take the third `pmuludq` form (D763): the low halves' product plus both cross products shifted up thirty-two, ten instructions and nothing new in the allocator, checked in the same fixture over `i64` lanes whose product crosses 2^64 and `u64` lanes across two chunks, in debug and release on both hosts. Byte lanes take a `pmullw` form (D764): the bytes unpacked against themselves, since 257 is 1 modulo 256, multiplied as words, masked and packed back, fourteen instructions and nothing new in the allocator, checked over sixteen distinct `u8` lanes, sixteen `i8` lanes and two chunks of `u8`, in debug and release on both hosts; every integer width of `*%` is packed now, and `f16` keeps the lane loop by design, its arithmetic being F16C or AVX-512. `--cpu x64-v3` (D765) lowers every thirty-two-byte vector operation as one VEX.256 instruction over a ymm register, the same selection through the emitter's VEX prefix, the level in the build identity and the manifest, `info` listing the levels, the fixture run at the level in both modes on both hosts. Section 5's xmm calling convention is deferred to the vector register class under C044 (D786): on this back end a vector crosses a neper call as copied storage, which no program can observe

### C060 — Comptime str parameters and varargs

link/comptime_str, link/str_format, link/io_printf; all three pack intrinsics expand -- `printf` and `format` against the format string, `gpu.launch` against the kernel's parameters (D778); a `...` declared anywhere else is refused by name at the parameter, `check/argument_pack` (D787)

### C079 — Cross-module inlining, 40 NIR cap

The inlining oracle (D207): every short non-generic function of every module is lowered ahead of the program into a builder of its own, and a call to one that came out at forty NIR instructions or under, with at most one register result, is replaced by a copy of its body -- parameters become the arguments, returns become branches to the continuation, references are re-interned -- in module order on both link paths, so an executable linked from artifacts is still byte-identical. Only a release build inlines (D211): a debug build keeps every call a frame, as section 13's debug-info rule says, and `emit-em-all --release` is where the artifacts' body edges come from. The artifact records a body edge to every inlined callee of another module, and `--incremental` acts on it: link/incremental pins, in release, a body edit behind a signature edge keeping the dependent and one behind a body edge rebuilding it. The oracle is built twice, the second against the first, so a copy is two levels deep and carries the body edges of the body it copies (D212, link/inline_nested: a leaf's body edit rebuilds the module two copies up). `--inline-cap N` and `--explain` (D348): the cap re-evaluated at 0/20/40/80/160 on the compiler compiling 500k lines (forty retained: seven per cent faster than none, twenty as fast at five per cent less image, more buys nothing) and every oracle decision explained on request. The cap holds within a module as well and the oracle stays two levels deep, on D348's measurement (D788).

### C080 — Incremental rebuild on the edge rule

`emit-em-all --incremental` (D205) lets section 12's edge rule decide per module: the artifact on disk stays when its source hash and build mode are unchanged (`--release` builds release artifacts, D211) and every recorded edge still matches the declaration it names in the target's fresh Interface, and is replaced otherwise; `kept`/`rebuilt` is printed per module. The decision is taken after checking and before lowering (D214): every hash an Interface carries comes from the checker -- a body hash is over the declaration's tokens -- so the fresh Interfaces are written from it alone, and a kept module is not lowered, selected or written at all. That is the saving: over the compiler's 31 modules a build with nothing changed takes 10 s against 34 s, and one with a body edit in `decimal` rebuilds `decimal` alone in 13 s, linking byte-equal to a clean build. An artifact holds the whole module now, not the functions this program reaches; the linker prunes. link/incremental pins unchanged sources kept, a body edit behind a signature edge rebuilding only its module with the linked result byte-equal to a clean build, and a signature edit rebuilding the dependent, on both platforms. The artifact path became usable at this size in D213: a CRC per read and a bit-loop `xor` under it had cost minutes. The checker settles the declarations first and the edge rule decides on them, so a kept module's bodies are not checked either, and the load-time checksum is table-driven (D224): a build with nothing changed is 4 s. What is left is the load itself -- every artifact read and widened to decide -- and the declarations of every module. `emit-executable --incremental` and `run --incremental` are the hot build (D319): the keep set settled after the declarations, the kept modules' bodies and code skipped, each fresh module's artifact written as it is selected, and the image linked from every module's artifact, byte for byte the cold build's; the compiler with nothing changed settles in 0.6 s and links in 1.0 s. At scale the artifact path walks a module's own rows and resolves through indexes, bytes are bytes and the NIR section is not written (D320): warm, nothing changed, the compiler builds in 1.1 s, a 500k-line program in 3.1 s and a 2M-line one in 12.6 s, each the cold build's image byte for byte. An unchanged module is not parsed unless something that changed imports it (D322, artifacts carry their imports, format 6): warm builds 0.86 s / 1.5 s / 6.1 s, and a leaf edit costs the warm build plus the module; with the manifest's digests carried on the artifact (D323, format 7) a release-built compiler builds itself warm in 0.24 s, 500k lines in 0.97 s, 2M in 4.0 s; with the artifacts read and validated on worker threads and the link reading through the bounds it holds (D324): 0.19 s / 0.36 s / 1.6 s A one-function edit rebuilds in 100–460 ms on both hosts with a release-built compiler, cold 650 ms, warm 100 ms (D789).

### C062 — Merged error table

src/error_table.e builds it and push_err expands against it; `main`'s failure line reads it in the binary (D199): a root `main` returning anything but `ok` reaches a synthesized `neper_report_failure`, one compare per declared error of the program, which writes `error: <qualified name>` to stderr through the runtime's own write before the exit with code 1 -- link/failure_line pins the module's own error and one of `e.os`'s on both platforms. `{}` on an `err` prints its qualified name from the table, `neper test`'s `error` field is the failure line read back (D253), and no trap row carries an `err` (D790).

### C065 — Spec 11 debug check table and trap protocol

A check that fires follows the trap protocol (D194): the runtime's `neper_trap` writes `file:line:col: trap[kind]: <values>` to stderr and exits 134 on both platforms, and link/trap_bounds pins the record for an index and a slice past the end. Rows delivered: `bounds` (index and slice), the compiler's own `unreachable` points, the `unreachable()` builtin with its literal as the values, which the checker counts as diverging (D195, link/trap_unreachable, check/unreachable_argument), the rows that trap in every mode -- `divide` by zero and the minimum by -1, both reported before x64 could raise `#DE` for them, and `shift` by a count past the width -- with a signed operand printed signed (D196, link/trap_arithmetic), `enum`: section 4's `Kind(x)` cast exists now and traps on a value naming no member (D197, link/trap_enum, check/enum_cast_width), `narrow` for an integer source: a cast whose value does not fit by width or by sign traps, and section 4's meant truncation `T.trunc(x)` exists and never does (D198, link/trap_narrow, check/trunc_float_argument), `narrow` for a float source -- NaN and a value past the target's range -- `tag`: a payload read or written under another member's tag (D200, link/trap_tag), `null`: every dereference of a pointer value -- `*p` and `p.field` -- read or written, refused for nil (D201, link/trap_null), and `overflow`: `+ - *` and unary `-` on every width, an unsigned 64-bit `*` through `mul`'s high half (D202, link/trap_overflow); `@nocheck { }` leaves the debug-only rows out of a block and the release rows in (D203, link/nocheck); `emit-executable --release` is the release build: every debug-only row left out, `+ - *` wrapping, casts truncating, shifts masked and a float outside its target saturating, NaN to 0 (D204, link/release_build, a fifth smaller). A trap ends with its backtrace: one `  at module.function` line per frame, walked over the rbp chain and named from a symbol table the driver appends after the code, which the artifact path reproduces byte for byte (D206, link/trap_backtrace), each frame with the file and line its call is at, from the line table (D209, D212), and `align`: `simd.load_aligned`/`store_aligned` at an address that is not a multiple of the vector's width, checked at the call site in debug and left out in release (D210, link/trap_align). The test root's channel is the exit status under one process per test; the control handle is not built (D790).

### C032 — Checked optimized builds and unsafe boundaries (M2.5-core H03)

A release build keeps `bounds`, `null`, `tag` and `align` (D355, `m25-h03-checked-release.md`); `@nocheck` is the explicit unchecked operation in every mode and `--unchecked` the whole-image one; the manifest lists every `@unsafe` function and `@nocheck` block and the check policy; a fixture traps in release on all three memory rows; the first bounds proof (`while i < x.len`, D356) its guard form (`if i < x.len`, D377), its conjunct form (the leftmost `i < x.len` of an `&&`, D378) its early-exit form (`if i >= x.len { ret }` proving the rest of the block, D380) the width proof (a `u8` widened, a literal mask or offset into an array of known length, D384) the slack form (`while at + K <= x.len` proving `x[at + j]`, D385) its early-exit form (`if at + K > x.len { ret }`, D387) and the equal-length form (`if a.len != b.len { ret }` proving the other slice, D390; 544 checks elided in the compiler's own build) with their eliminated and retained fixtures and a `--stats` count, which also found and closed the inlined bodies' lost checks. the second-local form (`let n = x.len` then `while i < n`, D452) with its eliminated and retained fixtures; the field base (`while i < s.items.len` proving `s.items[i]` through a local struct, or through a pointer when the body calls nothing, D462; fixture 76 -> 80, the compiler's own build 552 -> 576) with its eliminated fixtures and a retained one whose call empties the slice. An invalid `undef` cannot be made (D475): `= undef` of a type that admits only its members -- `bool`, an enum, a tagged union, a struct or array holding one -- is refused as E-SAFETY-0017 at compile time, so the `invalid` check release does not keep is never owed for it. A named constant is a literal to the proofs (D527): `at + LIMIT < len` elides the check `at + 3usize < len` elided, bare or through a `use` qualifier, where a constant had been no bound -- found by the metamorphic turn over the compiler, whose image grew by the retained checks when its literals were hoisted, and byte-identical since, which both suites hold; and a field spelled like a local is not a write to the local in the proofs' scans (D528), which the renamed-locals turn found keeping a check. The `invalid` representation check reaches every direct `mem.bitcast` to `bool`, an enum or a tagged union in debug and release (D548, D554), and the fixture proves `--unchecked` removes it. Definite initialization of the references an `undef` value holds (D918): `= undef` of a type holding a slice, a pointer, a function value or a `str` at any depth is E-SAFETY-0021 unless every reference-holding field is written -- or the whole value assigned -- before the value is read, scanned from the declaration to the end of the enclosing block, with `&x` not a read, only a write at the declaration's own depth counted, and more than 32 reference fields refused rather than tracked; `accept/safety_undef_written.e` collects the four written forms and `reject/safety_undef_reference.e` reads a slice field that was never written and `reject/safety_undef_branch.e` one written only inside an `if`. A pointer cast keeps a representation (D919): `mem.cast[*P]` to a `P` that admits only its members is E-SAFETY-0022 unless its source points to `P` or `void`, it is a placement whose next mention writes the whole value, or it stands in `@nocheck`; the library's fifteen field-by-field placements now write the whole state first and `e.ui.widget`'s typed state lookup is an `@nocheck` block naming its obligation; `accept/safety_cast_representation.e`, `reject/safety_cast_representation.e` and `reject/safety_cast_placement.e`. Bytes from across the C ABI (D920): an `extern`'s result, the pointee of its `*T` parameter, and a `@cc` callback's parameters and pointees of such a type are E-SAFETY-0023, after section 5's table; `accept/safety_foreign_representation.e`, `reject/safety_foreign_representation.e`, `reject/safety_foreign_callback.e`. An untagged `union` may not hold a field of such a type beside another (D921, E-SAFETY-0024, `reject/safety_union_representation.e`), checked once every aggregate's fields are known, and at every generic instance a body asks for, cached or new (D924, `reject/safety_union_generic.e`). The load and store audit is `m25-h03-checked-release.md` section 6 (D925); writing it found `@packed` and `@align(N)` accepted and ignored, and both now lay out as section 4 says, with `@packed` refused over an `Atomic[T]` (`link/layout_packed`, `reject/layout_attribute.e`). The trap's text and stub are shared by the program (D927): each distinct path and message is a data function the link folds, each site a `mov` and a call to a stub that moves its operands, the jump over it the short form -- the checked compiler is 8,330,240 bytes against 7,963,136 unchecked, +4.6% inside the +5% budget, and its cold wall +9.9% on a loaded host and +5.5% on a quiet one, inside +10%. Recorded boundaries rather than gaps: a `*void` the program erased other bytes to (D919), like `@nocheck` and `--unchecked`; the field-base proof across a call, measured as no lever (15 loops of that shape in the compiler against 379 count-bounded ones).

### C033 — Reproducible performance gate (evidence for E2 H25)

Registered workloads, budgets and rendered reports (D338, `m2-baseline.md`); `benchmarks/baseline/gate.py` judges a measurement cell by cell against the budgets and exits 1 on a breach (D366) -- twelve named on the D351 measurement, twenty on the D382 one and the causes found in the phase split (D383: two scans fixed, D355's retained checks named as what stands; D386: a profile of the compiler building itself found a quadratic slot walk, cold -14%; D387/D388: the warm build's byte sinks copy whole through the intrinsic memcpy and the hash reads inline under a proof, cold 603 ms, warm 115; D402: the crew's workers set up in parallel, the body phase halved; D403: two quadratic walks of the register allocator found on a synthetic function of four thousand loops, 2082 -> 74 ms, the compiler's own build unchanged; D411: the warm build profiled, the compiler's own xxHash64 identity a sixth of its CPU, replaced by the CRC32 instruction, warm 130 -> 117 ms by a stopwatch around the process; D428: the runtime no longer touches every small allocation, `os.touch` at the kernel-facing `e.os` sites keeps the property, peak RSS of the compiler's own build 1018 -> 322 MB release, eight-worker check bodies 70 -> 50 ms; D457: the unsafe inventory rides in the artifact, the warm manifest phase 20 -> 4 ms; D459: the link recomputes a function's content hash only where the image folds by it, warm `link from artifacts` 34 -> 27 ms; D460: the reach walk's answer per relocation is the reference's target, no second lookup in the copy and no third by name, `link from artifacts` 27 -> 22 ms, `link` 18 -> 15 ms; D461: a callee's module found once per artifact string, 22 -> 18 ms; the warm build of the compiler is now load 8, link from artifacts 18, symbol table 7, image 7, manifest 4 ms). The deterministic half of the gate is in both suites (D506): `benchmarks/baseline/static.py` builds the fixed sc500k workload in both modes with the stable stage on eight workers and `gate.py` holds the workers' arena high-water (not above) and the image bytes (within five percent) to `results/static-<host>.json`, since neither varies with the machine's load; a breach fails the suite and re-pinning is the decision row. The timed half is paired (D930): `benchmarks/baseline/paired.py` builds a fixed workload with the baseline and the candidate in alternation and judges the median per-run ratio, so host load lands on both; against the `m2-baseline` compiler rebuilt from its tag, the head cold-built sc500k/sc1m 1.35-1.54x (warm 1.10-1.30x, `results/paired-windows-d930.json`); a paired bisect put D355's retained checks at 1.15-1.25x and the rest in the analyses since; single-worker `perf stat` task-clock (stable to 0.5%) is the instrument, and profiles found the artifact writer's quadratic walks (every aggregate per `q.x`, every reference per module), a doubled comment strip, D927's per-site record writes and pointer-indexed lexer and byte-writer loops -- cut with identical outputs, the compiler 7,339 -> 6,900 ms, checked against unchecked +9.7%, against the baseline +32% (was +40%); D931: eight more profile cuts with identical outputs (the verifier's per-instruction copies, the last trap path record kept, the canonical text in one copy, lookup probes by field, a module's use marks made once, lowering's two proof scans one, literal types from the spelling, the call cache keyed by field), 6,924 -> 6,680 ms, +28% against the baseline; D932: whole-instruction copies in the program-wide walks read as fields and D494's protocol lookup from the index, identical outputs, a saving under the host's run-to-run noise (the baseline itself moves 5%); D933: exact instruction counts (cachegrind, 0.06% run to run; software SHA-256 under valgrind left out) found 15.7% of the compiler's instructions in the one 8-byte copy loop every aggregate copy emitted -- copies and clears of a known size are now laid out up to 32 bytes and looped 16 bytes a turn past it, with the canonical text, site columns, trap-record lookups and three proof views -- 109.90 -> 92.50 G instructions, CPU 6,667 -> 5,626 ms against the baseline's 5,118 (+9.9%, inside the cold budget on this instrument), the compiler's image 6.8% smaller; its paired gate on Windows (`results/paired-windows-d933.json`, 8 workers) passed sc500k both modes and sc1m debug and breached sc1m release (cold 1.123, warm 1.219); D934: the warm build takes the canonical hash an artifact this compiler wrote from the same bytes stored (sc1m release warm 330 -> 275 ms against the baseline's 260), `&&`/`||` results promoted to registers, terminators read as five fields, 92.50 -> 91.45 G instructions; a Windows sampling profiler (winprof.py) found the Windows-only user-time excess spread thin; D935: the paired gate passes on both hosts after D934, no breach (cold 1.004-1.097, warm 0.827-1.043; `results/paired-{windows,linux}-d934.json`). D936: the full budget table measured on both hosts (`results/h25-{windows,linux}-d936.json`) -- every deterministic measure of the fixed workloads passes (peak RSS -2.8% to +2.8%, arena -73% to -81%, image -28% to -45%, the Windows sc2m release debt closed), the timed cells decided by the paired runs because the stored times drifted with the host, and the compiler cell read per line of its 40% larger source (cold -1% to -14%, RSS -9% to +1%, release image +2% with its checks); no budget exceeded by a change in cost. D939: H25's edit/revert workflow frozen and paired (`benchmarks/baseline/edit.py`: body, comment and interface edits to the middle module, seven alternating cycles, the H14 reuse oracle every cycle) -- no breach on either host, ratios 0.56-0.99, a body edit rebuilds one module and keeps its importers by their edges, a comment edit rewrites nothing where the baseline rebuilt the module (`results/edit-{windows,linux}-d939.json`). D941: H25's rename workflow frozen with an absolute budget (`benchmarks/baseline/rename.py`: query, plan, apply and check timed on a fresh copy, H17 completeness and the unrelated-diff guard every run, budgets pinned at the median plus a quarter in `results/rename-<host>.json`) -- every guard held on both hosts, sc500k query/plan 2.8 s, apply 1-11 ms, check 1.6 s; move and delete have no planning tool yet. D943: H25's CPU program workflow (`benchmarks/cpu`: sieve, sort, hash, records in the core language; `benchmarks/baseline/cpu.py` pairs the baseline's release against the candidate's `--unchecked` release under the same contract, +10% frozen, and reports the checked release) -- same output everywhere, unchecked 0.63-1.01 of the baseline, checked +0-42% by loop, the data segment 832 B -> 37,940 B because unreached globals are emitted. D946: an image lays out only the globals a relocation of its code names (both linkers, both link paths), the CPU programs' images back within a few hundred bytes of the baseline's (sieve 56,556 -> 18,555 B on Linux). D947: H25's persistent-session workflow (`benchmarks/baseline/session.py` over `query-batch`: 100 context/uses queries with memory samples) -- 47-49 ms a query on sc500k and 96 ms on sc1m against loads of 2.7-9.4 s, zero bytes retained per query, five answers byte for byte a fresh process's, eviction and cancellation not applicable, budgets pinned in `results/session-<host>.json`. D948: H25's context/repair workflow (`benchmarks/baseline/context.py`: context answers' bytes and tiktoken cl100k/o200k tokens at budgets 16 and 64; five frozen defects repaired by the compiler's own fixes, every one verified on both hosts in 2-3 calls). D949: the H25 report (`docs/h25-report.md`): the frozen setup, the instruments, every workflow's result and reproducing command, the budgets in force, noise and exclusions, GPU pending with its M3 owners (C090-C096), H12's evaluation left to E2's claim gate; no budget exceeded by a change in cost on either host, each frozen with its workload and budget and measured on both hosts, GPU marked pending with its M3 owners (H25 requires one before closure), Linux measurements after the baseline, the H25 report

### C035 — Diagnosis, recovery and transactional repair (v1 precursor for T2 H09)

Every two-site E-SAFETY diagnostic carries its other site -- acquisition, move, deferred call, borrow, pointer, reset, mutation, thread start -- as a `related` span with a message saying which (D364), pinned by the reject corpus; stable codes throughout; the parser's nesting bound and error nodes are D341's; a forgotten cleanup carries its `defer <closer>(x)` and an untested acquisition its `if e != ok { ret e }` as `fixes` entries (D381, D382), and a rename is a plan with preconditions (D376); a type mismatch names both types in its message and carries them as `expected` and `actual` fields, pinned by `reject/type_mismatch` (D401). A diagnostic raised in a module that is not the operand names it under its own root (`toolchain-lib`, `project-src`, `project-lib`) by the manifest's rule (D427). a scalar mismatch at a name or a literal carries the conversion as a `maybe` fix over the expression's span (D444). an unknown value name within two edits of a name in scope names it and carries it as a `maybe` fix (D445), a member a module does not export names the module, the member and the nearest export at the member's token (D447), and a field an aggregate does not declare names the type, the field and the nearest field (D448); an unknown type name sits on its token and names the nearest type in scope -- a declared type or a builtin scalar -- as a `maybe` fix (D485; it was a location-free `name resolution failed`); the conversion fix reaches a whole value -- a call, a field read, an index, a group -- wrapped as one (D491; `reject/type_mismatch_call`), an arithmetic expression still offering none. An instance asked for by an instance relates the chain of requests, innermost first, up to three links (D543), where one site was named. `check-file --json` goes on past a failing function to the next and reports every function's first error in one run, the instances after them (D553), the plain output keeping to the first for neper-0 parity, where the first had ended the check; a cascade inside a body is still cut at its first failure. D950: the check goes on past a failing declaration too -- the resolver keeps each declaration's first name failure, the declarations rerun from a fresh checker without each declaration whose signature or type failed, and a use of one (a call, `q.f`, a type, a constant, a global) fails at its own token as `DeclarationFailed`, printed as a `note` whose `parent` is the root cause's error record, every other failure an error of its own (`reject/cascade.e`: four errors, three notes). D954: a syntax failure no longer ends `check-file --json` either -- the recovered tree (D341's error nodes, invalid bytes kept) stays loaded, each failure is reported at its own token, a failure in the tokens recovery skipped to resynchronize is a note under it, the declaration it broke is left out -- its interface, so a use is a note, or its body alone -- and the result carries `unchecked`, the count of declarations not checked, where a result without it is complete (`reject/syntax_recovery.e`: three errors, three notes, `unchecked: 3`); the plain output and the build still stop at the first failure, and nothing recovered is ever compiled

### C042 — Hostile inputs, artifact integrity and aggregate limits (v1 precursor for T2 H24)

Every artifact read is checksum- and layout-validated; hostile source/artifact fuzzing, bounded nesting, atomic publication, whole-build instance and comptime-step budgets, and corrupt-cache rebuilds are pinned by D213, D320, D341, D343, D344, D368, D426, D435, D472-D474. Build manifests are HMAC-SHA-256 authenticated under a random per-user key held outside project caches; unauthenticated or unrecorded artifacts rebuild, and the forge-both regression passes on Windows and Linux (D1020). D1028 corrects the CRC-only binding: the authenticated manifest now records the full SHA-256 of each artifact; CRC-preserving mutations and artifact-plus-manifest mutations rebuild the clean image on Windows and Linux in debug and release, while unchanged caches reuse normally.

### C036 — Declaration-level incremental semantic work (v1 precursor for T2 H14)

Module-level reuse with structured reasons (D363): the build manifest's `incremental` array says per module whether it was kept or rebuilt and why -- stable, edges-hold, edge-changed, source-changed, mode-changed, no-artifact -- asserted by both suites on a warm build and a body edit; a comment-only edit to the compiler rebuilds one module and keeps the rest by their edges; an unchanged import of a changed module is parsed for its declarations alone in a debug build -- header trees, the bodies skipped at the tokens (D392), and in a release build for its declarations and the bodies short enough to be inlining candidates, the oracle's own bound (D421: the edited build's parse 57-62 -> 45-51 ms, resolve 12 -> 6); a kept module's bodies are not checked in either mode (D391); the manifest's `work` and `--stats` count the bodies checked, the modules and the functions lowered -- zero on a warm build over a stable cache, one module and its functions after an edit that changed no interface, asserted by both suites (D405). the manifest's `work` and `--stats` count the declarations the front end held after its declaration pass, which on a warm build over a stable cache is the seeded surface alone -- 28 on the incremental fixture against 403 cold -- pinned by both suites (D446). A body's use of a foreign constant is a value edge (D492): the constant's value is baked into the body, and a warm build after the value changed rebuilds the module as `edge-changed` -- before, only a constant's use in another constant was an edge, and the module folding `if dep.LIMIT > 2` was kept with the old value, a wrong program from a warm build; the `incremental_value` fixture pins it in both modes on both hosts. A layout a body reads is an edge too (D493): every foreign aggregate reachable from the signatures a module references, spelled in its tokens, or held in those aggregates' fields is a signature edge whose hash covers the fields in order, so a reordered record rebuilds the module reading it -- before, the module was kept and read the old offset; `incremental_layout` pins it. A protocol function's absence is an edge (D494): for every such aggregate, the `eq`, `cmp` and `hash` its module does not declare are section 12's negative lookup edges, which nothing had written, so declaring one rebuilds the module whose instance took the supplied rule -- H14's fallback fixture, `incremental_fallback`, was a third wrong program from a warm build before. A declaration deleted from a dependency (D495) fails the warm build as a cold one -- the resolver's diagnostic at the dependent's line, naming the module and the member, exit 1, the previous executable untouched -- where it surfaced as an internal failure; `incremental_deleted` pins it, and the broken-then-repaired and edit-then-revert cases of H14's list were probed and hold. Trivia is apart from the identity (D504): the artifact's source hash leaves every comment's body out, so an edit inside a comment that moves no line keeps the module `stable` and the image is the clean build's, while a line added or removed rebuilds it, since the line tables would be wrong; both suites edit a comment of the incremental fixture in both modes. The identity leaves every line's trailing whitespace out with the comments (D534), so a comment added at a line's end or blanked to spaces keeps the module, and the warm path is held under the turns over the compiler: every comment of every module blanked keeps all thirty-five modules `stable` with the cold image, and one module's literals hoisted or its locals renamed rebuilds that module alone with the cold image, both suites -- a parameter's name being out of the signature identity since D535, where a rename had rebuilt every importer; and the same three edits hold over a cold release build with artifacts (D536), the two modules that inline from the edited one rebuilt by their body edges and the image the cold release build's. The per-module buffers grow to the function (D541): the link's line-row scratch and the writer's code-hash scratch were fixed at sixteen thousand rows and four megabytes, and a function of twenty thousand statements filled the one, twenty-seven thousand the other, both refused as a table full with no cause named; both grow on demand from the worker's arena, the buffer is named in the diagnostic, and both suites build a function of thirty thousand statements. D1028: cache reuse verifies each artifact's full SHA-256 bound by the authenticated manifest; CRC-preserving mutations rebuild on both hosts in both modes, without advancing declaration-level reuse. The Interface reads back whole (D1325): every record's typed payload -- a function's borrow source, no-escape positions, comptime parameters, parameters and returns, an aggregate's fields and backing, an alias's type, a constant's type and value, an error's value -- is walked by `em.interface_payload_end`, and a kept artifact whose Interface does not end where its lengths say is rebuilt as invalid-artifact; the compiler's own 37 modules warm-build stable in both modes on both hosts through it. Not yet: declarations from the Interface instead of a lexed tree (the payload is read, not yet decoded into the checker's records), reuse inside a rebuilt module Format 15 (D1510): function and aggregate Interface records carry an attribute tail -- intrinsic/variadic/gpu with the workgroup size, the import or contract strings and each parameter's `own`; resource/reorder/packed, `@align` and the cleanup name -- walked by `interface_payload_end`, the strings interned before the Strings section is written; the incremental fixture and the compiler's own warm build keep every module on both hosts and the self-host fixed point holds. Declarations from the Interface (D1511): in a debug hot build a stable import in the changed modules' closure whose Interface is decodable (no generics, instances, globals, or non-integer constants) declares from it -- resolver symbols in the resolve pass, checker records in the declaration pass -- and is never lexed; a body edit to the compiler's main.e decodes 34 of 37 modules and check.e 11, each warm image byte-identical to a clean build on both hosts. Not yet: generic templates, globals and string/float constants from the Interface, release builds (the oracle reads header-tree bodies), reuse inside a rebuilt module. Globals from the Interface (D1514, format 16): the Globals section carries each global's type after its records, so a stable import with globals -- e.os on both hosts -- declares from its artifact; a body edit to the compiler's main.e decodes 35 of 37 modules (e.mem stays lexed for its generics), `--stats` counts them as `modules decoded`, and each warm image is byte-identical to a clean build on Windows and Linux, as is a program reading a foreign scalar and struct-array global. Not yet: generic templates and string/float constants from the Interface, release builds, reuse inside a rebuilt module. Reuse inside a rebuilt module (D1515, format 17): an Emission section records each function's emission identity -- its canonical NIR with the lines, columns, paths, inline origins and import bindings selection reads -- and a source-changed module's previous artifact, verified against the manifest, gives each function whose identity holds its bytes, relocations and line rows in place of selection, its trap stubs asked for again so a renumbered `trap.N` is named as selection names it; a body edit to the compiler's main.e reuses 298 of 301 functions (selection 33 -> 4 ms) and a trapping function inserted first reuses 301 of 302 under renumbered stubs, each image byte-identical to a clean build on Windows and Linux, `--stats` counting `functions reused`. Constants are integer and bool only, so no string or float constant gap exists. Not yet: generic templates from the Interface, release builds (Interface decode and emission reuse), and skipping the lowering of a reused function. Emission reuse in release and for edge-changed modules (D1516): a module rebuilt because an edge did not hold keeps its verified artifact aside too, reuse runs in release, and an inline origin enters the identity relative to the function's least; a release body edit to lex.column_of rebuilds lex and, by their body edges, main and tool, reusing 554 of 561 functions (471 before origins were relative), each image byte-identical to a clean release build on Windows and Linux. Not yet: generic templates from the Interface, declarations from the Interface in a release build (the oracle reads header-tree bodies), and skipping the lowering of a reused function. Closed (D1517): the precursor's two remaining lines -- declarations from the Interface (D1511, D1514) and reuse inside a rebuilt module (D1515, D1516) -- have landed; a module that declares generic templates keeps its header tree because each instance is checked from the template's body, and a release build keeps header trees for the oracle's inline candidates (D421); per-function type-check and lowering queries are T2 H14's.

### C043 — Immutable snapshots and correct cache identity (v1 precursor for T2 H15)

Artifacts carry format version, target triple, build mode, source hash and interface/body hashes, and a mismatch is a miss (D205-D214); published by one atomic replace (D343); `--unchecked` is its own mode byte, so a warm build over the other policy's artifacts rebuilds every module as `mode-changed` and is the clean image, both suites both ways (D369); the writing compiler's own hash rides in every artifact and a warm build by another compiler executable rebuilds every module as `compiler-changed`, both suites (D398); a context answer's subject names the program's snapshot -- every module's source hash folded in graph order -- and both suites see it change with an edit (D407). `--inline-cap` rides in the identity's top byte, so a warm build under another cap rebuilds every module as `options-changed`, both suites (D431). `--overlay PATH=FILE` (D502) builds with a module's text from another file -- an editor's buffer -- the overlay's hash the input's and the artifact's identity, the file untouched; both suites build the value fixture over its edit as an overlay and read the file again without it. The key is a candidate, not a proof (D507): every hit on the 64-bit source key is verified by the bytes' SHA-256 when they are the artifact's and by the canonical text's -- comments left out -- when they are not, the artifact carrying both, and `--fault-collision` injects a hit on every key so both suites see a body edit under it rebuilt; the manifest's input digest is the bytes' own for a kept module too, which D504 had left as the artifact's. The overlays reach `check-file` and every query (D524): a check and a `uses-file` over a buffer of the root answer for the buffer with the file untouched, both suites; a plan over overlays hashes the buffers in its preconditions. Not yet: CPU features in the identity, the transaction boundary CPU features in the identity (D765, pinned by D1518): a warm build under `--cpu x64-v3` over x64-v1 artifacts rebuilds every module as `options-changed` and is the clean v3 image, and the plain warm build after it is the clean v1 image, debug and release on Windows and Linux; both suites assert it. Not yet: the transaction boundary. The transaction boundary (D1519): `apply-plan` takes `<root>/.neper/transaction.lock` by one exclusive create, hashes every precondition again under it, keeps each changed file's original and a journal of both digests, and re-hashes each file just before its atomic replace, putting back what it wrote when a writer that does not take the lock intervened; a crash leaves the lock and journal, the next apply refuses, and `--recover` restores files holding the new digest, leaves those holding the original and refuses to overwrite one edited since; `--fault-apply` and `--fault-edit` drive a held lock, a crash and recovery, and an intervening edit on a two-file plan, pinned by both suites on Windows and Linux. Closed: C043's two remaining lines have landed.

### C044 — Compilation policy and generated-code performance (precursor for T2/E2 H20)

Three policies, each a build identity and named in the manifest: debug, release with the memory checks retained, release `--unchecked` (D355, D369); the forty-instruction cap re-evaluated on the 500k-line workload and retained, `--inline-cap N` and `--explain` giving every inlining decision its reason (D346), and under `--json` as `inline` records of the build stream, gathered per worker and written in worker order, pinned per host (D408); the bounds proof and the `--stats` rows for elided checks and by-value copies (D356); measured budgets and the gate (D338, D366). `--stats` reports the register pressure of a build -- values allocated, values spilled, functions spilling -- summed over the crew (D450). Not yet: allocation counts, lazy `.em` section access, serialized alias facts, the cap against the GP workloads, any vectorizer (reported unavailable), the vector register class whose ABI is section 5's xmm convention for `Vec`/`Mask` (D786) Allocation counts and the unavailable vectorizer (D1520): `--stats` and the `stats` record count the arena allocation sites of the functions lowered (`mem.alloc`'s runtime calls, an inlined copy where it lands), and `--explain` ends with a `transformation` record naming `vectorize` as `unavailable`, in the schema and the `explain_instances` conformance streams of both hosts. Not yet: lazy `.em` section access, serialized alias facts, the cap against the GP workloads, the vector register class whose ABI is section 5's xmm convention for `Vec`/`Mask` (D786). The cap against the workloads (D1521): `benchmarks/baseline/inline_cap.py` builds GP-01 and the four M2 CPU programs under caps 0-160 on both hosts; the programs do not respond beyond noise, GP-01's fixed job is fastest at 40 on Linux and flat on Windows while its image grows 7.6 % at 40 and a third more past it, every capped compiler reaches its fixed point; forty is retained with a versioned code-size budget, results in `benchmarks/baseline/results/inline-cap-*-d1521.json`. Not yet: lazy `.em` section access, serialized alias facts, the vector register class whose ABI is section 5's xmm convention for `Vec`/`Mask` (D786). Serialized alias facts (D1522): a function's borrow source and no-escape parameters ride its Interface record (D1325, D1510) and come back with it when a stable import is declared from its artifact (D1511); a warm debug build that decodes `dep` rejects a view used after its `@borrows` source changed (E-SAFETY-0014) and accepts a `@noescape` parameter forwarded to `dep`'s no-escape callee, as the clean build does, on Windows and Linux, while a decode that drops the facts accepts the stale view and rejects the forward. Not yet: lazy `.em` section access, the vector register class whose ABI is section 5's xmm convention for `Vec`/`Mask` (D786). Lazy `.em` access (D1523): the whole artifact is the unit of trust (CRC and the manifest's SHA-256), read and verified once; within it every consumer reaches its sections through the directory and parses no other -- the hot load Imports/Interface/Deps, the decode Interface/Strings/Globals, reuse Code/Lines/Emission, the link Code/Lines/Globals; a fully warm build of the compiler reads and verifies its 37 artifacts (9.9 MB) and every source in 17-18 ms on Windows, so section-lazy reading, which would give up the whole-file digest, is not useful at this scale. Not yet: the vector register class whose ABI is section 5's xmm convention for `Vec`/`Mask` (D786). Closed (D1524): the vector register class and section 5's xmm/ymm ABI for `Vec`/`Mask` are later delivery under H20's own rule -- advanced vector optimizers need a workload-backed decision and a named milestone; GP-09, the workload that would measure it, does not exist, the convention alone is the copy D786 makes today, and the roadmap's M4 optimiser-depth line now names it; D786's by-storage deviation stands, unobservable to a program.

### C045 — Bounded, versioned harness transport (v1 precursor for T2 H18)

One versioned JSONL stream with a header, a closed record set and `result.data` as the extension map, validated against `docs/schemas/neper-v1.schema.json` by the suites (D227-D300); two-site diagnostics carry `related` (D364); `run --json` is bounded -- `--capture N` bytes per stream in the record, whole counts and `captured_complete` in the result, the files beside the executable holding the rest (D370); a build past `--deadline` ends with one diagnostic and exit 3 (D399); a context page reports its serialized `bytes` and takes a byte budget (D400), and its cursor is bound to the program's `snapshot` on the subject record (D407). a `fix` carries the plans' preconditions, the identity and SHA-256 of the source its edits are offsets into (D432). under `--json --time` every phase of a build is a `progress` record of the stream with its milliseconds, the arena and the elapsed time (D454). Typed name facts (D514): an unknown value name, an unknown type and a module without the member named carry `symbol`, `owner` and `near` as fields beside the message, as a mismatch carries `expected` and `actual` (D401), pinned by the near fixtures and the project goldens. Every E-SAFETY diagnostic carries `symbol`, the resource, view or type its rule is about (D545), pinned by the forty-nine safety and region fixtures. A program that does not load answers as a stream from every query (D521): the header is held until the first record, so the loader's parse or import diagnostic comes under it and a result of exit 1 follows, where the diagnostic had been text on stderr, and `index-file` over a file that does not parse had a stream with no header; pinned over `query_syntax` for three queries and the index on both hosts; `dis-file` and `build-manifest-file` answer the same way (D522), the manifest command under a `manifest` header in place of its object, and a batch over a program that does not check or load is one stream under a `query-batch` header (D523). Not yet: streamed capture chunks, sequence IDs Sequence IDs (D561): every live `progress` record carries a contiguous one-based `sequence` and the `result` stays last. Chunked capture (D1525): `run --json --chunked` sends each stream's captured prefix as `output` records of at most 4,096 bytes -- a per-stream `sequence`, `offset`, `bytes`, and `data` as UTF-8 text or base64 for binary, a split character moved whole to the next chunk -- and a closing record per stream with `total_bytes`, `truncated` and the `file` holding the rest; the schema carries the record, the `run_chunked` golden is pinned by both suites, and reassembly, binary and truncation cases pass on Windows and Linux. Closed: C045's two remaining lines have landed.

### C047 — Bounded tooling lifetimes and responsiveness (v1 precursor for T2 H16)

One process per query over one snapshot, reclaimed at exit -- measured and kept (D372); `--stats` accounts arena high-water, peak resident set, per-phase time and worker bytes (D311, D338); limits are named codes, not crashes (D344); the baseline's memory budgets and the gate (D366); `--deadline MS` cancels a build with one diagnostic, exit 3 and no published image or manifest (D399), with checkpoints between modules (D422), functions (D441, D442), interpreter steps (D496) and statements during checking/lowering (D540). `query-batch` reuses one check while reclaiming each request arena (D409, D410). Its memory report now separates live and reserved bytes, checked snapshot, session baseline and peak temporary request allocation (D558); both suites run ten thousand context queries against one snapshot, count every completion and prove the nonzero request peak is reclaimed exactly to the fixed session baseline (D559). Not yet: pinned snapshots and eviction, edit/revert cycling, and a backpressure scheduler (the worker default is eight, measured at four on the largest workload). Pinned snapshots, eviction and edit/revert cycling (D1526): `query-batch` holds up to eight snapshots in arenas of their own -- `edit`/`revert` move to the snapshot of the edited set (a hit compares the texts, a miss checks into a free slot or evicts the least recently used unpinned one), `pin`/`unpin`, `use KEY` refused as stale once evicted, an edit that does not check making no snapshot; `scripts/check_batch_snapshots.py`, run by both suites, holds 10,000 edit/query/revert cycles under a budget of two to one miss and 19,999 hits with live memory back at the session baseline, and eviction, stale keys, failed checks and pins, on Windows and Linux. Not yet: a backpressure scheduler (the worker default is eight, measured at four on the largest workload). A backpressure scheduler (D1527): `--memory-budget SIZE` admits one lowering worker per 256 MB, each held to an equal share, and a worker that runs dry hands its modules to the generous worker (D325) -- delayed, never refused, the same image -- while a budget under one worker's setup is refused by name; two faults in the dry path it exposed are fixed (a sweep-replaced worker's modules were lowered by no one, and an arena exhausted in selection ended the build); the compiler's build from no budget to 300 MB gives 8 to 1 workers and 1,834 to 346 MB reached with every image the default's on Windows and Linux, `--stats` reports workers admitted and the budget, both suites pin the budget and its refusal; the default of eight stays, as D339 measured. Closed: C047's three remaining lines have landed.

### C048 — Generated-source provenance and editability (v1 precursor for T2 H19)

A `<file>.e.map.json` beside a generated file maps diagnostics back to the original span with the generated one related; a stale or malformed map is E-TOOL-0001 with no artifact (D264, D300); version 2 names the generator and hashes its input, so a changed input is stale too, and a mapping's `edit` says whether the generated span may be edited or the original is the target (D373); no fix is ever offered on an original span; the compiler runs no generator. a generated file whose hash is not the map's while the generator's input is unchanged is a hand edit, `E-TOOL-0002`, told from a stale map, pinned by the corpus (D418); a generator's combined inputs (`generator.inputs`) are each checked and the first changed one named, and one input's line that became two declarations maps each to the one original span, pinned by the corpus (D464); a nested map -- the original itself generated under a map of its own -- is followed one level to the root original with the intermediate related, and a stale nested map is stated rather than followed, pinned by the corpus (D465); a failure inside an instance's body relates the site that first requested that instance, named with its arguments, in whichever module asked, pinned by the corpus (D466); the operand's map is an input of the build manifest with its hash, so a map-only change is visible there and nowhere in the code's identity, pinned per host (D467). The chain is bounded at eight nested levels (D499, D564), each level's mappings in its own eight slots and every intermediate related root-nearest first; `nested_deep` pins four levels past the former three-level ceiling. Provenance through inlining in a trap's backtrace (D519): a frame whose line lies in another module -- a body inlined there in release -- names that module's function holding the line as `inlined_from`, found from the checker's source ranges, where the runtime's frame could only name the function whose code holds the site; both suites pin it over `run_trap_module` in release, and the operand's own frames are under the project's identity. `dis-file --json --release` lists the release image, and each record's `inlined` names the runs of the function's code that are copies of another function's body, from the line table as backtrace frames are named (D542); a copied instruction also retains its bounded origin chain, so a run copied through another body carries `through` from the innermost intermediate outward while direct copies stay unchanged (D565). Not yet: provenance through inlining in diagnostics Provenance through inlining in diagnostics (D1528): a selection failure on a copied instruction is reported at the innermost body's source under its own module -- where it had taken the selected function's path with the copy's offsets -- naming the function it was inlined into and the bodies it came through, as `dis` and backtraces do; `--fault-select-inlined DEPTH` reproduces it and the corpus's `select_inlined` golden, the same on both hosts, is pinned by both suites. Closed: C048's remaining line has landed.

### C050 — Learnability and executable API documentation (v1 precursor for T2 H11)

The index carries every symbol's signature, spans, attributes and documentation (D232), `context-file` its resource and unsafe facts (D361) and, from the signature, the caller's contract -- allocation from an arena parameter, borrow or mutation per pointer parameter as the view rule reads it, fallible or partial results, a thread started in the body (D396) -- per function with `--symbol`, per module as a catalogue with `--module` (D397); the language card is generated and stamped (D374) and its examples are programs both suites check with the compiler -- a ```neper fence checks clean, a ```neper reject E-CODE fence is refused with that code, the near miss beside the edit shapes (D404). the card's diagnostic codes are marked verified, present or planned from the goldens, the suites and the source (D440), and its displayed grammar productions are explicitly `present` (D567). Concrete functions in a module catalogue are `supported-on-target`, derived from the checked source and requested concrete target rather than a second registry (D568); the first executable test reaching one promotes it to `verified` and is named as evidence (D570). Planned-only modules and APIs answer `unavailable` instead of appearing callable (D571-D572). Generic signatures retain their comptime parameters and dependent types (D573), and catalogues include generic templates: an uninstantiated template is `present`, while a tested concrete instance promotes its template to `verified` (D574). Both suites resolve all twenty-eight source-delivered surfaces and compare their exact declarations with the catalogue (D576); the sixteen compiler-origin functions in `e.atomic`, `e.io` and `e.str` expose exact indexed template signatures to the same gate (D577). `e.proc.run` now delivers independent capture limits and explicit exit, cancellation, deadline and output-limit outcomes over the host process-group/job boundary (D578), with inherited-writer drain closure still pending. The same semantic gate requires every catalogue declaration from all thirteen partial M1/M2 source modules and compares exact signatures for twelve; `e.simd` retains SL01's explicit dependent-metavariable spelling exception (D579). Not yet: the remaining SL05 drain edge, variant-composed spec surfaces and the deferred-library fixture manifest The SL05 drain edge closed with D580 (bounded final drain past a retained writer) and D581 (the complete grace for a descendant ignoring termination). Variant-composed spec surfaces (D1529): the module-surface gate checks `e.mem`, `e.meta` and `e.os` per target variant, with exact compiler signatures, in both suites; it found seven `e.os` catalogue drifts (window mode, monitor work area, accessibility node, `buffer` spellings), now reconciled. The deferred-library fixture manifest (D1529): `docs/library-fixtures.json` records every partial module's pending declarations and the executable fixtures that use it, generated and checked by `scripts/library_fixtures.py` in both suites. Closed: C050's three remaining lines have landed.

### C051 — Tokenizer grounding (v1 precursor for T2 H26)

`benchmarks/tokens/profile.py` writes a grammar-versioned vocabulary table per public tokenizer (cl100k_base, o200k_base): the model-token cost of every grammar terminal and the frequent composite forms, and `--measure` reproduces the corpus numbers from it -- 1.27 model tokens per lexical token on the conformance corpus, keywords one token each, fixed-width type names two, a typed literal three (D375); the card carries the table, rendered from the profiles and refused when a profile is of another grammar revision (D429). Not yet: families without a public tokenizer, the profile in the build manifest The profile in the build manifest (D1551): every manifest carries `tokenizer_profiles` -- each committed profile's encoding, grammar revision and canonical-JSON SHA-256 -- written by `manifest_profiles` for the build and `manifest-em`, generated and held by `benchmarks/tokens/manifest_profiles.py --check`, required by the schema; the eight manifest goldens move by that member alone (Windows byte-equal; Linux pending a run). Families without a public tokenizer get no invented profile (D375), so nothing remains. Closed.

### C052 — Structured edits (v1 precursor for T2 H29)

`plan-rename-file --json --symbol m.f --to g` emits a plan -- `precondition` (file hashes), `edit` (`rename-symbol`, site, span, replacement), `postcondition` -- and applies nothing; `scripts/apply_plan.py` applies all or none against the hashes; both suites round-trip it (D376); `add-parameter-and-migrate` is `plan-add-parameter-file`, applied and re-checked by both suites, refused where a value or a protocol holds the signature (D406); `replace-expression` is `plan-replace-expression-file`, the span checked to be one expression node, applied and re-checked by both suites (D414); `change-signature` is `plan-change-signature-file`, the parameters reordered or removed by index and every call re-rendered from its own text, applied and re-checked by both suites (D415) -- the four shapes `m25-h29-structured-edits.md` fixed all exist. every plan's result names the program's `snapshot` (D436). `--arguments FILE` gives the added parameter an argument per call by the call's line and column with a `*` default, refused for a call it leaves out (D455). `neper apply-plan` (D481) applies a plan in the compiler -- every precondition's hash or nothing, highest offset first, `.tmp` and one replace, E-TOOL-0003 for a plan that cannot be applied as it stands -- and both suites apply every corpus plan with it; the Python applier is retired. A type's rename is a plan too (D515), from the index's references, where a subject naming a type was refused; the plans over the compiler itself -- a function at five hundred and forty sites, a type at four hundred -- apply and build the stable stage in both suites (D537), and so do the signature plans over the same function, its parameters reordered at every call and a parameter added with an argument at every call (D538). A stale plan's refusal names the file whose precondition no longer holds, in the message and as `symbol` (D547). Not yet: a plan over more than one program A plan over more than one program (D1552): `apply-plan PLAN --root DIR --also PLAN2 --root DIR2 ...` applies up to eight programs' plans in one D1519 transaction -- a shared file read once and held to both hashes, an edit both make made once, other overlaps and failed plans refusing all -- checked in both suites (two programs renamed together, a doubled plan merged, a stale second program refusing both); stage 2 equals stage 3 on both hosts. Closed.

### C053 — Bounded semantic context for harnesses (v1 precursor for T2 H08)

`context-file --json --symbol module.name [--budget N] [--cursor N]` (D361): a subject record bound to the source SHA-256, target and check policy, then facts with provenance -- signature, `own` parameters, the rules that held or the unsafe boundary, every resolved call, dispatch, instantiation and discard with its span -- under a record budget with omission counts, a completeness flag and a deterministic cursor; pinned per host; the caller's contract from the signature -- allocation, borrow, mutation, errors, threads (D396) -- and the same per module as a catalogue (D397); `--bytes N` bounds a page in serialized bytes and the result reports `bytes` (D400); a type subject answers with its fields or members, its layout on the target and what the rules make of a value -- resource, borrow or copy (D419). a constant or a global is a subject too: its declaration, its settled value or its initialisation, and for a global that every thread shares it (D437). a function's page names every module its module imports with the interface hash the manifest records (D498), so an answer can be held against the interfaces it rests on. A broken source answers as a stream (D520): every query over a program that does not check emits its header, the diagnostic and a result of exit 1 on stdout, where `context-file`, `uses-file` and the plans had written text to stderr and nothing a harness could read; pinned over `query_broken` for three commands on both hosts. Borrow origins inside a body are facts (D1553): the region a value was taken in (the innermost live mark of its arena) and the storage a thread start lends, each a compiler-proved `borrow` record at the binding; the context, contract, nested-instance and batch goldens gain them on both hosts. Not yet: partial answers over the functions that do check Partial answers (D1554): `context-file --symbol` over a program that does not check checks on past the failing body (`check.run_partial`, the first diagnostic kept), and a function that did check answers with its page -- the diagnostic after the subject, the facts, a result of exit 1 marked `partial` -- pinned by `context_partial` on both hosts; a failing or non-function subject keeps D520's stream. Closed.

### C057 — Scoped concurrency and shared-state contracts (M2.5-core H04)

The design (`m25-h04-concurrency.md`, D365): the join obligation is H01's; a thread over this frame's storage cannot be detached, handed on, returned or stored past it (D357, E-SAFETY-0015); what a thread was given is lent to it until the join, read or written by nobody but through an address (D365, E-SAFETY-0016); a lock held as a value is a `sync.Guard` resource, released on every exit by H01's rule (D379); a pointer local bound from `&x` is followed, so a read or store through it while `x` is lent is refused (D393), and a thread start through that pointer alias lends the underlying frame storage too (D674); a thread context addressed through a local slice lends its known backing storage (D679), and one addressed through a tracked aggregate pointer field lends the pointed-to local rather than the carrier (D686), including the aggregate's second and later independently tracked pointer fields (D695, D700), recursively nested field paths (D705), comptime-indexed fixed-array pointer elements (D710), and every possible owner of a runtime-indexed element (D714); a read or a write lock held as a value is a `sync.ReadGuard` or `sync.WriteGuard`, each owed to its own release (D433); a `thread.Group` starts one thread per context, joins what it started when a start fails, and is one resource owed to `join_all` (D434); the compiler's crews and every fixture pass. The protected data as a view of the guard (D1555): `sync.data_guard`/`data_of`/`data_release`, the data reached through an `@borrows("g")` accessor (a `mem.cast` now keeps a proved provenance), consuming a resource ends every view of it (one carried in another local included), and a view returned past a deferred release is refused; pinned by `accept/dataguard_scoped`, three `reject/safety_dataguard_*` cases and `link/sync_dataguard` on both hosts, 601 sources swept with none newly refused. Aliases through externally sourced slices and globals (D1556): a lent context lends every slice local it holds at any field depth (a parameter's or a call's slice, backing unknown), and a module-scope variable the thread's entry function names -- or a same-module callee, four deep -- is refused in the parent until the join (atomic and lock types, and access under a guard, exempt); pinned by `reject/safety_thread_param_slice`, `reject/safety_thread_global` and `accept/thread_global_joined` on both hosts, 602 sources swept with none newly refused. Not yet: a perturbation fixture A perturbation fixture (D1557): `thread.perturb`/`perturb_point` spin a seeded 0..N steps at each synchronising step, and `link/thread_perturb` runs four workers over a data guard and an atomic under six seeds with the same 12,000 each time on both hosts, in both suites; an unguarded copy loses updates and fails. Closed.

### C058 — Regions, borrows and container views (M2.5-core H02)

The lexical subset (D354, `m25-h02-regions.md`): a mark is followed, values allocated after it dangle at the reset, views of a container dangle at its mutation, both refused at the use (E-SAFETY-0013/0014) with the join and loop rules of H01; no false positive across the compiler, library and fixtures; a pointer local bound from `&x` is recorded as an alias of `x`, and the lending rule (D393), the region rule and the view rule (D394) follow it, `.len` excepted, a slice bound from a place of `x` is the same alias (D395), and a struct local given `&x` in a field -- by its literal or by a store -- aliases `x` through that field alone (D413); an assignment records the same alias a binding does and ends the one the local held, and a slice rebound ends the aliases other slices held of its old storage (D416). A view's end is a fact of the context page (D501): at the `mem.reset` of its region or the call given its container by pointer, the local views nothing from there, which is what the rules refuse a read after; `context_moves.ends` pins it per host. Mutable container calls follow direct and copied local pointer aliases (D671-D672); region matching canonicalizes direct, addressed and aliased arena locals (D673), including copied pointer parameters (D676); copied marks retain the original checkpoint (D677); accessors through pointer aliases produce tracked views (D678); and deferred reset takes effect at scope exit, allowing earlier uses while refusing direct, derived-slice and derived-pointer returns across the reset (D675, D680-D681). Pointer aliases extracted from an aggregate, the aggregate carrier itself, and direct aggregate copies or assignments retain that reset boundary and are E-SAFETY-0018 (D682-D685). Addressed accessors and mutations through tracked aggregate pointer fields use the pointed-to container (D687-D688); nested aggregate literals and field assignments retain their enclosed region pointer (D689-D690). Two independent top-level pointer fields retain field-specific targets through use, carrier return, aggregate copy and separate field assignment (D691-D694). The sparse form retains third and later top-level aliases through use, carrier return, aggregate copy, separate field assignment and thread contexts without growing every `Resource` (D696-D700). Recursive field paths retain every nested owner through use, carrier return, aggregate copy, nested assignment and thread context (D701-D705). Comptime-indexed fixed-array paths retain each element owner through use, carrier return, lexical copy, separate assignment and thread context (D706-D710). Runtime indices conservatively use every matching element owner for reads, deferred returns, mutable-call invalidation and thread lending, including below nested aggregate fields (D711-D715). Explicit `@borrows` summaries are declaration-checked, proved over scalar and aggregate returns, applied to the exact caller argument and carried through generic specialization (D731-D735, E-SAFETY-0019). Explicit `@noescape` inputs are declaration-checked; direct and aggregate returns, global retention, unannotated/extern calls, indirect callbacks and thread handoff are rejected, while exact forwarding to another checked no-escape parameter is accepted (D736-D739, E-SAFETY-0020). Nonempty multi-input sets receive the same return, global and forwarding proof for every named origin (D741-D744); artifact-format-14 interfaces and canonical signatures serialize the counted ordered set through generic specialization (D745). Raw-cast provenance (D1558): `mem.cast[*T](p)` of a tracked pointer keeps `p`'s region or view as a binding (and, since D1555, as a `@borrows` return), so a cast out of a region value used after its reset is E-SAFETY-0013; `reject/regions_cast` and `accept/regions_cast_valid` on both hosts, 604 sources swept with none changed. Build-then-freeze containers (D1559): `list.Builder[T]` is a generic resource grown by `build_push` and consumed by `freeze` into a read-only slice (or by `builder_drop`), so growing it after the freeze is E-SAFETY-0001 and forgetting it E-SAFETY-0002; `link/list_freeze`, `reject/regions_freeze_grow` and `reject/regions_freeze_forgotten` on both hosts. Generation-tagged handles (D1560): `slot_map` keys carry the issuing map's owner beside slot and generation (slots retire rather than wrap), so a key answers only in its own map and never after `remove`, `clear` or an arena reset that reuses the storage -- three compares per access; `link/slot_map_owner` on both hosts. Non-lexical liveness (D1561): a pinned local may move or close once every known holder of the pointer is named nowhere from the move to the function's end (a move through the pointer itself, and any move in a loop, stay pinned); `accept/pins_last_use` on both hosts, 157 reject answers unchanged, 607 accept sources with only the new case newly accepted. Not yet: arbitrary heap/container retention Heap/container retention (D1562): a call given `&c` by mutable pointer and a region value or view for an `own` parameter leaves `c` in that region or viewing that container, so a use of `c` after the reset or change is refused (a borrowed argument is not kept); `reject/regions_container_retain` and `accept/regions_container_valid` on both hosts, reject answers and accept sources unchanged by the sweeps. Closed.

### C059 — Resource ownership and cleanup (M2.5-core H01)

The seeded and declared resources are affine and obligated, `own` transfers, every exit audits, `defer` reserves, failed acquisition narrows, branches/loops join, borrows cannot be consumed, copies and representation access are refused, and `os.dup` creates the only second handle identity (D345-D353). Pointer-mediated consumption resolves to the pinned owner (D610); concrete generic containment is classified after substitution (D611); tagged-union payloads propagate affinity (D612); and contextual closers consume their final resource parameter (D613). Fixed arrays inherit their element's classification and track comptime-indexed slots, exact provenance and full or comptime-offset slice aliases (D616-D620). Runtime-indexed reads, moves, overwrites and stores conservatively cover every possible affine element, and runtime-offset slices retain the same owner set (D711, D716-D720). Owned resource-slice parameters carry collective obligations, reject partial moves, drain through a proven zero-to-length sweep, and receive full or comptime-offset fixed-array ownership transfers (D721-D725). Dynamically filled `os.Thread` arrays retain their view behavior until owned resource-slice summaries can prove helper joins. Seeded handle representations are private behind explicit plain-handle views; resource reflection is empty outside the declaring module; `meta.get` and `meta.set` reject affine fields; and every delivered typed format codec stops at the same named-field boundary (D624-D628). Both host compilers pin valid transfers and each negative surface. The debug check-bodies cost is counted in callgrind instructions against the same compiler without resource checking; exact gates on `ret`, the lent/dangling alias questions and bare-name paths bring `sc500k` inside the +10% budget at +9.1% (D1563). Four more exact cuts (opacity asks the module first, add_local keeps the affine answer, thread reads skip until a thread runs, stores ask the value before the place's path) put both debug rows inside D352's +10%: sc500k +7.4% in instructions, the compiler source +9.2% wall-clock (+12.9% in instructions) (D1564). A region value or view handed to a non-`own` parameter beside `&c` leaves `c` holding it unless the parameter is `@noescape`, the callee's body (followed across modules to the least fixed point) keeps nothing of it, or `c`'s type has no slot its pointers fit; `@noescape` now refuses a store through another parameter (D1565). An owned resource slice or tracked array handed over as `x[..k]` and `x[k..]` with one immutable or comptime bound moves whole; between the sides every owed element is maybe-moved, the other side must follow in the same block or arm, and any other range of one is E-SAFETY-0003 (D1566). `let x = try f()`, `let (a, b) = try f()`, `x = try f()` and a statement `try` in a function answering more than its `err` now lower (they stopped the build before), returning the error beside zero values through the same path as `ret` (D1567). `list.Owning[T]` holds obligated elements failure-safely: slots reserved up front, a full `own_put` hands the element back, `own_take` gives one out, and `owning_finish` ends an empty list and traps on one still holding elements; forgetting the list or a handed-back element is E-SAFETY-0002 (D1568).

### C066 — General comptime interpreter

A `const` initialiser may call a function (D218): the interpreter walks the callee's syntax tree with integer and bool values -- locals, assignment and the compound forms, `if`, `while`, `break`, `ret`, every operator, checked casts, constants, and calls to other such functions in any module -- under the section's ten-million-step budget, and a call that reaches anything else, or runtime state, is refused under E-COMPTIME-9999 naming the constant and what it reached (link/comptime_call, check/comptime_call_runtime, check/comptime_call_budget). A call stands in an array length and a `[...]` argument the same way (D219), and a `when` condition that is not a question about the target is a bool it evaluates (D220); an array local of integers or bools -- `zero`, indexed reads and writes, `.len` -- and `for` over a range run in the frame (D221, a sieve in link/comptime_call). A `const` may be a bool -- `true`, a comparison, `&&`, `||`, `!`, or a call -- and a constant that reaches a call through another is put off until the signatures exist rather than refused (D222); one a type asks for before them is refused with the reason (check/comptime_call_in_type). An `if` whose condition is constants alone -- a comparison, `&&`, `||` over constants, literals and their operators, no local and no call -- is settled by the same interpreter (D500), the arm not taken no code in the checker and the lowering alike, and a `phase` record each; `fold_const` pins two folds and a branch over a local. The interpreter's values live in section 9's byte-addressed memory in the target's layout (the layout moved into the checker, byte-identical output): structs, arrays, slices and strings as locals, parameters and results, fields, indexing and ranges with bounds checks, copied by value across calls, one slot per allocation site per frame (D1569, link/comptime_struct, link/comptime_array_call, check/comptime_slice_bounds). Pointers are interpreter addresses: `&x` of any place, `*p` as place and value, fields through pointers, equality, `mem.cast[*U]` reinterpreting in the target layout, functions with no result, and a pointer-valued constant refused as section 9 requires (D1573, link/comptime_pointer, check/comptime_pointer_result). Evaluated bodies take `err` values (`ok`, named and qualified errors, equality), calls with several results in a caller-owned area, `ret (a, b)`, `let (a, b) = f()` with `_`, and `try` as a statement and a binding's initializer, a failure returning the error beside zero values (D1574, link/comptime_errors). `mem.arena_from` runs as written over interpreter memory, and `mem.alloc[T]` (aligned, `Exhausted` when full, 0xCD fill), `mem.mark` and `mem.reset` (0xDD fill) follow the runtime, their results bindable and `try`-able (D1575, link/comptime_arena). An evaluated body asks the checker's reflection questions -- `meta.type_name`, `mem.size_of`/`align_of`, `meta.array_len`, `meta.signed` -- and unrolls `for f in meta.fields[T]()` and `for m in meta.members[E]()` with `name`, `offset` and `value` (D1576, link/comptime_meta). `eval EXPR ROOT ARCH OS [FILE]` folds `EXPR` as a `const` in FILE's scope (or an empty module's) through the interpreter and prints the integer or bool, with no codegen and no link, refusing what a `const` would refuse (D1577).

### C084 — DWARF, CodeView and .nepersym debug info

The symbol and line table (D206, D209): after the code, per function its start, length and `module.function` name, and its line rows -- a code offset, a line and a file wherever the line changes, inlined bodies naming their own file -- which the trap protocol reads for its backtrace; artifacts carry the rows in a Lines section and the artifact path reproduces the table byte for byte. (D1581) Every ELF image, debug and release, carries unloaded section headers, a `.symtab` (`_start` and each placed function), the D206 table named `.nepersym`, and DWARF 4: a compile unit, a subprogram per function (main's with `DW_AT_main_subprogram`) and a `.debug_line` program from the same rows, with a row at each function's entry. gdb 15.1 breaks after the prologue, steps by line and backtraces `add`/`main`/`_start` with lines; addr2line and objdump name every function; the loaded bytes of all 589 link fixtures are unchanged, and `run.sh` checks the sections and gdb's stop. (D1582) Variables: lowering records each bound name and parameter, selection places it (a stack object or parameter slot for the whole function, else its register or spill slot over its live range, split at call windows into the preserve slot), and a Vars section (format 18) carries the records and a struct type table through the artifacts, emission reuse included; every ELF image gets DWARF types (primitives, str, pointers, slices, arrays, structs by qualified name, enums), parameters and variables with exprloc or .debug_loc locations, and a .debug_frame naming each function's callee-saved slots. gdb 15.1 shows arguments, locals, struct fields, enum members and `ptype` in the stopped and the calling frames, in a test program and in the self-hosted compiler; `run.sh` checks a local and an argument; loaded bytes of all 590 link fixtures unchanged, Windows images byte-identical, a warm build with reused functions equals the clean one, cold Linux build +7%. (D1583) PE images with line rows carry the same DWARF (lines, locals, types, frames) in five discardable `.debug_*` sections named through the COFF string table, plus a COFF symbol per function, as MinGW lays them out; `link_elf.write_dwarf` is shared by both linkers (and D1582's `.debug_line` size fixed). All 590 link fixtures run on Windows with the previous compiler's exit codes and output, the self-hosted compiler reproduces itself, objdump and gdb in WSL read the sections, symbols, lines and locations, and `run.ps1` checks the sections and names. (D1584) A local's scope runs from its binding to the end of its block (blocks and switch arms close it in lowering); Vars records carry it (format 19) and the linker nests a DW_TAG_lexical_block per block, so gdb lists a block's locals only inside it and resolves sibling blocks' same-named locals to the one in scope; `run.sh` requires a lexical block, all 590 link fixtures still behave as before on Windows. (D1585) A bare union is a DW_TAG_union_type of its members (referred to by a union declaration), and a tagged union a struct of its `tag` enum (`Name.Tag`) and an anonymous payload union, so gdb reads `n.tag` and `n.Square` as the language does; the new `debug_types` fixture runs on both hosts and `run.sh` checks gdb's struct, enum, union and tagged-union answers. (D1586) The trap walk's table is section 13's NEPS layout (header, sorted 32-byte entries of u64 start/end and name/file/line-program indexes, length-prefixed strings, ULEB128 delta line programs) in its own section -- `.nepersym` after the runtime on ELF, a `.nepsym` data section on PE -- rebased and re-pointed by the linkers; both runtimes binary-search it and decode the programs (re-embedded with ml64 and GNU as). Backtraces are unchanged: 460 Windows and 425 Linux link fixtures agree with the previous compiler on exit code, stdout and stderr. (D1587) Closed at the user's call: CodeView on PE is the roadmap's M4 PDB writer (MSF container, DBI, module, symbol and line streams) and is tracked there; every other line of C084 is delivered on both hosts (D1581-D1586).

### C089 — M3-01: @gpu profile enforcement, device types, address spaces, shared var

The `@gpu(X, Y, Z)` attribute is read at signature collection: one to three positive integer literals with a product of at most 1024, on a non-extern function, refused otherwise under one diagnostic; a kernel called anywhere but `gpu.launch` is refused at the call (D778). `shared var name: T` is a statement directly in a kernel's body with a device storage type and no initialiser, refused elsewhere, with an initialiser, or with a pointer, slice, string, bool or function type; on the CPU build its storage is the workgroup's block, one per launch, addressed in the kernel's entry block and filled with 0xCD before every workgroup (D781; `link/gpu_shared`). `[]shared T` and `*shared T` parse and are erased on the CPU build, as section 10 says they are. (D1588) A kernel's body and every helper it reaches are walked (as D1565's callee walk) and the first construct outside section 10's device profile is reported at the kernel with its call chain: recursion, function pointers, module-scope vars (not `e.gpu`'s), `try` in the kernel, `mem.cast`, extern calls, `e.thread`/`e.atomic`, `undef`, bare unions, and addresses or slices of private variables; kernel parameters must be device storage types or slices of them. Four refusal fixtures and one accepted kernel on both hosts; every GPU link fixture still builds. (D1589) A device-only helper (reads `gpu.*` ids, barriers, device atomics or subgroups, or names `shared`) is refused when called from plain CPU code; `gpu.Buf[T]` refuses an element that is not device storage; the kernel walk follows generic helpers; `@gpu` takes `caps(...)` and `ftz`, the walk infers each kernel's capabilities and refuses one outside `caps(...)` with the chain, and the Interface entry (format 20) records the inferred set and the `shared var` total. Five check fixtures on both hosts; every GPU link fixture unchanged. (D1590) `[]shared T` and `*shared T` are types distinct from `[]T` and `*T`: a flag on the checker's type, set by the written qualifier, a `shared var`, and slices and addresses of shared storage, compared by equality and assignability, printed in diagnostics and carried by the Interface's type encoding; `gpu_spaces` runs shared slices and pointers through typed, generic and pointer helpers on both hosts and `gpu_space_mix` is refused. C089 is complete.

### C097 — Warm rebuild from the command line: hello world 0.4 s, the compiler 1.7 s

Measured 2026-09-27 on Windows with build/windows/neper-self.exe `build FILE --output EXE`, twice each: a four-line hello world took 569 ms then 412 ms, and src/main.e 1,841 ms then 1,726 ms, against D336's 80 ms warm compiler build. The cause (D1681): the short `build` and `run` never passed `--incremental`, so every build was cold, and a warm build then still checked every declaration and linked the image it already had. The short spellings are incremental now (the image stays the clean build's, spec section 12), and a build whose every module is stable since its artifact, with nothing reported, stops after the load when the stamp beside the artifacts -- a key over the compiler identity, the command line less -j/--perturb/--time, and each module's artifact checksum, with the image's SHA-256 -- matches and the output file still hashes to that image. Measured on Windows, idle: hello world cold 210 ms, warm 23-28 ms; src/main.e cold 1,770 ms, warm 49-51 ms (a warm build that links is 285-335 ms); the warm image is byte-equal to the cold one; an edited source rebuilds, and an output tampered with, deleted or at another path is linked again. Pinned in both suites: the second `--incremental` build of a program reports no check or link phase, and a tampered output is relinked to the same image, which runs.

### T002 — build

`emit-executable PATH ROOT ARCH OS OUTPUT [--release] [--arena SIZE] --json` (D230): the section 1 header with command `build`, every front-end, lowering, code-selection and error-table diagnostic as a record, and the result naming the executable as it was given; tests/conformance/tools pins a program that builds and one that is rejected. Every successful build writes `.neper/<mode>/build-manifest.json` under the project root, making the directory when it is missing (D254, D287: `os.mkdir` joined the fixed surface as a bootstrap intrinsic, the self-hosted side already having it from the per-host `e.os` source), its one artifact the executable as named with the SHA-256 of the bytes written; both suites remove the directory, validate the manifest the build makes against the schema and compare the hash to the file on disk. `--project DIR` names the project root outright instead of discovering it from the operand (D263), so a file outside the tree -- a generated test runner -- is built as part of it. Spec section 2's spelling works (D276): `neper build FILE [-o OUT] [--target ARCH-OS] [--release] [--json]`, with the toolchain root the binary's own directory, the target the host unless said, and the output the operand's stem (`.exe` on Windows); `run`, `check`, `fmt`, `index`, `dis` and `build-manifest` have the same front door; both suites compare the short `build` stream to the positional form's golden. `neper test FILE [--project DIR]` is the short `test` (D292): always the stream, its WORKDIR `.neper/debug/test/` under the project the operand is in, made when missing; both suites compare it to the positional form's golden. `neper check` and `neper test` with no operand are the project the current directory is in (D294). Not yet: a project root as `build`'s operand, and warnings. D1682: `neper build` and `neper run` given a directory, or no operand, build that project's (or the working directory's) `src/main.e` into an executable named after the project's directory, written into spec section 13 and pinned in both suites; warnings are disabled in v1 by spec section 13, every diagnostic an error or a note on one. A repeated short `build` is incremental and stops after the load when nothing changed (D1681).

### T030 — lang-stats.py judges the compiler, not the shell: failures and build time

Of 266 failed build-shaped commands in 2026-09-20..27, 134 failed on a compile code, 16 on a trap, a test assertion, a timeout or the bootstrap lint, and 116 on the shell or the harness (a PowerShell suite line, a blocked sleep, a denied permission, an awk syntax error, a missing file), yet fail% and 1st-ok% count all 266 against Neper. bld ms is the wall time of the whole Bash call, including the 0.3-1.4 s every call pays and the program or suite it runs: of 3,714 counted commands only 368 compiled and nothing else, and even those median 2.2 s. Done when fail% counts a failure only with a compile code or a test/assert/trap signature (plumbing reported apart), and build time is reported for compile-only commands beside the whole-command figure. The patch.exe spec counting and the repo-path match of `neper` as a build are fixed in scripts/lang-stats.py already, and --harness claude|codex|dsh now reads one agent: pooled rows put Codex's Neper sessions (fail% 15.5, 1st-ok% 82.3, thk/B 0.177 in 2026-09-20..27) against a Dart row Codex never wrote, and removing them moves Neper's 30-day fail% from 6.9 to 4.9, 1st-ok% from 92.9 to 96.4 and selfcor% from 26.7 to 14.4. Three more distortions remain: a Python patch script run in the same command as a build counts the build's failure as an edit that did not apply (130 of 2,016 script runs in the week), so edit% (Claude 4.5 vs Dart 1.5) mostly measures builds, while Claude's own Edit tool failed 3 times in about 1,750; Neper probe programs written to the scratchpad count as landed code (1,954 of 14,088 KB in the week), cheap whole-file writes that flatter $/KB; and Dart shows 3 compile fixes and cmpl% 0.2 over 30 days, which suggests COMPILE['Dart'] does not match the analyzer's output, leaving fix turns, 1-edit% and repeat% with no Dart side to compare -- to verify against a Dart transcript's failed build. D1680 meets the done bar: a failed build-shaped command with neither a compile code nor a test signature (assert, panic, trap, timeout, a suite's throw at run.ps1/run.sh:N, lint_bootstrap, exit N) is plumbing, out of builds, fail% and 1st-ok% and reported as plumb%; cmp ms is the median of compile-only commands beside bld ms; and a source file written under a scratch or build folder is a probe, a helper that lands nothing. Last 7 days, Claude: Neper fail% 2.5, plumb% 2.7, bld ms 3,155, cmp ms 1,604, landed 4,461 -> 3,523 KB. The two distortions left are closed too (D1680): a patch run chained with a build charges the build's failure to the build, not the edit (Neper edit% 3.2 -> 2.8, builds 1,561 -> 1,766 over 7 days), and COMPILE['Dart'] was checked against the 32 failed dart/flutter commands of the last 600 transcripts -- every one condensed or grep-filtered with no analyzer line left, so the near-zero Dart cmpl% is the missing text, not the pattern.

### T014 — Build manifest with versions and SHA-256

`build-manifest-file PATH ROOT ARCH OS --json` (D238): the canonical `neper-build-manifest` object -- schema, version, tool and language versions, grammar revision, target, mode, root module, and one `inputs` entry per source module carrying its source identifier and the real SHA-256 of its bytes (ported into artifact_hash.e over the byte-per-slot representation, checked against the RFC 6234 `abc` vector and python hashlib); tests/conformance/tools/manifest.e pins it per host. A build writes the same object to `.neper/<mode>/build-manifest.json` under the project root with `mode` from `--release` and `artifacts` carrying the executable as named, `kind` executable, the target and the SHA-256 of the bytes written (D254), making the directory when it is missing (D287). Every input carries section 2's real identity (D265): `project-src` or `project-lib` with its path under that root, `toolchain-lib` for a module under the toolchain's lib, and the operand by its basename otherwise; and every module but the root is a `dependencies` entry with `interface_sha256` -- the source with every function body left out, so an edit inside a body moves only `body_sha256` -- and `body_sha256`, the whole file; tests/conformance/tools/manifest_project pins a two-module project per host. The artifact's path is project-relative as section 7 says (D293): the executable as named, made absolute under the current directory, then spelled from the project root with `/` separators, or kept absolute when it lies outside the project; both suites read the corpus build's artifact by that spelling. The `unsafe` inventory and `options.checks` (D355). Every declared asset as an `assets` entry with its project-relative path, media type, attributes, size and SHA-256 (D792). Libraries (D1685): one entry per library the image imports, resolved as the target's loader will -- the executable's directory then System32 with `.dll` added on Windows, the library directories on Linux -- with its SHA-256, null off the target's machine or when not found; a no-op build lists the same through the stamp; link/extern_import pins kernel32 and libc.so.6 in both suites.

### T010 — dis

`dis-file PATH ROOT ARCH OS --json` (D233): the codegen pipeline, then one `disassembly` record per emitted function with its module.function symbol, the target triple and its listing, ending in the result with the function count; tests/conformance/tools/dis.e pins it per host. The listing is a mnemonic disassembly (D269, src/disasm_x64.e): one line per instruction -- the function-relative offset, the Intel-order mnemonic and operands (64/32/16/8-bit and xmm registers, `[base + index*scale + disp]` and rip-relative memory, signed immediates, jump targets as offsets), then the bytes after `;` -- from a linear sweep over the encodings emit_x64 produces, with section 11's inline trap text listed as one `text` line rather than decoded; 3,546 instructions across three fixtures were cross-checked against GNU objdump with no semantic difference, and eight fixtures list with no unknown byte. A `call` is named after its bytes (D278): `-> module.function` when its resolved displacement lands on a function's start, and the runtime or imported symbol from the relocation that will fill it otherwise (`-> neper_os_exit`). `--att` (D1703) spells the listing as GNU `as` does -- reversed operands, `%`/`$`, `disp(%base,%index,scale)`, suffixes only where no register sizes the operation, `movzbl`/`cltq`/`movsl` -- and 174,732 instructions from eleven fixtures assemble to identical bytes from both spellings; tools/dis_att pins it per host. The listing follows jumps (D1704): only bytes reached from offset 0 by fall-through, jmp and jcc are decoded, the emitter's inline strings and tables are `db` lines (tools/dis_follow pins it), and every legacy SSE form the vector selection emits decodes -- 27,090,684 reached instructions across the 617 compiling link fixtures with no undecodable byte, and an xmm memory operand no longer mislabelled `qword`. The VEX forms `--cpu x64-v3` emits decode through the same 0F rows (D1705) -- ymm, the vvvv source, NDD shifts, an xmm shift count, vzeroupper -- 24,191 instructions of simd_lanes under x64-v3 with no undecodable byte and identical GNU bytes from both spellings; tools/dis_vex pins it per host

### T013 — Stable diagnostic codes from diagnostics.md

39 of 46 registered codes are emitted (D215; the E-SAFETY codes under D345, D348, D349, D351, D354, D357 and D365; E-TEST-9999 under D256, E-FORMAT-9999 under D257, E-TOOL-0001 under D264, E-SYNTAX-0012 under D275), and every one reaches the JSON stream as a `diagnostic` record with its span (D228): E-CLI-9999 for the usage line, E-LEX-0001/0002/0003/9999 for the token the scanner refused by the byte it starts at, E-MODULE-0001 for a `use` naming no module or one defined by both roots and E-MODULE-0002 for one closing a cycle, each at the module that wrote it, E-COMPTIME-9999 for a reflection shape and E-MEM-9999 for an atomic's element or ordering, beside the E-NAME, E-TYPE, E-ERROR and E-LINK codes already there; check/module_missing, module_cycle, lex_literal, lex_tab, lex_utf8 pin them. E-FORMAT-0001 for a source that is not in canonical layout, via `fmt --check` (D244). `test` reports E-TEST-9999 at a `@test` that is not a test -- not a function, or one with a signature other than `fn name(a: *mem.Arena) -> err` -- and exits 2 with nothing compiled (D256, tests/conformance/tools/test_reject.e). `fmt` refuses a comment between an attribute and its declaration as E-FORMAT-9999 at the comment, and an invalid token under its lexical code, as records in the stream rather than a bare `error:` line (D257, tests/conformance/tools/fmt_reject.e). A stale or malformed source map beside the operand is E-TOOL-0001 (D264, tests/conformance/tools/stale_map.e). A soft delimiter still open at a column-0 declaration is E-SYNTAX-0012 at the opener (D275, tests/conformance/reject/barrier.e). Every code the compiler raises is pinned by a conformance fixture (D297). Not yet: E-GPU, E-SAFETY and E-TOOL-9999, whose subjects do not yet diagnose, and E-LINK-9999 pinned. Transcripts 2026-09-20..27: E-TOOL-9999 "internal compiler failure" ended 5 builds with emit_x64.Capacity, check.Unsupported, assets.InvalidManifest and assets.AssetMissing -- a capacity, an unsupported form and two asset-manifest faults, none of them internal, so each wants its own code and a message naming the limit or the file. D1683 names them: a full table says which (the machine-code buffer, the NIR tables, the checker's...), `check.Unsupported` is E-TYPE-0009, and an asset-manifest fault is E-MODULE-9999 from any command with the load's words, a missing asset naming its file (link/asset_missing, both suites and hosts). E-LINK-9999 is pinned by a real FNV-1a collision, `main.Ea88a` / `main.E16e68` (D1702, link/error_collision, both suites). E-GPU-9999 is section 10's refusals -- attribute, launch, device reach, caps, shared placement, barrier, a Buf element (D1706) -- pinned by the GPU refusal checks in both suites; E-TYPE-0009 by reject/not_supported, `continue` outside a loop given its own message (reject/continue_outside); E-TOOL-9999 by an apply-plan precondition under toolchain-lib (tools/plan_foreign_root.jsonl); E-SAFETY was already pinned code by code. Every one of the 66 codes in docs/diagnostics.md is raised and pinned, and render_card.py counts every family verified.

### T006 — fmt canonical layout

`fmt-file PATH --json` (D234): one `formatted` record whose text is the canonical layout -- four-space indent by brace depth, one space around binary and assignment operators and after comma and colon, no space inside delimiters or around `.`/`..` or before a call or index list, slice and array element types and prefix operators glued, comments preserved with a trailing comment one space out, blank runs collapsed to one with none at a block edge, a single final newline; tests/conformance/tools/fmt.e is already canonical, so the golden pins idempotence too; `--check` reports E-FORMAT-0001 at the first non-canonical byte and exits 1 (D244). One space inside a brace pair on a line -- `{ ret ok }`, `struct { a: i32 }`, `Pair { a: 1i32 }` -- and none in `{}` (D255), pinned by tests/conformance/format/layout.e, a deliberately mangled source whose canonical side is the golden; `fmt-file PATH` without `--json` prints the canonical text itself. What `fmt` refuses is diagnostics in every form (D257): each invalid token under its lexical code and a comment between an attribute and its declaration as E-FORMAT-9999, the stream ending in a result that exits 1 with no `formatted` record, the plain form printing the human lines to stderr. Three more of section 6's rules (D273): exactly one blank line separates top-level declarations -- an attribute, a `///` or `//` line, or a `use` before another `use` leads into the next one rather than separating it -- an empty block is `{}`, and `else` follows `}` on the same line; the format fixture pins all three. The contiguous comment-free `use` block at the start of a file sorts by module path then alias (D274), pinned by the fixture. A bracketed list -- a call's or signature's `(...)`, a type body's `{...}` -- that would exceed 100 columns from where it opens breaks after the opener, one element per line four columns in with a trailing comma, the closer back on the opener's indent; one that fits is joined onto one line with no trailing comma; a grouping `(` or any `[` only ever joins, since a trailing comma inside is not syntax, and a list with a comment inside is left as written (D277). A member literal after a keyword keeps its space (`case .Red`, not `case.Red`) and a `case` or `default` label sits at its `switch`'s indent, the statements under it one level in (D284). Every source of the compiler and the library formats idempotently, and a compiler built from its own formatted source agrees with the goldens. An aggregate literal's body is a list too (D285): a `{` after a PascalCase name outside an `if`/`while`/`for`/`switch`/`when`/`else` header or a signature's `-> Type` is the parser's own literal rule, so `Pair { a: 1, b: 2 }` joins and a wide one breaks one field per line. A run of attribute lines sorts by attribute name (D286). `fmt -` reads stdin and writes only the canonical source to stdout, `--json` the `formatted` record under the `--path` identity (D289). `fmt FILE` formats the file in place, writing nothing when it is canonical, and `fmt` with no operand formats every `.e` under the project's src/ and lib/ in byte order, `--check` naming each non-canonical file as an E-FORMAT-0001 line and exiting 1 (D295); both suites format a one-file project and a copied file to the corpus's canonical text. `fmt --check --json` over a project is a stream (D1699): a diagnostic per non-canonical file under its project identity, at its first differing byte, pinned as tools/fmt_project on both hosts. A raw string takes the fewest `#` that keep its bytes (D1700, format/raw_strings on both hosts). A layout that does not parse is refused with the parser's diagnostics (D1707): the grammar ends a statement at its line, so two on one line are E-SYNTAX-9999 and never formatted (tools/fmt_statements), while an `else` the layout joins to its `}` is repaired; the check found `ret (` breaking a grouping as `(x,)`, which now joins (format/ret_grouping); the whole tree formats to text that parses, the same 394 files non-canonical before and after, both hosts.

### T003 — check

`check-file PATH ROOT ARCH OS --json` (D228): the header, a `diagnostic` record for every error the front end reports -- lexical, syntax, module, resolution and checking, each with its registered code, message and span -- an unreadable operand as a location-free E-CLI-9999 with exit 2, the `result` with the exit status, and nothing on stderr; every diagnostic printer goes through one emitter that writes the human line or the record. tests/conformance/accept and reject pin five streams byte for byte on both platforms. `check-project DIR ROOT ARCH OS WORKDIR --json` checks every module under DIR/src (D262): the tree walked in byte order so the stream is the same on every filesystem, each module checked in its own `check-file --json --path REL` process so its identity is its path under src -- `nested/deep.e`, not a basename -- and the children's records merged into one stream with one header and one result carrying the diagnostic and module counts; tests/conformance/tools/check_project pins three modules, two with an error. `neper check FILE` is the short spelling (D276) and `neper check` with no operand checks the project the current directory is in as `check-project`, working under its `.neper/debug/check/` (D294), as does `neper test` as `test-project`; both suites run each from inside a corpus project and require the project form's golden. `check-file - ... --json --path REL` reads the module from stdin under the `--path` identity (D490), the reject corpus's golden byte for byte on both hosts. A project walk names each module under `project-src` (D1697): `check-project`, `index-project` and `test-project` pass `--project-path src/REL`, and every span, precondition and test `file` carries it, both hosts. A module outside src is walked by no child of its own, so its diagnostics come from the src modules that reach it, each written once (D1709): a lib type error had been dropped and the project checked clean; tools/check_project_lib pins it in both suites, and a missing work directory is made rather than an internal failure. A note's `parent` is renumbered to its error's place in the merged stream (D1710), a note whose error comes from a module walked later waiting for it, pinned by tools/check_project_notes in both suites.

### T001 — JSONL v1 stream envelope and version header

The header, diagnostic, token, syntax and result records of section 1 (D227, D228), each a line, the result last with the exit status; emitted by `tokens`, `parse`, `check-file`, `info` (D229), `emit-executable` (D230), `run` (D231), `index` (D232), `dis` (D233), `fmt` (D234) and `test` (D240) -- every section 1 command now streams. An operand that cannot be read answers with the envelope on every one of them (D260): the header, one location-free E-CLI-9999, the result exiting 2 with the command's own zero counts, pinned in both suites for tokens, parse, fmt, fmt --check, dis and test; `check`, `build`, `run` and `index` had it since D228-D232. `-` reads the operand from stdin under the `--path` identity section 4 requires with it, on `tokens`, `parse` and `fmt` (D289: `os.stdin` joined the bootstrap's fixed surface the way `os.mkdir` did); both suites pipe a fixture in and compare against its own golden. `--absolute-paths` on `tokens`, `parse`, `check` and `index` adds `absolute_path` beside the operand's identity and changes nothing else (D290: an absolute operand as given, a relative one under the current directory, which `os.current_dir` joined the bootstrap's fixed surface for); both suites take the field out of a check and a tokens stream and require the golden. `-` on `index-file` under `--path` (D488) reads the module from stdin, the loader taking the text as the root's; both suites pipe the index fixture in and require its golden. `.` and `..` segments are collapsed in `absolute_path` (D489), never past a drive or the leading separator, so two spellings of one file compare equal; both suites spell the fixture roundabout and require the plain path. JSON output that cannot be written -- stdout closed, a full device -- is the one ASCII line section 2 allows on stderr and exit 2 (D1711), where main had tried the failure record on the same stdout and fallen to the runtime's line; the Linux suite pins it through /dev/full.

### T015 — Generated source maps

Section 8, both halves (D264). The generator: `test` writes `nptest-runner.e.map.json` beside the runner it generates -- `neper-source-map`, the runner's SHA-256, one mapping from the operand's text at its place in the runner to the operand -- validated against the schema by both suites. The consumer: `emit-executable`, `run`, `dis` and `check-file` read `<operand>.map.json` when one lies beside the operand; a diagnostic inside a mapped range is reported at the original span as primary with the generated span related, so a test that does not compile is reported at the test's own line (tests/conformance/tools/test_compile_error.e); a map whose hash is not the operand's, or that is not a source map, is E-TOOL-0001 and the command fails with no artifact written (tests/conformance/tools/stale_map.e). The runner's map has two mappings when the operand's `main` was renamed (D281), the second beginning mid-line. A stale or malformed map is E-TOOL-0001 up front and the analysis still runs unmapped, so the operand's own diagnostics follow it; `check` and `build` then fail with no artifact, as section 8 says (D300, tests/conformance/tools/stale_map_error). The project walks' modules are under `project-src` (D1697). The operand's map holds 32 mappings (D1698, tools/many_mappings maps an error in the twelfth splice to its input on both hosts). A mapping moves the columns of its first line by where each side begins (D1713): an indented splice and the renamed `main`'s own line report the original's column (tools/test_main_line, and five corpus goldens that had recorded the generated column). The map is read member by member (D1714): whitespace, key order and escaped strings are any generator's choice (tools/pretty_map, indented, keys reversed, its input path escaped, maps to the input on both hosts).

### T009 — index, symbols and references

`index-file PATH ROOT ARCH OS --json` (D232): a `symbol` record for the operand module and each of its module-scope declarations -- fn, extern, type, const, module_var, error -- with the closed `kind`, qualified name, full and selection spans and container id, ending in the result with the symbol count; tests/conformance/tools/index.e pins all seven kinds. Each symbol carries its `signature` (the header up to the body brace, so a const or extern is its own), its `attributes` (the `@name` run section 12 requires adjacent) and its `documentation` -- spec section 3's `///` run, one optional space stripped, joined with LF, ended by a blank line or an ordinary `//`, and attaching through the attributes (D251); the fixture pins a two-line doc, a documented `@test`, and a run broken by a blank line. Under a function or type the parse tree supplies its parameters, fields and enum/union members as `parameter`, `field` and `member` symbols with the declaration as `container_id`, qualified `module.Decl.name`, their own signature and `///` documentation, in token order (D258); the fixture pins a documented field, two enum members and three parameters. Every use of one of the module's own names, and every name reached through a `use` qualifier, is a `reference` record (D271): `import` for each `use`, `type` in a type position or a type's name in a path, `call` before `(`, `instantiate` before `[`, `write` before an assignment, `address` after `&`, `read` otherwise; a bare name resolves to the operand's symbol by id -- spec section 5 lets no local shadow a module-scope name, so the match is the resolution -- and a qualified one names `path.name` with a null id; records sorted by span start after the symbols, the result counting both; the fixture pins eleven across every role but `protocol`. Symbols and references go out in section 5's one span order (D280): the references are collected first, every symbol's id is known before any record is written, and each reference is emitted before the first symbol -- nested ones included -- whose span starts after it; the fixture's thirty records are monotone in span start. `index-project DIR ROOT ARCH OS WORKDIR --json` indexes every module under a project's src and lib in byte order, each in its own `index-file --json --path REL` process so its identity is its path from the root, the symbol, reference and diagnostic records under one header and a result with the totals; `neper index` with no operand is that over the project the current directory is in (D298, tests/conformance/tools/index_project). Locals are symbols (D483): every `let`/`var` binding, each name of a tuple binding, and every `for` variable is a `local` under its function, and a bare name in the body that is a local or parameter declared before it is a reference to that symbol with its role, read off the tree as the module-scope references are; the two index goldens carry them. The sixteen compiler-origin functions exposed through the source-delivered `e.atomic`, `e.io` and `e.str` modules are null-span `intrinsic` symbols with exact canonical signatures (D577). `index --all` (D1686) indexes the toolchain's lib after the project's modules, each under `toolchain-lib` through `index-file --toolchain-path`, less the modules the project's own lib shadows: 360 modules from tools/index_project on both hosts, pinned in both suites. Comptime parameters are `parameter` symbols whose signature says `T: type` (D1708), and a use resolves to them as to a local, in a type position too: `[N]T` reads `N` and names `T` as `type` (tools/index_comptime, both suites, both hosts). The calls the compiler makes are compiler-origin `protocol` references (D1715): index-file runs a partial check, and each dispatch settled on a declared function -- a template's `T.eq` once per instance, a `for`'s `next` at its subject -- names its concrete target, with the id when it is the module's own; a supplied operation names none (tools/index_protocol, both suites, both hosts).

### T005 — test and @test discovery

`test-file PATH ROOT ARCH OS WORKDIR --json` (D240): the @test functions of the operand -- an `@test` attribute on a top-level `fn` -- are discovered in source order, a runner carrying them is compiled by spawning the compiler again, and each test runs in its own process so a trap is a crash rather than aborting the harness; the section 7 stream buffers one `test` record per function in source order, a `test_summary`, and the result, exiting 1 if any test is not `passed`. A returned err is `failed`, a trap `crashed`, classified from exit status and stderr; each test and the run carry a real `duration_ms` from the monotonic clock (D242), normalised out of the golden. a test that outruns the deadline is ended by a watchdog thread inside the runner -- the fixed os surface gives the driver no kill and no timed wait, so the child self-terminates on the futex wait's deadline and exits 124 -- and is reported `timeout` with the deadline in `timeout_s` (D246, `WORKDIR [TIMEOUT_MS]`). A crashed test carries the same structured `trap` payload as `run` (D253), mapped from the generated runner back onto the operand -- the runner is the operand's text two `use` lines down, so its span, frame functions and lines come out as the operand's, and a frame in the runner's own scaffolding keeps its printed name with no source; a crash with no record is the `exit` kind carrying the status. `error` is `ok` for a passed test and the qualified name after `error: ` for a failed one, with the runner's module name replaced by the operand's; the fixture's third test indexes past a five-element array. A `@test` that is not a test is refused before anything is compiled, as E-TEST-9999 at the declaration (D256). `test-project DIR ROOT ARCH OS WORKDIR [TIMEOUT_MS] --json` runs every module under DIR/src (D263): the tree in byte order, each module through `test-file --json --path REL` in its own process so its `file` is its path under src and its `module` the dotted name (`nested.deep`), the runner built as part of the project via `emit-executable --project DIR` so a test's `use` of a sibling module resolves, a module with no tests counted and skipped without a compile, and the children's records merged under one header, one summed `test_summary` and one result with the test and module counts; tests/conformance/tools/test_project pins three modules, one test-less, one failing test and one nested test that uses a sibling. A test that does not compile is reported at its own span through the runner's source map, the compiler's records forwarded before the E-CLI-9999 (D264). An operand that both defines `main` and carries tests works (D281): the runner renames the operand's `main` to `nptest_operand_main` and its source map carries the seam as a second mapping, so a diagnostic past it still lands on the operand (tests/conformance/tools/test_main, test_main_error). A failed `test.assert`, `eq`, `near` or `fail` puts its message in the test record (D1684): `e.test`'s `current` record, the root writing it to stderr between 0x1E bytes after the test, `neper test` lifting it into `message` before the outcome is read (tools/test_message, both suites and hosts). A test that calls the operand's own `main` reaches it (D1716): the runner renames every bare `main` of the operand, with a map seam at each, so an error after two calls on one line is reported at the operand's column (tools/test_main_call, test_main_call_error, both suites and hosts).

### T007 — tokens, lossless over 94 tokens

`tokens [--json] [--path VIRTUAL.e] FILE` (D227): the section 1 header, a `token` record per token with its registry kind, lexeme, span and leading trivia, a `diagnostic` before each `INVALID` token whose lexeme is the base64 object, and the `result`; every record validates against docs/schemas/neper-v1.schema.json, the trivia and lexemes concatenate back to every byte of the compiler's own sources, and tests/conformance/tokens pins every_kind (93 of the 94 kinds) and hostile (BOM, CRLF, a tab, unterminated literals, invalid UTF-8 inside a comment) byte for byte; `-` reads stdin under `--path` (D289) The 94th kind is INVALID, which a valid file cannot hold: tokens/hostile pins it, so the two fixtures pin all 94 between them (D1718).

### T008 — parse, lossless over 54 syntax nodes

`parse [--json] [--path VIRTUAL.e] FILE` (D227): the token records, one `syntax` record whose root lists the top-level nodes with kind, span, token range and ordered `{node}`/`{token}` children, a `diagnostic` where the parser stopped, and the `result`; schema-valid, and tests/conformance/parse pins every_kind and recovery byte for byte. Recovery past the first error was already in the tree -- an `ErrorNode` per failed statement or declaration, the parse going on -- and now every failure is a diagnostic at its own token, not only the first (D275, parse/two_errors pins three); a soft delimiter still open at a column-0 declaration keyword is E-SYNTAX-0012 at the opener, naming the keyword that ended it, in the parse stream, the check stream and the human line (parse/barrier, reject/barrier); `-` reads stdin under `--path` (D289) Every one of the 54 node kinds is in a parse golden (D1718): parse/node_kinds adds the six every_kind left out -- Attribute, UnionEnumType, UnionMember, GroupExpr, AggregateLiteral, LiteralItem -- in both suites.

### C090 — M3-02: SPIR-V emitter on the Vulkan 1.2 floor and the Vulkan compute runtime

The design and the split are D1610: NIR lowered without the CPU frame, private memory as word arrays, device addresses under PhysicalStorageBuffer64, one push constant holding the argument block's address. Row 1 (D1610): `emit-executable FILE ROOT spv none OUT` writes the program's kernels as one SPIR-V 1.5 module -- 32-bit scalars, device slices as two-word addresses (no Int64), the invocation ids, `if` and `ret`, NoContraction on every float result; saxpy's module ran bit-identically with the CPU on an NVIDIA RTX 3080 and an Intel Iris Xe and is pinned byte for byte in both suites (tests/conformance/spirv). Rows 2 and 3 (D1611): `e.gpu.vulkan` dynamically loads Vulkan, enumerates floor devices, owns mapped device-addressable buffers, pipelines and dispatch; `.Vulkan` is wired through `e.gpu`, and each kernel's dependency-linked `K$spirv` companion embeds its module for `gpu.launch`. `gpu_vulkan_raw` checks pinned saxpy bit for bit on every floor device or explicitly reports no device; `examples/saxpy.e` prints equal CPU and Vulkan checksums on an NVIDIA RTX 3080 and an Intel Iris Xe. Row 4 (D1612): the emitter writes structured nested `while` and `for` loops with `break` and one or several `continue` edges; NIR's private stack carries mutable values instead of SSA phis. `tests/conformance/spirv/loop.spv` passes Vulkan 1.2 validation and is pinned byte for byte; `gpu_vulkan_loop` matches every CPU/Vulkan result on an NVIDIA RTX 3080, an Intel Iris Xe and WSL's Vulkan device. Row 5 (D1613): f32 division and square root retain NoContraction FMA refinement and finish with exact u64 significand division or restoring square root, including normal/subnormal rounding, infinities and canonical NaNs; f32 kernels request DenormPreserve. `tests/conformance/spirv/float.spv` passes Vulkan 1.2 validation and is pinned byte for byte; `gpu_vulkan_float` matches 8,192 deterministic random and boundary vectors against the CPU on an NVIDIA RTX 3080 and Intel Iris Xe. Row 6 (D1614): 8-, 16- and 64-bit integer values, packed narrow private loads and stores, struct and array locals, by-value aggregate helper parameters, ordinary `OpFunctionCall` helpers and monomorphised generic instances. `tests/conformance/spirv/types.spv` passes Vulkan 1.2 validation and is pinned byte for byte; `gpu_vulkan_types` matches the CPU word for word on an NVIDIA RTX 3080, Intel Iris Xe and WSL's Vulkan device. Row 7 is partial (D1615): one module-wide Workgroup word block sized for its largest kernel, shared loads/stores and aggregate copies, `gpu.barrier`, both `gpu.memory_barrier` scopes, every scoped 32-bit atomic form and 64-bit device atomics. `tests/conformance/spirv/sync.spv` is pinned byte for byte; `gpu_vulkan_sync` matches CPU shared and atomic results on the RTX 3080, Iris Xe and WSL's Vulkan device. Row 7 subgroup coverage now includes identity and votes (D1720, D1721): `gpu.sid`, `gpu.subgroup_size()`, `gpu.subgroup_elect()`, `gpu.subgroup_all()`, `gpu.subgroup_any()` and `gpu.subgroup_ballot()` use the CPU's fixed 32-lane model and Vulkan's subgroup inputs plus Vote/Ballot operations. The CPU scheduler tags subgroup cuts separately from workgroup barriers, resumes independent subgroups, and snapshots predicates so every lane reads one completed vote. `tests/conformance/spirv/subgroup.spv` is pinned byte for byte; `gpu_subgroup_identity` validates full and partial subgroup votes and masks on the CPU, two Windows Vulkan devices and WSL's Vulkan device, and the complete Windows self-host suite passes. Capability discovery and launch refusal are now wired end to end (D1722): Vulkan queries integer, float, atomic, subgroup and f32 denormal support through `vkGetPhysicalDeviceProperties2` and feature records; `DeviceInfo.capabilities`, `gpu.has` and the generated launcher's inferred requirement mask use the same bits. `gpu_cpu` proves an unsupported `ftz` kernel is refused before execution; Windows runs each optional-capability fixture on its compatible adapter, WSL correctly leaves denormal-preserving float kernels on the CPU, and the complete Windows self-host suite passes. Broadcast and shuffle are now landed (D1723): typed 32/64-bit values cross the CPU's subgroup cut as snapshotted representation words, invalid or non-uniform sources trap, and SPIR-V emits the Ballot/Shuffle group operations. The pinned subgroup module is byte-identical across Windows and Linux; CPU, compatible Windows adapters and WSL pass full and partial subgroup checks. Row 7 is complete (D1725): integer add/min/max/and/or/xor and f32 add/min/max reuse the CPU snapshot and emit native SPIR-V arithmetic reductions; the pinned module is byte-identical across hosts, and the full/partial runtime fixture passes on the CPU, Windows Vulkan and WSL Vulkan, and the complete Windows self-host suite passes. Row 8 is partial (D1726-D1732): checked Vulkan launches carry a hidden fault-buffer address; bounds and slice guards use a device CAS so the first failure records its site and invocation, later failures count, and only the faulting invocation returns. Tag, enum, invalid and null trap blocks use the same writer and return. Pointer conditions collapse their two address words before the structured branch header, keeping `OpSelectionMerge` adjacent to `OpBranchConditional`. Debug integer add, subtract and multiply now guard their wrapped result for signed or unsigned overflow; divide and remainder always guard zero and signed `MIN / -1`, then record `Overflow` or `DivideByZero`. `gpu_fault_bounds` proves exact Bounds, Tag, Null, Alignment, Overflow and DivideByZero records, including null through a helper and every signed/unsigned arithmetic form, one-shot `sync`/`download`, `last_fault` and queue reuse on the CPU, two Windows Vulkan devices and WSL's Vulkan device. A module reserves the hidden slot only when reachable NIR can write a fault; its embedded companion marks that ABI, and `gpu_fault_nocheck` proves an all-`@nocheck` kernel starts ordinary parameters at byte zero on the CPU, two Windows Vulkan devices and WSL's Vulkan device. `gpu_fault_unchecked` builds a syntactically checked out-of-range access with `--unchecked`: CPU and Vulkan report no fault, exact Vulkan output proves the zero-prefix ABI, and both host manifests say `options.checks: off`. `spirv-val --target-env vulkan1.2` accepts both modules, their bytes are identical across Windows and Linux, and all six pinned SPIR-V modules remain unchanged. The full Windows suite remains blocked before compiler fixtures by the stale `docs/library-fixtures.json` produced by unrelated shared-tree library edits. Row 9 is partial (D1733): the Vulkan runtime persists one opaque driver blob per decoded SPIR-V xxHash64, entry point and device/driver/capability identity under the platform user cache or an isolated `NEPER_GPU_CACHE` root. Records carry magic, length and CRC-32C; a checksum-valid corrupt Vulkan header is rejected by the driver, rebuilt from an empty cache and durably atomically replaced only after pipeline success, while all cache I/O failures remain correctness-neutral misses. `gpu_vulkan_loop` restores the exact valid blob and CPU-identical output after that corruption on two Windows adapters and WSL's Vulkan device. The private `$spirv` companion now carries the writing compiler's executable/options identity (D1734), clean executable builds learn it, and `e.gpu` folds it into the cache key; changing only `--inline-cap` creates a distinct entry per device with the same CPU-identical result on Windows and WSL. Row 9 is complete (D1735): `gpu_cache_corrupt` injects a seeded rebuild failure after hashing the restored valid entry, requires a nonzero launch exit with that file byte-identical, then removes the injection and proves the cache remains usable on two Windows adapters and WSL's Vulkan device. Row 10 correctness is complete (D1736): GP-09's SIMD Base16 codec matches `e.bytes` for every tail length under the baseline and x64-v3 levels on Windows and Linux, while GP-10 maps the existing M3 corpus to its design obligations and keeps every exact compatible CPU/Vulkan result bit-identical on two Windows adapters and WSL. The comparison corpus and alternating standard-library runner are in place (D1737): C, C++, Rust, Go and Neper agree on both workload checksums, and Neper CPU/Vulkan agree on GP-10. The seven-run publication is complete (D1738): raw JSON and `docs/gp-performance.md` report every sample, compile/runtime p50 and p95, peak RSS and image size for all eleven C, C++, Rust, Go, Neper CPU and Neper Vulkan cells without hiding the measured optimisation gaps. The literal sweep now includes shared slices and pointers (D1739): NIR retains their address-space qualifier, `gpu_spaces` matches all eight CPU/Vulkan words on two Windows adapters and WSL's Vulkan device, and its raw module passes Vulkan 1.2 validation. The exact sweep also covers barriers and shared aggregates (D1740): `gpu_barrier` compares `relay`, looped `rounds`, and `plain`; `gpu_shared` compares integer `tally` everywhere and f32 `block_sum` where its denormal requirement is supported. It exposed and fixed contextual shared aggregate temporaries clobbering the workgroup block. All pass on two Windows adapters and WSL's Vulkan device. Packed private/shared bool spills are now emitted (D1741), making short-circuit kernels device-callable. `gpu_cpu` compares `ids` everywhere and `saxpy` on denormal-capable devices while checking `needs_ftz` capability/refusal; `gpu_present` compares every `fill` pixel. Both pass on two Windows adapters and WSL, and the raw module validates. The final exact-kernel audit is complete (D1742): `gpu_tensor` compares every reached u32 kernel, i64 where Int64 is present, and f32 where denormals are preserved on two Windows adapters and WSL. Undefined shared reads, deliberately divergent barriers, and compiler-statistics/incremental fixtures are explicitly outside the semantic comparison set. C090 is complete

### L009 — Neural layers for molecules and sequences in e.ml

Landed e.ml.recurrent (LSTM/GRU steps and forwards) and e.ml.gnn (GCN/GAT/MPNN layers) as surface:source modules with module-apis.md fences, modules.json entries, and link fixtures ml_recurrent/ml_gnn wired into run.ps1 and run.sh; both fixtures emit with the self-hosted compiler and exit 0 against hand-computed references, and check_module_surfaces.py passes. The catalog entry is 2259.

### L010 — Chemical similarity and scaffold core in e.ml

Landed e.ml.fingerprint (Morgan/path fingerprints, Tanimoto/Dice scoring, Taylor-Butina clustering, bounded McGregor FMCS) as a surface:source module with module-apis.md fence, modules.json entry, and link fixture ml_fingerprint wired into run.ps1 and run.sh; the fixture emits with the self-hosted compiler and exits 0 against hand-computed references, and check_module_surfaces.py passes. The catalog entry is 2260.

### L011 — Chemometric extensions in e.ml (PLS regression, UMAP)

Landed pls/pls_solve in e.ml.linear (NIPALS PLS1, house-style coefficients) and umap/umap_sigma/umap_affinity in e.ml.reduce (exact neighbourhoods, smooth-kNN fuzzy affinities, PCA start, cross-entropy SGD with PCG negatives; e.ml.reduce gains an e.algo.rand dependency), with catalogue fence amendments, modules.json update, and link fixture ml_chemometric wired into run.ps1 and run.sh; the fixture emits with the self-hosted compiler and exits 0 (NIPALS coefficients, PCA start, group separation, degenerate cases), and check_module_surfaces.py passes. The catalog entry is 2261.

### L012 — Longitudinal and mixed-model core in e.algo.stat

Landed e.algo.stat.mixed (Gaussian GEE with independence/exchangeable/AR(1) working correlations and robust sandwich, MMRM-UN by log-Cholesky REML with GLS at the optimum, random-intercept LMM by two-parameter REML with BLUPs, plus Wald/contrast/Cholesky helpers) as a surface:source module with module-apis.md fence, modules.json entry, and link fixture ml_mixed wired into run.ps1 and run.sh; the fixture emits with the self-hosted compiler and exits 0 against statsmodels GEE/MixedLM and an independent REML implementation (Pearson ML scale matched), and check_module_surfaces.py passes. The catalog entry is 2262.

### L013 — Time-to-event trial extensions in e.algo.stat

Landed e.algo.stat.survival_trial (Kaplan-Meier, unweighted log-rank, Cox PH by Newton-Raphson with Breslow ties, Lan-DeMets OBrien-Fleming/Pocock spending, Simon optimal/minimax designs by exact exhaustive search with documented tie-breaks, likelihood CRM by golden section, Farrington-Manning with closed bisection MLEs) as a surface:source module with module-apis.md fence, modules.json entry, and link fixture algo_survival_trial wired into run.ps1 and run.sh; the fixture emits with the self-hosted compiler and exits 0 against hand-computed and independently cross-checked references (Simon optimality verified by a second exhaustive implementation plus Monte Carlo), and check_module_surfaces.py passes. The catalog entry is 2263.

### L014 — Causal and missing-data core in e.algo.stat

Landed e.algo.stat.causal (propensity scores by Newton, Hajek IPTW with known-weights sandwich, doubly robust AIPW over caller outcome predictions, Bayesian MICE chained equations with Rubins pooling behind a generic driver) as a surface:source module with module-apis.md fence, modules.json entry, and link fixture algo_causal wired into run.ps1 and run.sh; the fixture emits with the self-hosted compiler and exits 0 against numpy references (including Neper-OLS composition and MICE determinism plus between-imputation variation checks), and check_module_surfaces.py passes. The catalog entry is 2264.

### C091 — M3-03: CPU backend, workgroup-by-workgroup launch with barrier loop-fission

A launch on `.Cpu` runs the whole grid on the calling thread, workgroups in workgroup-id order and invocations in local-id order, the grid rounded up to whole workgroups, with `gpu.gid`, `gpu.lid` and `gpu.wgid` set before each step (D778). The kernel's CPU build is a resumable step (D780): every local lives in a frame of the invocation's own (`Stack` emits each frame address with its offset, then lowering hoists those addresses into the entry block), the body is cut at every `gpu.barrier()` into a store of the barrier's number, a return and a resume block the entry's dispatch branches to by `pc`; `launch_run` in `e.gpu` schedules a workgroup round by round until every invocation returned, and an invocation that returned before a barrier its peers reached, or reached another one, traps as `barrier` naming both (`link/gpu_barrier`, `link/gpu_divergence`). A kernel's `shared var`s are one block per launch handed to every step, 0xCD-filled per workgroup (D781). Runtime-bound and slice-collection `for` loops retain their loop-invariant bound and data pointer in the invocation frame across cuts (D1743; `link/gpu_barrier`, CPU and Vulkan on Windows and WSL). Scratch frames and shared storage return to the device arena after each CPU launch, including the sort and attention launchers (D1744; `link/gpu_barrier` checks the arena mark, `link/gpu_gaps` passes on Windows and WSL). CPU frame addresses are emitted per allocation and hoisted into the entry before verification, removing the 256-allocation table; `link/gpu_barrier` retains a 640-element `u32` array (2.5 KB), its last element and a following local across a barrier on CPU and Vulkan, while `link/gpu_frame_many` retains 300 distinct allocations across one barrier on Windows and WSL (D1745-D1746, D1750-D1751). `neper run --subgroup-width` selects 8, 16, 32, or 64 CPU lanes; the default stays 32. `link/gpu_subgroup_width` checks integer and float collectives, lane IDs, broadcast and a partial final subgroup at all four widths on Windows and WSL (D1747). `link/gpu_barrier_occurrence` now traps when lanes reach the same static barrier in different `while` or `for` iterations; nested uniform loops pass on Windows and WSL (D1748). The stage-one C bootstrap builds and runs the selected width on both hosts (D1749). A direct device-only barrier helper is copied into the CPU kernel's resumable step in debug and release, retaining parameters and locals across the cut; the same helper remains a SPIR-V barrier on Vulkan. `link/gpu_barrier_helper` passes on Windows and WSL (D1752). Large direct helpers now spill only oversized value/block inline maps to the build arena; `link/gpu_barrier_large_helper` with 70 conditionals passes in debug and release on Windows and WSL (D1753). Five-helper barrier chains now run in debug and release on Windows and WSL, including nested helper loops, a scalar result and an unused recursive helper; a mismatched helper-loop occurrence traps on both hosts (D1754; `link/gpu_barrier_chain`, `link/gpu_barrier_helper_occurrence`). Consecutive self-hosted compiler stages are byte-identical. Pending indexed-store addresses and binary left operands now survive a barrier-bearing helper call without changing evaluation order (D1755; `link/gpu_barrier_chain`, debug and release on Windows and WSL). Earlier call arguments (including an aggregate address) and computed indexed-field bases now survive barrier-bearing later expressions in debug and release on Windows and WSL (D1756; `link/gpu_barrier_chain`). The direct helper still runs on CPU and available Vulkan devices on both hosts; five repeated Windows self-builds passed and consecutive compiler stages are byte-identical. Compound assignments now retain both their old value and indexed address across a barrier-bearing right side (D1757; `link/gpu_barrier_chain`, debug and release on Windows and WSL). Sequential self-hosted compiler stages are byte-identical on both hosts. A reached generic barrier helper now runs within the CPU resumable step in debug and release on Windows and WSL; a host call to that generic is refused and sequential self-hosted compiler stages are byte-identical (D1758; `link/gpu_barrier_chain`, `check/gpu_generic_device_only`). The C bootstrap now accepts the 161st `Checker` field and `dispatch`'s locals, and frame-temporary errors propagate without tuple-return `try`; both suites build their self-hosted compilers and pass 226 surface checks, then stop at the shared tree's stale library-fixture manifest (D1759). One aggregate-return barrier helper, including a concrete generic instance returning an aggregate, now uses its caller-owned result slot within the CPU step in debug and release on Windows and WSL; ordinary aggregate-return fixtures pass, Windows C bootstrap builds, and self-hosted stages are byte-identical (D1760; `link/gpu_barrier_chain`, `link/advanced`, `link/by_value_snapshot`). The bootstrap local table is reduced from 272 to the measured minimum 265; Linux C bootstrap assembly hit ENOMEM under this WSL host's 4.9 GB limit, while the existing Linux self-hosted compiler built and ran the change. Two-register multi-result barrier helpers with one or several returns, a concrete generic two-result instance, and a three-result hidden-slot helper now run within the CPU step in debug and release on Windows and WSL; ordinary multi-result calls remain correct, both C bootstraps build the compiler after trimming each function's local table to its actual use, and consecutive self-hosted stages are byte-identical (D1761; `link/gpu_barrier_chain`, `link/by_value_snapshot`). The GPU profile forbids indirect calls on both backends; an unresolved function-pointer field call now fails in the device reachability walk with its helper chain. The focused diagnostic passes on Windows and WSL, and C-bootstrap and self-hosted compiler builds are byte-identical on both hosts (D1762; `check/gpu_profile_indirect`). Earlier scalar and aggregate results in a multi-value `ret` now survive a barrier-bearing later result, including two later cuts. The barrier-chain fixture passes in debug and release on Windows and WSL; ordinary multi-result returns pass, both C bootstraps build and run the changed compiler, and bootstrapped and self-hosted builds are byte-identical (D1763; `link/gpu_barrier_chain`, `link/by_value_snapshot`). Slice data pointers, lengths, implicit bounds and earlier explicit lower bounds now survive barrier-bearing later bounds without changing evaluation order. Lower-only, upper-only and two-bound forms pass in debug and release on Windows and WSL; ordinary slices pass, both C bootstraps build the compiler, and bootstrapped and self-hosted stages are byte-identical (D1764; `link/gpu_barrier_chain`, `link/mem_slices`). Return values now survive deferred barrier calls in the CPU step, including scalar and two-register returns; hidden-slot aggregate returns retain their pre-defer copy. The barrier-chain fixture passes in debug and release on Windows and WSL, `link/try_positions` passes, both C bootstraps build the compiler, and next-stage self-hosted binaries match; three further sequential Windows self-builds passed after two intermittent access violations (D1765). Deferred call arguments in a CPU kernel step now retain their declaration-time values across later barriers, including a captured slice, index and computed scalar after the source variable changes. The barrier-chain fixture passes in debug and release on Windows and WSL; `link/try_positions` passes, and bootstrapped, self-hosted and next compiler stages are byte-identical on both hosts (D1766). Intermittent Windows self-build access violations required retries. Computed vector addresses now survive a barrier-bearing right operand; short-circuit right operands also pass (D1767; `link/gpu_barrier_chain`, debug and release on Windows and WSL). Self-hosted stages are byte-identical on both hosts; Vulkan SAXPY passes on two Windows devices and one WSL device; emitted SPIR-V matches the pinned corpus on both hosts. A runtime `for` range now retains its computed start across a barrier-bearing end expression (D1768; `link/gpu_barrier_chain`, debug and release on Windows and WSL); next-stage self-hosted compiler hashes match on both hosts and Windows SAXPY SPIR-V remains pinned. The committed library-fixture manifest and Windows suite parser were corrected after C091 fixture additions (D1769). Checked device unsigned addition now uses the remaining-range condition instead of a wrapped-result comparison (D1770); `link/gpu_tensor`, `link/gpu_vulkan_loop`, and `link/gpu_fault_bounds` pass on both Windows Vulkan devices, and all five changed pinned SPIR-V modules validate for Vulkan 1.2. In an isolated worktree, the Windows self-host suite passed 226 exact surfaces, the 123-module manifest, bootstrap lint, library fixtures, pinned SPIR-V, and the tensor fixture, then exposed `link/gpu_spaces`: a shared pointer saved in a private local left its Vulkan module empty. SPIR-V now stores that workgroup byte offset (D1771); the unchanged fixture passes on CPU and both Windows Vulkan devices, while Linux emits valid SPIR-V and reports `gpu spaces ok`. The cache-recovery gate now checks replacement and failed-rebuild preservation without requiring an opaque driver blob to reproduce byte-for-byte (D1772). Subsequent isolated Windows full-suite attempts passed the GPU fixtures and reached whole-tree transformation gates, then stopped under host disk and commit pressure with intermittent `e.fs` or OS failures and compiler self-build arena exhaustion; a focused `e.fs` retry passed. Multi-target assignment addresses now survive a barrier-bearing right-side call in ordinary and `try` paths (D1773); `link/gpu_barrier_chain` fails the old compiler's NIR verifier and passes in debug and release on Windows and Linux with the new compiler, while `link/try_positions` passes on Linux. An isolated Windows self-host suite now passes end-to-end after the cache-recovery gate starts with a fresh directory (D1774). Fresh-cache corruption, replacement and injected-failure probes pass on two Windows devices and one Linux device; the Linux suite gate no longer demands byte-identical opaque driver blobs. An earlier multi-target destination address now also survives a barrier inside a later destination's index expression, with the same saved slot reused across the right-side call (D1775). The extended `link/gpu_barrier_chain` fails the previous compiler's NIR verifier and passes in debug and release on Windows and Linux; `link/try_positions` passes, and consecutive self-hosted compiler stages match byte-for-byte on both hosts. With source and regression fixture byte-identical to the landed files, the isolated Windows self-host suite passed end-to-end, including the 226-source-surface gate, Vulkan runtime, static gate, metamorphic transforms and final self-build. The D:-hosted Linux full suite reached its C bootstrap but WSL restarted while building the compiler; a separate retry at the documented 400 MB arena minimum also restarted WSL without producing an artifact. The barrier-chain fixture now also exercises a barrier-bearing `while` condition across two iterations and barrier-bearing helpers in both runtime `for` bounds (D1776); it passes in debug and release on Windows and Linux without another lowering change. A protocol `for` now retains a computed iterator field address across a body barrier by saving it in the invocation frame and reloading in the condition block (D1777); `link/gpu_barrier_chain` passes in debug and release on Windows and Linux, consecutive Linux self-hosted compiler stages are byte-identical, and the isolated Windows self-host suite passes end-to-end with the patched compiler and protocol regression. The implicit `next` method's barrier is now discovered through protocol dispatch recording and inlined into the CPU kernel step (D1779). The previous compiler emits `link/gpu_barrier_chain` but its executable traps on a native barrier-helper call; the new compiler runs it in debug and release on Windows and Linux. Ten other GPU fixtures pass on Windows and six on Linux, and consecutive self-hosted compiler stages match byte-for-byte on both hosts. Aggregate literal fields and a switch subject also retain their barrier-bearing regressions (D1778). An array literal now tests an earlier element surviving a barrier-bearing later element (D1780); `link/gpu_barrier_chain` passes in debug and release on Windows and Linux. The iterator-discovery scratch slice is C-bootstrap-compatible: Windows C bootstrap builds the compiler at a 512 MB arena, and that compiler builds the next self-hosted stage. A clean Linux full-suite attempt and separate 512 MB Linux C-bootstrap attempt both restarted WSL during the C-bootstrap build, so neither establishes a suite pass. `check-file` now runs implicit iterator device reachability after body checks (D1781): `check/gpu_profile_implicit_next` rejects a hidden module-scope variable on Windows and Linux with the same E-GPU diagnostic as executable emission. The valid profile and CPU barrier-chain checks pass, Windows C bootstrap builds at a 640 MB arena, and consecutive self-hosted stages match byte-for-byte on both hosts. Full suites remain unverified on this host. A uniform loop now tests a deferred barrier at its normal edge, `continue`, and `break` (D1782); `link/gpu_barrier_chain` passes in debug and release on Windows and Linux without another lowering change. A separate Vulkan protocol-iterator probe returns `e.gpu.Unsupported` with or without a barrier in `next`, while a plain Vulkan kernel from the same source path runs; this is not claimed as CPU loop-fission support. Protocol `next` now also calls a nested barrier helper (D1783); `link/gpu_barrier_chain` passes in debug and release on Windows and Linux. A pure wrapper calling a device-only helper remains a separate device-callability inference gap, not a CPU fission failure. The generated fixture manifest now names `algo_causal`, `algo_survival_trial`, and `ml_mixed` (D1784). After the survival-trial library fix at `afdc224b`, the canonical Windows and Linux self-host suites passed end-to-end without fixture skips, including their final compiler-image comparisons. Both passed 229 exact source surfaces, the 123-module fixture manifest, GPU CPU/barrier fixtures, 3352 stream records in 361 files, 59 differential cases, metamorphic checks, and static gates with four measures judged and none breached. Windows exercised live Vulkan devices; the full Linux run used `VK_ICD_FILENAMES=/dev/null` because this WSL host's llvmpipe run stalled, while focused Linux Vulkan evidence is recorded above. The pending-expression audit found no uncovered barrier-cut consumer (D1786): existing frame spills cover multi-child expressions, and switch cases are constant-only. C091 is complete.

### L061 — Standard statistical charts in e.gfx.chart

Foundation in `lib/e/gfx/chart.e` covers borrowed numeric columns and caller-owned scatter/line/bar/step marks, area polygons, lollipop stems and center/lower/upper error bars, plus histogram bins, sorted ECDF, R7 box plots, Gaussian density, normal Q-Q and mirrored-KDE violin. Confidence bands close ordered lower/upper columns into a caller-owned polygon; horizontal dumbbells emit paired endpoints and their connecting segments. `gfx_chart_intervals` checks geometry, scene/SVG commands, containment, ordering and capacity refusals on Windows and Linux. Cartesian `Spec` supports independent linear, log10, symmetric-log and reverse x/y scales; `ticks` emits caller-owned values/positions and `e.gfx.chart.scene` draws grid, axis and tick strokes. `nice_ticks` selects 1/2/5 linear steps and 1/2/5 log-decade candidates, with symmetric-log retaining equal transformed-space positions; `format_ticks` writes shortest-round-trip f32 labels into caller-owned storage and refuses an empty buffer without trapping. `gfx_chart_nice_ticks` checks linear/log/symmetric-log/reverse breaks, labels and refusal paths on Windows and Linux. `guide_labels` positions tick strings in caller-owned metadata, while scene text reuses `e.text.layout` and a registered TrueType font and SVG streams escaped `<text>`; `gfx_chart_labels` checks alignment, title escaping and refusals on Windows and Linux. Row-major heatmaps, Pearson correlation matrices and equal-panel facet geometry emit caller-owned cells/rectangles. `layout_with_limits` borrows optional x/y domains for shared or free facet scales, rejecting limits that exclude the data or baseline; `gfx_chart_facet` covers the geometry and refusal paths. `e.gfx.chart.svg` streams solid-colour marks, matrix tiles and guides with escaped accessible metadata and colours matching current CPU scene channel packing. `gfx_chart`, `gfx_chart_qq`, `gfx_chart_matrix`, `gfx_chart_cartesian`, `gfx_chart_scale`, `gfx_chart_facet`, `gfx_chart_intervals`, `gfx_chart_labels`, `gfx_chart_nice_ticks` and `gfx_chart_svg` check geometry, statistics, scales, scene/SVG commands and refusal paths; `examples/chart_gallery.e` rendered one hundred and seventeen inspected PNG previews and one hundred and seventeen XML-parsed SVG companions in `docs/chart-previews/`, including labeled linear, log and symmetric-log examples. Detailed registry and staged plan: `docs/charting-engine-plan.md`. Category-major `grouped_bars` and `stacked_bars` reuse per-series Bar layouts for grouped, signed-stacked and 100%-stacked rectangles; `gfx_chart_composition` checks geometry, scene/SVG commands and refusal paths on Windows and Linux. `category_ticks` supplies ordinal centers for the existing label pass and `legend_items` pairs caller-owned swatch geometry with borrowed series names; `gfx_chart_composition` checks placement, escaping, scene/SVG output and refusals on both hosts. The three bar previews now show category text and two-series legends in PNG and SVG. `frequency_polygon` reuses histogram bin counts and links their centers to a zero baseline; `rug` emits independent short x-axis strokes, retaining tied observations. `gfx_chart_distribution` checks geometry, reuse, adapters and refusals on Windows and Linux; the gallery adds two PNG/SVG pairs. `PointLine` composes scatter points and connected segments under one domain; `strip` maps numeric observations to deterministic vertical jitter, preserving ties without collision avoidance. `gfx_chart_distribution` checks their geometry, capacity refusals and scene/SVG output on Windows and Linux, and the gallery adds two more PNG/SVG pairs. `beeswarm` keeps numeric x positions and packs overlapping square marks into free vertical lanes, returning `TooLarge` if the panel is too short; its candidate scan is cubic in the worst case. `dot_plot` reuses histogram bin counts and stacks one dot per observation, also refusing vertical overflow. Both reuse the scatter scene/SVG branches, and `gfx_chart_distribution` checks geometry, capacity and adapters on Windows and Linux. The gallery adds two more PNG/SVG pairs. `e.gfx.scene.damage_of` now avoids shifting pixels beneath unchanged prefix/suffix paint; the two-frame `gfx_chart_distribution` regression fails without the guard and passes on Windows and Linux, and the gallery re-renders without stray guide ticks. `waterfall` derives floating signed steps, a closing total and level connectors from an opening amount plus changes, reusing bar and segment scene/SVG paths; `gfx_chart_composition` checks geometry, refusal paths and both adapters on Windows and Linux, and the gallery adds the thirty-fourth PNG/SVG pair. `e.gfx.chart.scene.rasterize` now returns caller-owned straight-RGBA output, releases compiled scenes on errors and composes with `e.fmt.png.encode` after arena-backed writer creation; `gfx_chart_png` checks a transparent PNG round trip on Windows and Linux, and the gallery uses this export path for all seventy-three PNGs. `bullet` composes descending qualitative-range bars, a slim actual bar and a target rule from existing Bar/Rug layers; `gfx_chart_composition` checks geometry, capacity, refusal paths and scene/SVG output on Windows and Linux, and the gallery adds the thirty-fifth PNG/SVG pair. `pareto` stably orders nonnegative category counts into frequency Bar and cumulative-fraction PointLine layers with independent y domains; `gfx_chart_composition` checks geometry, refusals and scene/SVG adapters on Windows and Linux, and the gallery adds the thirty-sixth PNG/SVG pair with labeled count and percentage axes. `pie` emits caller-owned Area polygons for nonnegative category weights, with a zero inner-radius ratio for pie and a positive ratio for donut; `gfx_chart_polar` checks geometry, invalid input, storage refusal and scene/SVG adapters on Windows and Linux. The gallery adds the thirty-seventh and thirty-eighth PNG/SVG pairs with category legends. `waffle` divides a caller-sized grid into cumulative-rounded category cells as Bar layers; `funnel` turns nonincreasing stage counts into centered trapezoid Area layers. `gfx_chart_funnel_grid` checks geometry, invalid input, caller capacity and scene/SVG adapters on Windows and Linux. The gallery adds the thirty-ninth and fortieth PNG/SVG pairs with category legends. `bubble` reuses scatter x/y scales and maps a nonnegative size column to circle area, with caller-owned circle bounds; scene cubic paths and SVG circle marks share the layout. `gfx_chart_bubble` checks area ratios, log mapping, zero-size marks, invalid inputs, caller capacity and both adapters on Windows and Linux. The gallery adds the forty-first PNG/SVG pair. A quantitative size legend and overlap policy remain. `regression_line` uses the existing streaming OLS accumulator to return a fitted Line and a domain shared with scatter; `covariance_ellipse` returns a caller-resolution data-ellipse Line at a caller-selected Mahalanobis radius, refusing singular covariance. `gfx_chart_overlays` checks exact linear references, constant-y fits, rotated and singular covariance, storage refusals and scene/SVG adapters on Windows and Linux. The gallery adds the forty-second and forty-third PNG/SVG pairs. `regression_interval` computes pointwise OLS mean-confidence and new-observation prediction ribbons from residual variance and leverage, with a caller-supplied two-sided Student-t critical value; it returns aligned Band and Line layers on a domain that also contains the observations. `gfx_chart_overlays` checks numerical references, singular/short samples, critical/storage refusals and scene/SVG adapters on Windows and Linux. The gallery adds the forty-fourth and forty-fifth PNG/SVG pairs. Simultaneous bands, automatic quantiles and nonlinear smoothers remain planned. `combo_bar_line` reuses Bar and PointLine layout at shared category centers with independent baseline-inclusive left and line right domains; `gfx_chart_composition` checks signed values, axis alignment, invalid/capacity paths and scene/SVG adapters on Windows and Linux. The gallery adds the forty-sixth PNG/SVG pair with numeric secondary-axis guides. Irregular x, more than two axes and aligned axis tables remain planned. `ridgeline` evaluates Gaussian KDE for each concatenated group on a common grid, scales heights by the global peak and emits overlapping caller-owned Area layers. `gfx_chart_ridgeline` checks numeric values, malformed groups, invalid overlap/bandwidth and storage refusals plus scene/SVG output on Windows and Linux. The gallery adds the forty-seventh PNG/SVG pair with readable x ticks and group labels. Weighted density and transformed x axes remain planned. `candlestick` and `ohlc` map strictly increasing numeric x plus validated open/high/low/close columns into caller-owned Rug and Bar layers, preserving irregular gaps and doji marks. `gfx_chart_finance` checks numeric references, malformed prices/x, capacity and scene/SVG adapters on Windows and Linux; the gallery adds the forty-eighth and forty-ninth PNG/SVG pairs. Date formatting, corporate-action adjustment and volume companions remain planned. `treemap` lays out a parent-before-child hierarchy with proportional leaf Bar rectangles and caller-owned group bounds. `gfx_chart_treemap` checks area, invalid hierarchy/weights/capacity and scene/SVG output on Windows and Linux; the gallery adds the fiftieth labeled PNG/SVG pair. Squarified packing and interactive drilldown remain planned. `sunburst` shares tree validation and subtree totals, maps ordered siblings to angular sectors and depth rings, and emits caller-owned Area polygons. `gfx_chart_sunburst` checks numeric spans, zero leaves, invalid data/storage and scene/SVG output on Windows and Linux; the gallery adds the fifty-first PNG/SVG pair. Curved labels and adaptive tessellation remain planned. `icicle` shares validated hierarchy totals, maps subtree shares into horizontal depth bands, extends shallow leaves to the bottom, and reuses Bar scene/SVG adapters. `gfx_chart_icicle` checks proportions, depth, zero leaves, invalid data/storage and both adapters on Windows and Linux; the gallery adds the fifty-second PNG/SVG pair. `circle_pack` reuses hierarchy totals to place ordered, non-overlapping sibling circles with areas proportional to subtree totals, using caller-owned bounds and Bubble scene/SVG adapters. `gfx_chart_circle_pack` checks area ratios, nested containment, separation, zero nodes, invalid data/storage and both adapters on Windows and Linux; the gallery adds the fifty-third PNG/SVG pair. Ring placement is not density-optimal. `population_pyramid` maps two aligned nonnegative age columns to opposing horizontal Bar layers with a shared maximum, central label gutter and row gaps. `gfx_chart_population_pyramid` checks reference geometry, invalid counts/gaps/storage and scene/SVG adapters on Windows and Linux; the gallery adds the fifty-fourth PNG/SVG pair. `sankey` lays out ordered forward weighted links as caller-owned smoothstep Area ribbons and Bar nodes on a shared flow scale across columns. `gfx_chart_sankey` checks two- and three-column geometry, zero links, invalid data/storage and scene/SVG adapters on Windows and Linux; the gallery adds the fifty-fifth PNG/SVG pair. Automatic crossing reduction remains planned. `alluvial` reuses Sankey ribbons for adjacent-stage links and checks conservation at every interior stratum. `gfx_chart_alluvial` checks four-stage geometry, skipped links, imbalance, capacity and scene/SVG adapters on Windows and Linux; the gallery adds the fifty-sixth PNG/SVG pair with stable caller-supplied cohort colours. Automatic crossing reduction and inferred cohort identity remain planned. `streamgraph` centers nonnegative sample-major series around a silhouette baseline at one shared vertical scale and returns caller-owned Area polygons. `gfx_chart_streamgraph` checks numeric geometry, malformed data, capacity and scene/SVG adapters on Windows and Linux; the gallery adds the fifty-seventh PNG/SVG pair. Wiggle offsets and automatic layer ordering remain planned. `chord` maps a directed square matrix to outer group arcs and caller-owned Area ribbons, preserving asymmetric pair weights and self loops. `gfx_chart_chord` checks numeric geometry, self links, zero pairs, malformed matrices, capacity and scene/SVG adapters on Windows and Linux; the gallery adds the fifty-eighth PNG/SVG pair. Adaptive curve tessellation, direction arrows and highlighting remain planned. `mekko` gives each category a width proportional to its total and each series cell a height proportional to its within-category share, so cell area encodes its fraction of the grand total. `gfx_chart_mekko` checks numeric proportions, empty/invalid tables, zero-width categories, capacity and scene/SVG adapters on Windows and Linux; the gallery adds the fifty-ninth PNG/SVG pair. `euler2` solves exact two-circle intersection area from two set totals and their overlap; `venn3` supplies seven membership anchors for a nominal, non-area-proportional three-set layout. `gfx_chart_venn_euler` checks geometric references, membership, invalid inputs, capacity and scene/SVG adapters on Windows and Linux; the gallery adds the sixtieth and sixty-first PNG/SVG pairs. Arbitrary three-set region-area fitting remains planned. `ribbon_rank` maps sample-major values into equal-height ordinal Area bands over ordered x positions, with larger values ranked first and stable input-order ties. `gfx_chart_ribbon_rank` checks reference ranks, ties, malformed inputs, capacity and scene/SVG adapters on Windows and Linux; the gallery adds the sixty-second PNG/SVG pair. Missing categories and curved crossover interpolation remain planned. `gauge` returns background and measured semicircular Area rings plus a target Rug rule at a validated positive maximum; `target_status` returns signed delta and attainment for either target direction. `gfx_chart_gauge` checks geometry, zero/full values, malformed inputs, capacity, status rules and scene/SVG adapters on Windows and Linux. A KPI card composes existing bullet layers with this status; the gallery adds the sixty-third and sixty-fourth PNG/SVG pairs. Dynamic labels, threshold bands and widget binding remain planned. `word_cloud` maps pre-tokenized unique weighted words to legible sizes, honors exact-match exclusions and packs measured text boxes by deterministic spiral placement with collision and bounds checks. `gfx_chart_word_cloud` verifies weight order, exclusions, refusals and scene/SVG text on Windows and Linux; the gallery adds the sixty-fifth PNG/SVG pair. Tokenization, case normalization, font embedding and scalable packing remain planned. `state_timeline` maps ordered f64 half-open intervals into row-aligned Bar layers, coalesces exact abutting equal states and leaves gaps blank. `gfx_chart_state_timeline` checks large timestamps, ordering, overlap, gaps, invalid state/domain, capacity and scene/SVG adapters on Windows and Linux; the gallery adds the sixty-sixth and sixty-seventh PNG/SVG pairs for operational state timelines and status histories. Date/time formatting, timezone semantics and event annotations remain planned. `sparkline` maps dense evenly spaced samples through existing Line layers for guide-free in-cell rows. `calendar_heatmap` maps sorted day offsets to sparse week/weekday Heatmap cells with caller gaps; missing days remain blank. `gfx_chart_calendar_sparkline` checks geometry, invalid input, short storage and scene/SVG adapters on Windows and Linux; the gallery adds the sixty-eighth and sixty-ninth PNG/SVG pairs. Calendar/date labels, locale policy, missing sparkline samples and shared in-cell scales remain planned. `event_timeline` maps sorted f64 timestamps to lane-centered Lollipop points and stems, and `in_cell_bars` maps nonnegative values against a common maximum within caller-owned cells; zero values leave the track blank. `gfx_chart_events_cellbars` checks large timestamps, geometry, ordering, invalid values and storage plus scene/SVG adapters on Windows and Linux; the gallery adds the seventieth and seventy-first PNG/SVG pairs. Event label collision, nullable report data and per-row normalization remain planned. `forest_plot` maps validated effect intervals and center estimates on linear/log/symlog scales with a separate reference rule. `e.algo.stat.agreement_limits` computes paired-difference bias and sample-SD limits at a caller-selected multiplier; `bland_altman` maps means, differences and three guides to existing Scatter/Rug layers. `gfx_chart_agreement_forest` checks numeric references, refusals and scene/SVG adapters on Windows and Linux; the gallery adds the seventy-second and seventy-third PNG/SVG pairs. Forest weighting/pooled estimates, limits confidence intervals and proportional-bias analysis remain planned. `e.algo.stat.binary_curve` groups tied scores into one threshold; `roc_auc` and `average_precision` yield checked reference values, while `e.gfx.chart.binary_metric_curve` reuses Line geometry for ROC, precision–recall, cumulative gain and lift. `gfx_chart_binary_curves` checks ties, class/storage refusals and scene/SVG output on Windows and Linux; four new PNG/SVG gallery pairs bring the total to seventy-seven. `binary_calibration` validates unit probabilities and aggregates caller-owned equal-width bins, while `binary_confusion` counts thresholded outcomes. Existing PointLine and Heatmap marks render calibration and a 2x2 confusion matrix; `gfx_chart_diagnostic_tables` checks reference values, refusals and scene/SVG output on Windows and Linux. Two more PNG/SVG pairs bring the total to seventy-nine. `roc_partial_auc` integrates to an explicit false-positive cutoff, `youden_index` selects the highest-score point maximizing sensitivity minus false-positive rate, and `decision_curve` computes model/treat-all net benefit over probability thresholds. `roc_partial_region` reuses Area geometry; Line and Rug mark the decision curves and Youden point. `gfx_chart_binary_curves` checks reference values, invalid/capacity paths and scene/SVG adapters on Windows and Linux; three more PNG/SVG pairs bring the total to eighty-two. `e.algo.stat.regression_diagnostics` computes fitted values, raw and internally standardized residuals, leverage and Cook's distance from one OLS fit, rejecting singular/exact fits and short storage. Existing Scatter and Lollipop layouts render residual/fitted, leverage/residual and Cook-by-observation previews. `gfx_chart_regression_diagnostics` checks numeric references, refusals and scene/SVG output on Windows and Linux; three more PNG/SVG pairs bring the total to eighty-five. `e.algo.stat.survival_curve` groups sorted follow-up times with tied events preceding censoring, emitting Kaplan–Meier survival, Nelson–Aalen cumulative hazard and at-risk/event/censor counts. Existing Step and Scatter marks render survival, hazard and censor markers. `gfx_chart_survival` checks reference fractions, tied and all-censored cases, invalid/storage refusals and scene/SVG output on Windows and Linux; two more PNG/SVG pairs bring the total to eighty-seven. Greenwood intervals, log-rank comparisons and competing risks remain planned. `e.algo.stat.imr_limits` computes consecutive moving ranges and three-sigma Individuals/MR limits; `xbar_r_limits` computes subgroup means, ranges and A2/D3/D4 limits for sizes 2–10. Existing PointLine and Rug marks draw the four control charts and their upper/center/lower rules. `gfx_chart_control` checks NIST numeric references, refusals and scene/SVG output on Windows and Linux; four more PNG/SVG pairs bring the total to ninety-one. `e.algo.stat.attribute_control` computes pooled p/np binomial and c/u Poisson three-sigma values and limits, with per-observation p/u limits for variable subgroup sizes and bounded p/np limits. PointLine and Rug marks render observed values and the three limit traces. `gfx_chart_attribute_control` checks numeric references, malformed sizes, clipping and scene/SVG output on Windows and Linux; four more PNG/SVG pairs bring the total to ninety-five. `xbar_s_limits` adds c4-corrected X-bar/S limits; `cusum_control` adds upper/lower tabular sums and decision signals; `ewma_control` adds startup-adjusted weighted means and limits. `gfx_chart_weighted_control` checks numeric references, invalid/capacity refusals on Windows and Linux; five more PNG/SVG pairs bring the total to one hundred. `laney_control` reuses p/u estimates and adjusts their subgroup-specific three-sigma limits with adjacent standardized-score moving ranges divided by 1.128. `gfx_chart_laney` checks overdispersion, variable sizes and invalid/capacity refusals on Windows and Linux; two more PNG/SVG pairs bring the total to one hundred and two. `g_control_limits` fits a geometric model for whole opportunities between events and interpolates percentile limits; `t_exponential_control_limits` fits positive elapsed times to an exponential model. `gfx_chart_rare_event` checks numeric references, invalid/degenerate inputs and large gaps on Windows and Linux; two more PNG/SVG pairs bring the total to one hundred and four. `control_run_rules` checks eight special-cause patterns against per-point centers/sigmas and marks each completing observation. `gfx_chart_run_rules` verifies all eight tests, strict boundaries, varying sigma and refusals on Windows and Linux; a highlighted PNG/SVG preview brings the total to one hundred and five. `imr_phase_control` computes per-phase Individuals limits without cross-boundary moving ranges; `control_run_rules_phased` resets all eight test windows at boundaries. `gfx_chart_phases` checks phase values and reset/refusal paths on Windows and Linux; a phased Individuals PNG/SVG preview brings the total to one hundred and six. `attribute_control_phased` re-estimates P/Np/C/U limits per phase while retaining subgroup-specific P/U limits; `gfx_chart_attribute_phases` checks all four against independent phases and refusal paths on Windows and Linux. Four new phase-split PNG/SVG previews bring the total to one hundred and ten. `laney_control_phased` fits phase-specific P-prime/U-prime centers and Sigma Z without cross-boundary ranges; `gfx_chart_laney_phases` checks independent phase estimates and refusals on Windows and Linux. Two phase-split PNG/SVG previews bring the total to one hundred and twelve. `subgroup_control_phased` re-estimates X-bar/R or X-bar/S limits per phase using the existing equal-subgroup calculators; `gfx_chart_subgroup_phases` checks both modes against independent phases and refusal paths on Windows and Linux. Four phase-split PNG/SVG previews bring the total to one hundred and sixteen. `parallel_coordinates` maps row-major observations across independently normalized axes into caller-owned segments; `gfx_chart_parallel_coordinates` checks constant axes, invalid/capacity refusals and scene/SVG output on Windows and Linux. One labeled PNG/SVG pair brings the total to one hundred and seventeen. `pp_normal` compares empirical midpoint ranks with a caller-specified normal CDF and identity reference; `gfx_chart_qq` checks numeric positions, invalid inputs, capacities and scene/SVG output on Windows and Linux. One new PNG/SVG pair brings the total to one hundred and eighteen. `scatterplot_matrix` composes per-variable ranges with off-diagonal Scatter facets and caller-labeled diagonal panels; `gfx_chart_parallel_coordinates` checks constant columns, malformed input, capacity refusals and scene/SVG output on Windows and Linux. One new labeled PNG/SVG pair brings the total to one hundred and nineteen. `boxen_plot` emits nested R7 letter-value boxes, a median rule and tail points through existing Box marks; `gfx_chart_qq` checks exact quartile geometry, depth and storage refusals, plus scene/SVG output on Windows and Linux. One new PNG/SVG pair brings the total to one hundred and twenty. `mosaic` maps contingency counts to area-proportional cells and Pearson residual colours, with zero cells omitted and caller-owned gutters; `gfx_chart_mekko` checks numeric residuals, geometry, capacity and invalid-input refusals, plus scene/SVG output on Windows and Linux. One labeled PNG/SVG pair brings the total to one hundred and twenty-one. `association` maps contingency counts to signed Pearson-residual rectangles with square-root expected widths and row baselines, preserving area proportional to observed-minus-expected counts; `gfx_chart_mekko` checks reference residuals, geometry, independence, invalid/capacity paths and scene/SVG output on Windows and Linux. One PNG/SVG pair brings the total to one hundred and twenty-two. `fourfold` standardizes one 2x2 table to equal margins while preserving the odds ratio, emits area-proportional quarter-circle polygons and optional Wald confidence arcs with zero-cell correction; `gfx_chart_mekko` checks reference odds ratio, interval, radii, invalid/capacity paths and scene/SVG output on Windows and Linux. One PNG/SVG pair brings the total to one hundred and twenty-three. Multi-stratum auto layout, alternate standardizations and multiplicity adjustment remain planned. `horizon` folds signed series into threshold-split positive/negative Area patches with explicit origin and band width; `gfx_chart_horizon` checks crossing geometry, irregular x spacing, invalid/capacity refusals and scene/SVG output on Windows and Linux. One PNG/SVG pair brings the total to one hundred and twenty-four. Automatic origin/scale selection, missing-data gaps and grouped multi-series layout remain planned. `seasonal_subseries` groups consecutive cycles into Line subseries and arithmetic-mean Rug rules; `gfx_chart_seasonal` checks exact positions, means, partial cycles, flat data, invalid/capacity refusals and scene/SVG output on Windows and Linux. One PNG/SVG pair brings the total to one hundred and twenty-five. Explicit phase labels/times, missing gaps and alternative reference statistics remain planned. `fan` maps nested forecast intervals and their median through one shared domain, reusing Band and Line adapters; `gfx_chart_fan` checks irregular x, nesting, flat distributions, capacity refusals and scene/SVG output on Windows and Linux. One PNG/SVG pair brings the total to one hundred and twenty-six. Quantile estimation from simulations, coverage labels and observed-history anchoring remain planned. `decomposition` computes classical additive centered-MA trend, phase-mean seasonal values and remainder, with aligned four-panel Line output; `gfx_chart_decomposition` checks odd/even numeric references, flat data, invalid/capacity refusals and scene/SVG output on Windows and Linux. One PNG/SVG pair brings the total to one hundred and twenty-seven. Multiplicative/STL decomposition, missing observations and date labels remain planned. `correlogram` computes lag-zero-normalized ACF and Durbin-Levinson PACF in paired Rug panels with zero and approximate 95% guides; `gfx_chart_correlogram` checks exact numeric references, geometry, refusals and scene/SVG adapters on Windows and Linux. One PNG/SVG pair brings the total to one hundred and twenty-eight. Missing-data handling, alternative confidence intervals and FFT acceleration remain planned. `variogram` bins 2D Euclidean site pairs into classical half-mean-squared semivariances, returning pair counts and mean distances alongside Scatter marks; `gfx_chart_variogram` checks numeric references, vertical pairs, empty/capacity refusals and scene/SVG adapters on Windows and Linux. One PNG/SVG pair brings the total to one hundred and twenty-nine. Directional/robust estimators and model fitting remain planned. `radar` normalizes per-axis ranges into filled polygons with caller-owned spoke/ring guides; `rose` maps pre-binned directional weights to equal-angle sectors with area-proportional square-root radii. `gfx_chart_radial` checks coordinates, area ratios, refusals and scene/SVG adapters on Windows and Linux. Two PNG/SVG pairs bring the total to one hundred and thirty-one. Raw-angle binning and polar axis interaction remain planned. `ternary` closes three nonnegative parts to unit sum and projects them into a fixed-aspect simplex with caller-owned parallel grid guides; `gfx_chart_ternary` checks corners, normalized mixtures, invalid/storage refusals and scene/SVG adapters on Windows and Linux. One PNG/SVG pair brings the total to one hundred and thirty-two. Ternary density and contour overlays remain planned. `quiver` locates vector tails through Cartesian scales and adds explicitly pixel-scaled shafts and arrowheads as Rug segments, omitting zero-length arrows; `gfx_chart_quiver` checks geometry, signed/zero vectors, invalid and capacity refusals, and scene/SVG adapters on Windows and Linux. One PNG/SVG pair brings the total to one hundred and thirty-three. Magnitude-colour legends remain planned. `streamlines` bilinearly samples regular row-major vector grids and advances caller seeds by fixed-distance midpoint steps, clips paths to domain edges and returns independent Rug strokes. `gfx_chart_streamlines` checks uniform, varying and stationary fields, edge clipping, invalid/storage refusals and scene/SVG output on Windows and Linux. One PNG/SVG pair brings the total to one hundred and thirty-four. Bidirectional integration, adaptive error control and occupancy suppression remain planned. `phase_space` maps scalar values and explicit lag into a square equal-scale PointLine orbit; `recurrence` thresholds pairwise Euclidean distances among those two-dimensional states into a symmetric binary Heatmap. `gfx_chart_phase_space` and `gfx_chart_recurrence` check reference coordinates and recurrence cells, constant/repeated series, invalid/capacity refusals, and scene/SVG output on Windows and Linux. Two PNG/SVG pairs bring the total to one hundred and thirty-six. Higher-dimensional embeddings, recurrence quantification and threshold selection remain planned. `drawdown` reuses Area layout for fractional losses from the running price peak; `cohort_retention` maps compact triangular counts to per-cohort fractions and sparse Heatmap tiles. `gfx_chart_drawdown` and `gfx_chart_cohort_retention` check values, invalid inputs and capacity refusals, plus scene/SVG adapters on Windows and Linux. Two more PNG/SVG pairs bring the total to one hundred and thirty-eight. Return/volatility companions and cohort labels/legend automation remain planned. `contour` interpolates ordered scalar-grid levels into Rug isolines with a centre-decided saddle rule; `filled_contour` clips two triangles per grid cell into Area bands. Per-band scene/SVG paths eliminate shared-edge seams. `gfx_chart_contour` and `gfx_chart_filled_contour` check geometry, area conservation, invalid/capacity refusals and both adapters on Windows and Linux. Two PNG/SVG pairs bring the total to one hundred and forty. Missing-value masks, polygon merging, contour labels and irregular grids remain planned. `price_volume` aligns a closing-price Line and nonnegative volume Bars on one padded numeric x domain; `returns_volatility` computes simple per-observation price returns and trailing sample SD in two panels on a shared x domain. `gfx_chart_price_volume` and `gfx_chart_returns_volatility` check numeric references, alignment, flat series, invalid inputs/capacities and scene/SVG output on Windows and Linux. `gantt` maps ordered task intervals and completion fractions into paired Bar layers on an explicit numeric time domain and categorical rows. `gfx_chart_gantt` checks geometry, invalid domains/rows/fractions, capacity and scene/SVG adapters on Windows and Linux. `milestone_roadmap` reuses validated event positions and maps each to a diamond Area layer. `gfx_chart_milestone_roadmap` checks reference geometry, ordering/row/size/capacity refusals and scene/SVG output on Windows and Linux. `burndown` and `burnup` reuse shared Line domains for actual/ideal remaining work and completed/scope traces. `gfx_chart_burn` checks irregular x values, reference calculations, flat series, invalid inputs/capacities and scene/SVG output on Windows and Linux. `earned_value` aligns PV/EV/AC on one value domain while planned value extends beyond the measured prefix. `gfx_chart_earned_value` checks partial-horizon numeric positions, flat data, invalid inputs/capacity and scene/SVG adapters on Windows and Linux. `risk_matrix` bins likelihood/impact observations over caller-supplied ratings, returns per-cell counts, and reuses heatmap scene/SVG output; `gfx_chart_risk_matrix` checks orientation, repeated risks, refusals and both adapters on Windows and Linux. `resource_histogram` preserves concurrent unit peaks at assignment boundaries, splits normal/excess bars at capacity and reuses Rug guides; `gfx_chart_resource_histogram` checks exact loads, gaps, refusals and scene/SVG output on Windows and Linux. `swimlane` maps role-lane steps and forward links into caller-owned Bar and directional Rug geometry; `gfx_chart_swimlane` checks cross-lane/same-lane handoffs, refusals and both adapters on Windows and Linux. `kanban` lays caller-ordered cards into workflow columns with per-column counts and WIP-limit breach status; `gfx_chart_kanban` checks placement, policy reporting, refusals and scene/SVG output on Windows and Linux. Thirty-eight new PNG/SVG pairs bring the total to one hundred and eighty. `chart.cause_effect_tree` places an effect-rooted, right-to-left candidate-cause hierarchy with leaf-proportional spans in caller-owned box, connector and label storage; `gfx_chart_cause_effect_tree` checks unequal subtrees, geometry, scene/SVG escaping and refusal paths on Windows and Linux. AND/OR fault logic and measured label fitting remain planned. `chart.fishbone` lays out a right-facing effect, alternating category ribs, direct causes and nested earlier-parent subcauses in caller-owned marks and labels; `gfx_chart_fishbone` checks deterministic geometry, three-level parent linkage, scene/SVG escaping and refusal paths on Windows and Linux. Measured-label collision avoidance remains planned. `normal_capability_individuals` and `capability_sixpack` compose I/MR, last-25, histogram with within/overall fits, normal Q-Q and three tolerance intervals with Cp/Cpk/Pp/Ppk; `gfx_chart_capability_sixpack` checks reference calculations, six-panel geometry, scene/SVG and refusal paths on Windows and Linux. Subgroup, nonnormal and confidence-bound variants remain planned. `pert_cpm_schedule` computes three-point expected duration and variance, earliest/latest times, slack and critical tasks from a validated dependency DAG; `pert_cpm_network` emits staged Bar nodes and directional Rug links with critical-edge flags. `gfx_chart_pert_cpm` checks numeric references, cycles, invalid estimates, storage refusals and scene/SVG output on Windows and Linux. The gallery adds the PERT/CPM PNG/SVG pair. Working calendars, lead/lag constraints, resource levelling and project-duration uncertainty remain planned. `value_stream_map` computes process, value-added and queue totals, lead time, process-cycle efficiency and rolled yield while emitting stage boxes, directional links and a proportional time ladder. `gfx_chart_value_stream` checks numeric references, geometry, single-stage behavior, invalid/capacity refusals and scene/SVG output on Windows and Linux. The gallery adds a value-stream PNG/SVG pair. Branching flows, inventory/transport symbols, takt/capacity constraints and future-state comparison remain planned. `sipoc` lays out ordered supplier/input/process/output/customer columns, caller-owned entries, header connectors and per-column counts, refusing invalid or cramped geometry. `gfx_chart_sipoc` checks interleaved entry order, sparse columns, capacity/invalid cases and scene/SVG output on Windows and Linux. The gallery adds a SIPOC PNG/SVG pair. Decision, handoff and execution semantics remain separate diagram work. `decision_tree_values` evaluates a validated rooted choice/chance/outcome tree with probability-weighted and maximum-child expectations; `decision_tree_layout` emits leaf-interval Bar nodes and chosen-edge Rug connectors. `gfx_chart_decision_tree` checks references, malformed trees, capacity and scene/SVG output on Windows and Linux. The gallery adds a decision-tree PNG/SVG pair. Influence diagrams, utility preferences and DAG decision networks remain planned. `org_chart` lays out a validated single-root reporting hierarchy into leaf-weighted Bar nodes and orthogonal Rug connectors. `gfx_chart_org_chart` checks placement, malformed trees, storage refusals and scene/SVG output on Windows and Linux. The gallery adds an org-chart PNG/SVG pair. Multiple roots, dotted-line relationships and collapse remain planned. `dependency_graph` validates a general DAG, layers nodes by longest path and emits caller-owned Bar boxes and directional Rug connectors. `gfx_chart_dependency_graph` checks merges, splits, disconnected nodes, malformed graphs, capacity and scene/SVG adapters on Windows and Linux. The gallery adds a dependency-graph PNG/SVG pair. Crossing reduction, port selection and editing remain planned. `flowchart` emits caller-owned terminal and decision polygons, process rectangles and orthogonal arrows from explicitly placed nodes and opposing ports; cycles are permitted. `gfx_chart_flowchart` checks geometry, refusals and scene/SVG on Windows and Linux. The gallery adds a flowchart PNG/SVG pair. Automatic placement, crossing avoidance and mixed-axis ports remain planned. `state_machine_step` advances only on a unique state/event transition; `state_machine` emits caller-owned state polygons, arrowed transitions, event labels, initial and final markers and self-loops. `gfx_chart_state_machine` checks behavior, malformed graphs, capacity and scene/SVG adapters on Windows and Linux. The gallery adds a state-machine PNG/SVG pair. Hierarchical/concurrent states and automatic placement remain planned. `sequence_diagram` emits caller-owned participant headers, dashed lifelines, activation bars, ordered calls, dashed returns, self-calls and message labels. `gfx_chart_sequence_diagram` checks ordering, direction, invalid spans/capacity and scene/SVG adapters on Windows and Linux. The gallery adds a sequence-diagram PNG/SVG pair. Automatic call-stack inference, fragments and destruction markers remain planned. `entity_relationship` emits caller-owned table/header boxes, PK/FK field tags, relationship labels and crow's-foot one/optional/many endpoints. `gfx_chart_entity_relationship` checks interleaved fields, optional/reverse links, malformed geometry, capacity and scene/SVG on Windows and Linux. The gallery adds an ER-diagram PNG/SVG pair. Automatic placement, vertical routing and collision-safe labels remain planned. `branching_process_map` validates rooted split/merge DAGs, conserves per-stage branch fractions and computes yield-aware terminal output and arrival-weighted expected processing time. `gfx_chart_branching_process` checks numeric references, malformed flows, storage and scene/SVG on Windows and Linux. The gallery adds a branching-process PNG/SVG pair. Rework loops, calendars and stochastic distributions remain planned. `stem_and_leaf` rounds sorted values to an explicit leaf unit, groups signed stems and retains duplicate digits in caller-owned rows and leaves. `gfx_chart_stem_and_leaf` checks negative and decimal grouping, repeated values, refusals and scene/SVG on Windows and Linux. The gallery adds a stem-and-leaf PNG/SVG pair. Automatic unit selection, split stems and label collision handling remain planned. `range_intervals` maps low-to-high values onto explicit shared numeric limits and categorical rows, returning caller-owned floating bars and separate endpoint caps. `gfx_chart_range_interval` checks exact geometry, invalid domains and intervals, capacities and scene/SVG on Windows and Linux. The gallery adds a range-interval PNG/SVG pair. Zero-length points, open endpoints, overlap dodging and automatic domain selection remain planned. `probability_plot` maps ordered samples onto normal or exponential probability paper with nonlinear percent ticks, an explicit fitted reference and separate Scatter/Line layers. `gfx_chart_probability_plot` checks ties, numeric reference positions, nonuniform exponential ticks, clipping, refusals and scene/SVG on Windows and Linux. The gallery adds a labeled probability-plot PNG/SVG pair. Automatic fitting, confidence envelopes and more families remain planned. `spine_plot` maps a column-major contingency table to marginal-width columns and conditional-height outcome stacks, emitting caller-owned category Bar layers and totals; with zero gutter, each cell area equals its count share. `gfx_chart_spine_plot` checks numeric areas, zero cells, refusals and scene/SVG on Windows and Linux. The gallery adds a spine-plot PNG/SVG pair. Automatic empty-column omission remains planned. `hexbin` assigns bounded x/y observations, including panel-edge values, to the nearest pointy-top hexagonal cell; caller-owned counts and six-vertex Area polygons reuse scene/SVG adapters. `gfx_chart_hexbin` checks count conservation, corners, geometry, adapters and refusal paths on Windows and Linux. The gallery adds a hexbin PNG/SVG pair; adaptive and weighted bins remain planned. `bin2d` counts bounded x/y observations into caller-owned rectangular cells with exact u64 counts and heatmap-compatible layout. `gfx_chart_bin2d` checks count conservation, corners, midpoint assignment, geometry, scene/SVG adapters and refusal paths on Windows and Linux. The gallery adds a bin2d PNG/SVG pair; automatic bin sizing, weights and density smoothing remain planned. `e.algo.stat.kde2d` evaluates normalized product-Gaussian density on caller-owned axes; `chart.density2d` contours its grid at peak-relative levels. `gfx_chart_density2d` checks numeric Gaussian references, contour geometry, scene/SVG adapters and refusal paths on Windows and Linux. The gallery adds a density2d PNG/SVG pair; automatic bandwidths, weights and probability-mass levels remain planned. `half_violin` emits a caller-selected one-sided KDE polygon; `raincloud` combines that polygon with all raw observations and an R7 Tukey box/whisker summary on the same value axis. `gfx_chart_half_violin` and `gfx_chart_raincloud` check symmetry, quartiles, outlier visibility, scene/SVG adapters and refusal paths on Windows and Linux. Two PNG/SVG pairs join the gallery; collision-free raw-point packing remains planned. `slopegraph` maps paired values to fixed before/after x positions under a common y domain, preserving each series through crossings and exposing endpoints for labels. `gfx_chart_slopegraph` checks crossings, constant domains, adapters and refusals on Windows and Linux; one PNG/SVG pair joins the gallery. Automatic label collision avoidance remains planned. `connected_scatter` reuses ordered PointLine geometry without sorting x; `marginal_histogram` composes aligned scatter, exact x-bin and rotated y-bin layouts with caller-owned counts. `gfx_chart_connected_scatter` and `gfx_chart_marginal_histogram` check path order, exact frequencies, shared domains, scene/SVG adapters and refusal paths on Windows and Linux. Two PNG/SVG pairs join the gallery; automatic sequence-label and multi-panel placement remain planned. `e.algo.stat.log_logistic4` evaluates a caller-supplied LL.4 mean without fitting, and `chart.dose_response` aligns observed values and model on a log-dose axis. `e.algo.stat.interval_hazard` computes event/person-time rates from right-censored follow-up in explicit right-closed intervals, and `chart.hazard_rate` draws those rates as a step curve. `gfx_chart_dose_response` and `gfx_chart_hazard_rate` check numeric references, boundary assignment, adapters and refusals on Windows and Linux. Two PNG/SVG pairs join the gallery; fitting, uncertainty intervals, smoothing and delayed entry remain planned. `influence_plot` combines one-predictor OLS leverage, internally standardized residuals and area-scaled Cook's distance with separate points for zero-Cook observations and visual reference guides. `gfx_chart_influence_plot` checks numeric reference diagnostics, bubble area, guide geometry, scene/SVG adapters and refusal paths on Windows and Linux. One PNG/SVG pair joins the gallery; externally studentized residuals and automatic noteworthy labels remain planned. `docs/chart-preview-backlog.txt` now makes unrendered individual gallery targets explicit; the generated preview denominator counts that ledger plus rendered PNG/SVG pairs, rather than comparing preview files with grouped catalogue entries. Adjustment for dividends/corporate actions, log returns and time-scale annualization remain planned. Date conversion, Weibull T limits, unequal subgroup sizes, historical parameter overrides, chart-specific test defaults and other SPC variants remain planned. Left for follow-on work rather than L061: other distribution/Cartesian variants, font fallback for separators a face lacks, label leader lines and optimised dense-cluster placement, embedded fonts and compression in PDF output, multi-layer widget views, SVG font subsetting, Machado anomalous-trichromacy tables and a faster PNG deflate; benchmarks against ggplot2/base R/lattice are queued as L162. Security maintenance (D1793) closes output-staging, XML-ingestion, image-default and template-budget findings; `scripts/check_security.py` passes on Windows and Linux. This maintenance does not advance L061's chart score. `weibull_probability_plot` now maps positive failure times to log-time/Weibull paper with NIST median ranks for complete or Type-I end-censored samples and a caller-supplied two-parameter reference; a Windows/Linux geometry and scene/SVG fixture covers the NIST 20-unit sample and refusals. The gallery adds the one hundred and eighty-first PNG/SVG pair. Earlier right-censor removals, parameter estimation and confidence bounds remain planned. `binomial_acceptance_probability` and `oc_curve` now render NIST's (n=52, c=3) single-sample attributes operating-characteristic curve with exact beta-function binomial acceptance probabilities. The Windows/Linux fixture checks NIST table values, boundary cases, geometry and scene/SVG paths; the gallery adds the one hundred and eighty-second PNG/SVG pair. Finite-lot hypergeometric, double/multiple sampling and plan optimization remain planned. `gage_rr_crossed` now computes balanced crossed ANOVA mean squares, interaction selection and nonnegative variance components from repeated part-by-operator readings; `gage_rr_components` emits paired variance-contribution and study-variation bars. A Windows/Linux fixture checks Minitab's published reduced-model table, both interaction branches, refusals and scene/SVG adapters; the gallery adds the one hundred and eighty-third PNG/SVG pair. Unbalanced/nested studies, intervals, tolerance ratios and the full multi-panel study remain planned. `multi_vari` now maps balanced two-factor readings to raw points, per-cell means, independent within-group connectors and outer-factor means with caller-owned storage. A Windows/Linux fixture checks means, grouped geometry, constant data, refusals and scene/SVG adapters; the gallery adds the one hundred and eighty-fourth PNG/SVG pair. Three-/four-factor nesting, missing cells and uncertainty remain planned. `main_effects` now accepts observation-major categorical factor ids and unbalanced observations, returning raw level means/counts, independent factor lines and grand-mean references with caller-owned storage. Windows/Linux fixtures check unequal counts, geometry, flat values, refusals and scene/SVG adapters; the gallery adds the one hundred and eighty-fifth PNG/SVG pair. Model-adjusted means, uncertainty and interaction diagnostics remain planned. `interaction_plot` now computes raw two-factor cell means and counts for unbalanced nonempty cells and emits separately styled PointLine series on a shared scale; a Windows/Linux fixture checks crossing geometry, flat values, adapters and refusals, and the gallery adds the one hundred and eighty-sixth PNG/SVG pair. Missing-cell interpolation, model-adjusted interactions, intervals and significance tests remain planned. `cube_plot` now projects an eight-vertex, three-factor, two-level design and computes raw response means/counts for nonempty combinations with caller-owned buffers. Windows/Linux fixtures check values, geometry, flat responses, adapters and refusals; the gallery adds the one hundred and eighty-seventh PNG/SVG pair. Fitted means, design-only cubes and four-plus-factor grids remain planned. `spectrogram` now maps borrowed one-sided STFT coefficients to caller-owned time/frequency heatmap cells with a finite decibel floor and axis metadata. Windows/Linux fixtures check power values, bin order, geometry, scene/SVG adapters and refusals; the gallery runs `e.dsp.stft` on rising and steady tones for the one hundred and eighty-eighth PNG/SVG pair. Calibrated PSD, alternate frequency scales, streaming and legend controls remain planned. `waterfall_spectrum` now samples an existing one-sided spectrogram into separately styled oblique frequency traces with retained frame indices and a shared decibel scale. Windows/Linux fixtures check bin order, frame sampling, geometry, scene/SVG adapters and refusals; the gallery adds the one hundred and eighty-ninth PNG/SVG pair from `e.dsp.stft`. Depth-buffered occlusion, interaction and calibrated PSD remain planned. `bode` now maps sampled complex response values to log-frequency magnitude-dB and unwrapped-phase panels, with a finite zero-gain floor and caller-owned numeric/geometry buffers. Windows/Linux fixtures check the low-pass reference, decade positions, phase wrap, zero gain, scene/SVG adapters and refusals; the gallery adds the one hundred and ninetieth PNG/SVG pair. Gain/phase margins, transfer-function evaluation and MIMO panel grids remain planned. `nyquist` maps sampled real-coefficient SISO frequency response to equal-scale real/imaginary positive and conjugate-negative branches, with the (-1, 0) critical point and caller-owned geometry. Windows/Linux fixtures check complex-plane mapping, reflection, equal scaling, scene/SVG adapters and refusals; the gallery adds the one hundred and ninety-first PNG/SVG pair. Full contour closure around imaginary-axis poles, winding/stability certification, model evaluation and MIMO remain planned. `scatter3d` now projects borrowed x/y/z columns through an explicit azimuth/elevation/perspective camera, normalizes a three-axis box, sorts depth with O(n log n) caller-owned indices, and emits far-to-near perspective-sized circles plus a twelve-edge cube frame. Windows/Linux fixtures check 3-D extents, depth order, aspect, flat data, scene/SVG adapters and refusals; the gallery adds the one hundred and ninety-second PNG/SVG pair. Density surface, wireframe, interactive rotation and true depth-buffered occlusion remain planned. `histogram3d` reuses `bin2d`'s inclusive-boundary joint counts, extrudes every nonempty x-y cell into a count-height prism, projects top and camera-facing side quads through the shared `Viewport3d`, and sorts faces by average depth. Windows/Linux fixtures check bins, height, face order, reversed azimuth, scene/SVG output and refusals; the gallery adds the one hundred and ninety-third PNG/SVG pair. Occlusion is painter-ordered, not depth-buffered, and the first slice supports above-plane cameras only. `surface3d_grid` now projects finite row-major scalar grids into caller-owned sorted Area quads and row/column wire segments with the shared 3-D camera. `density_surface3d` feeds that grid with explicit-bandwidth product-Gaussian KDE; `wireframe3d` accepts any finite regular scalar grid. A Windows/Linux fixture checks grid geometry, KDE peak/domain, face ordering, scene/SVG adapters, flat data and refusals. The gallery adds the one hundred and ninety-fourth density-surface and one hundred and ninety-fifth wireframe PNG/SVG pairs. Exact hidden-surface removal, adaptive mesh resolution, interactive rotation and calibrated 3-D axes remain planned. `anom` computes one-way group means, a pooled within-group standard deviation and balanced or unequal-size decision limits from a caller-supplied ANOM critical; it flags out-of-limit means and reuses scene/SVG layers. The Windows/Linux fixture checks numeric limits, unequal groups, flat data, adapters and refusals. The gallery adds the one hundred and ninety-sixth PNG/SVG pair. Automatic exact critical-value selection, two-way ANOM and nonnormal variants remain planned. `hotelling_t2_individuals` computes Phase I and Phase II covariance-adjusted scores, with beta and F upper limits from historical sample size and alpha. The Windows/Linux fixture checks correlated covariance, both limit formulas, signals, singular refusal, adapters and capacities. The gallery adds the one hundred and ninety-seventh PNG/SVG pair. Subgroup T-squared and historical exclusion workflow remain planned. `generalized_variance` plots subgroup covariance determinants with pooled Phase I reference and `b1`/`b2`/`b3` moment factors, one- or two-sided moment-normal limits, Phase II isolation and out-of-limit signals. The Windows/Linux fixture checks two- and three-variate numeric cases, singular subgroups, adapters and refusals. The gallery adds the one hundred and ninety-eighth PNG/SVG pair. Exact/Cornish-Fisher calibration and unequal subgroup sizes remain planned. `mewma` computes multivariate exponentially weighted scores with an exact finite-time covariance factor and a caller-supplied run-length-calibrated upper limit; historical Phase II data determine the reference mean/covariance without monitoring leakage. The Windows/Linux fixture checks recurrence, lambda-one equivalence, signal classification, singular refusal, adapters and capacities. The gallery adds the one hundred and ninety-ninth PNG/SVG pair. In-library ARL calibration, per-variable lambdas and subgroup MEWMA remain planned. `normal_capability` adds an individuals histogram, within/overall fitted normal count curves, LSL/mean/USL guides, Cp/Cpk/Pp/Ppk and observed versus normal-model out-of-spec PPM, using `stat.normal_capability_individuals` and `stat.normal_capability_performance`. The Windows/Linux fixture checks estimators, observed tails, adapters, degenerate data and refusals; the gallery adds the two-hundredth PNG/SVG pair. `lognormal_capability` adds a two-parameter lognormal MLE, Minitab-style overall Z-score Pp/Ppk, observed and fitted tail PPM, and a skewed histogram with fitted count curve and LSL/median/USL guides. The Windows/Linux fixture checks numeric fit and tail references, adapters, invalid/flat data and storage refusals; the gallery adds the two-hundred-and-first PNG/SVG pair. `binomial_capability` adds pooled defective-unit PPM, a Wilson interval, target comparisons, a variable-size P chart, cumulative weighted rate and out-of-limit points. A Windows/Linux fixture checks numeric references, adapters and refusals; the gallery adds the two-hundred-and-second PNG/SVG pair. `batch_capability` adds a balanced one-way ANOVA variance split, between/within and overall Cp/Cpk/Pp/Ppk, tail PPM, and batch-means plus within-batch-SD panels. The Windows/Linux fixture checks exact components, zero-between clamping, adapters and refusals; the gallery adds the two-hundred-and-third PNG/SVG pair. `gage_linearity` adds replicate bias-versus-reference points, per-standard means, an OLS fit, mean-bias confidence limits, slope p-value and a zero-bias guide. The Windows/Linux fixture checks numeric references, adapters and refusals; the gallery adds the two-hundred-and-fourth PNG/SVG pair. `attribute_agreement` adds per-appraiser within and versus-standard matched-item fractions with exact Clopper-Pearson intervals, plus all-appraiser item agreement and pooled rating-level kappa. The Windows/Linux fixture checks counts, intervals, kappa, adapters and refusals; the gallery adds the two-hundred-and-fifth PNG/SVG pair. `gage_run` preserves each crossed part/operator/repeat measurement as an individual point, with operator-specific layers, part dividers and an overall-mean guide; `gage_run_summary` reports the grand mean, extrema and maximum within-cell repeat range. The Windows/Linux fixture checks exact statistics and geometry, scene/SVG adapters, constant values, invalid dimensions and storage refusals; the gallery adds the two-hundred-and-sixth PNG/SVG pair. `e.algo.geo.map_project` adds explicit equirectangular and Mercator map windows with dateline-centered wrapping; `choropleth` joins keyed region values and caller-supplied outer/hole rings into scene/SVG-matched compound fills, while `proportional_symbol_map` scales site-circle area with value. The Windows/Linux map fixture checks projection references, keyed missing data, opposite hole winding, area ratios, adapters, seam rejection and storage refusals; the gallery adds the two-hundred-and-seventh and two-hundred-and-eighth PNG/SVG pairs. `cross_tabulate` retains exact u64 category intersections and marginal totals; `matrix_aggregate` sums finite numeric cells while distinguishing missing from observed zero. `cross_tab_report` and `matrix_report` add header bands, marginal/grand totals, contiguous-group subtotals and optional row/global-scaled positive data bars in caller-owned geometry. The Windows/Linux `gfx_chart_reports` fixture checks counts, sums, nulls, subtotals, bar ratios, adapters and refusals; the gallery adds two paired PNG/SVG previews. `future_value_stream_map` pairs current/target proportional ladders, derives demand takt and marks a pacemaker, FIFO/pull controls and over-takt stages; its Windows/Linux fixture checks numeric deltas, geometry, adapters and refusals, and the gallery adds a paired preview. `cap_table_waterfall` computes overflow-checked existing, pool-top-up and investor share totals, before/after holder percentages and a retained-ownership dilution bridge; the Windows/Linux `gfx_chart_cap_table` fixture covers fractions, geometry, adapters, optional issuance events and refusals, and the gallery adds a paired preview. SAFE/note conversions, preferences, voting classes and valuation are not part of this share-count slice. `tornado_sensitivity` stably orders paired one-at-a-time output ranges by swing, preserves low/high assumption identity under reversed response, and maps all rows to a common baseline; the Windows/Linux `gfx_chart_tornado` fixture checks sorting, geometry, adapters and refusals, and the gallery adds a paired preview. `football_field` composes method valuation ranges and a benchmark over one caller-specified domain; the Windows/Linux `gfx_chart_football_field` fixture checks capped bars, reference mapping, adapters and refusals, and the gallery adds a paired preview. `yield_curve` maps ordered maturities and finite supplied rates over explicit shared axes; the Windows/Linux `gfx_chart_yield_curve` fixture checks uneven spacing, inversion, negative rates, adapters and refusals, and the gallery adds a synthetic two-scenario paired preview. `monte_carlo_distribution` makes exact equal-width counts, empirical CDF steps and an at-or-below threshold fraction from caller-owned trial outcomes; the Windows/Linux `gfx_chart_monte_carlo` fixture checks count conservation, endpoint bins, sorting, CDF geometry, adapters and refusals, and one fixed-seed toy simulation yields histogram and CDF preview pairs. `aggregate_decomposition_tree` rolls nonnegative leaf measures up a depth-first-preorder parent hierarchy and draws proportional parent-share bars in a static left-to-right tree; the Windows/Linux `gfx_chart_aggregate_tree` fixture checks totals, geometry, adapters and refusals, and the gallery adds its PNG/SVG pair. `date_axis_line` maps ordered civil dates by elapsed days over explicit date/y domains, with month-start `date_ticks` and caller-owned ISO year-month labels; the Windows/Linux `gfx_chart_date_axis` fixture checks leap-year spacing, adapters and refusal paths, and the gallery adds a PNG/SVG pair. `discrete_axis_bars` aggregates repeated category keys in caller-defined factor order and preserves missing levels as zero-height slots; the Windows/Linux `gfx_chart_discrete_axis` fixture checks totals, geometry, adapters and refusals, and the gallery adds a PNG/SVG pair. `category_facet_scatter` assigns categorical rows to ordered shared-scale panels, retains empty levels and emits strip labels; the Windows/Linux `gfx_chart_category_facet` fixture checks grouping, scene/SVG adapters and refusals, and the gallery adds a PNG/SVG pair. `wrapped_legend_items` wraps caller-measured swatch/label pairs inside a bounded legend region without collision; the Windows/Linux `gfx_chart_legend_wrap` fixture checks geometry, adapters and refusals, and the gallery adds a PNG/SVG pair. `masked_scatter` omits incomplete x/y pairs using explicit presence masks while preserving source row IDs and refusing invalid observed coordinates; the Windows/Linux `gfx_chart_missing_scatter` fixture checks compaction, adapters and refusals, and the gallery adds a PNG/SVG pair. `chart.scene.begin_clip` and `chart.svg.begin_clip` scope rectangular clipping around marks and annotations, with matching end calls; the Windows/Linux `gfx_chart_clipped_annotation` fixture checks scene command balance, escaped SVG, invalid bounds and IDs, and short-builder refusal. The gallery adds a paired PNG/SVG preview with a visibly cropped note. `plot_grid` arranges independent chart specifications in caller-owned weighted row-major cells with explicit gaps; the Windows/Linux `gfx_chart_plot_grid` fixture checks geometry, adapters and refusal paths, and the gallery adds a paired preview with line, bar, scatter and area panels. `shared_facet_guide_labels` places common x/y tick text only along the exterior of a complete aligned facet grid; the Windows/Linux `gfx_chart_shared_guides` fixture checks positions, deduplication, adapters and refusal paths, and the gallery adds a paired four-panel preview. `hit_scatter` maps pointer coordinates to nearest marks and retained source row IDs, `selected_point_outline` supplies a renderer-neutral highlight, and SVG points expose focusable fragment links with stable row metadata; the Windows/Linux `gfx_chart_selection` fixture checks geometry, tie/identity semantics, adapters and refusals, and the gallery adds a selected-state PNG plus interactive standalone SVG. Widget event wiring and cross-chart state remain planned L062 work. Pagination, print layout and tabular export remain planned, along with arbitrary polygon clipping, map-file import, geographic legends, Weibull and other nonnormal families, Poisson attribute capability, unequal-size batches and broader stability/fit diagnostics. `accessible_palette` returns six qualitative series colours for an opaque background, moving only seeds below 4.5:1 toward black or white by the smallest bisected amount; `rendered_contrast_ratio` measures the channel bytes the scene/PNG and SVG adapters actually write (D2101). The Windows/Linux `gfx_chart_accessible_palette` fixture checks white, black and mid-gray backgrounds, unchanged passing seeds, adapter colours and refusals; the gallery adds a labelled white/dark PNG/SVG pair, which empties the planned preview backlog, and `tests/test_charts_doc.py` re-checks the written label colours with an independent WCAG computation. `chart.svg.append_brush` gives the SVG adapter the scene's `paint.Brush` parity: `gradient` writes user-space linear/radial gradients with the rasterizer's stops and pad spread and refuses zero-length linear gradients, whose colour the two backends disagree on; `embed_font` streams a TrueType/OpenType file into a base64 `@font-face` data URL and `append_labels_in` names that family (D2102). The Windows/Linux `gfx_chart_svg_paint` fixture checks gradient markup and references, the solid fallback, a base64 round trip across encoder chunks, scene parity and refusals; the gallery adds the `gradient_font` pair, whose embedded Montserrat a browser loads and `tests/test_charts_doc.py` decodes back to the font file. `simulate_color_vision` applies the Vienot-Brettel-Mollon protan/deutan/tritan model with a linear-RGB severity blend, `color_lab` and `ciede2000` measure CIELAB/CIEDE2000 differences, and `palette_separation` reports a palette's closest pair as a given viewer sees it (D2103); it shows the accessible palette keeps ~10 CIEDE2000 for typical vision but 1.2 for deuteranopes, which is why charts label series. The Windows/Linux `gfx_chart_color_vision` fixture checks Sharma's CIEDE2000 pairs, CIELAB, simulated colours and separations against NumPy/scikit-image references (`scripts/chart_cvd_reference.py`) and refusals; the gallery adds the `color_vision` pair, whose swatches the doc test re-simulates from the LMS model. `place_point_labels` places point labels in caller priority order over Imhof's eight candidate positions, keeping each inside the plot, off earlier labels and clear of other points, and reports labels with no free slot as unplaced (D2104). The Windows/Linux `gfx_chart_label_placement` fixture checks slot order, edge flipping, neighbour blocking, a 40-point cluster whose 27 placements match a Python replica, adapter output and refusals; the gallery adds the `label_placement` pair, which labels 21 of 25 European cities and greys out the Benelux four. The new `e.gfx.chart.locale` module writes tick text through `e.text.locale`: `format_ticks_in` gives an axis one shared precision (`tick_decimals`) with the locale's decimal/grouping separators and CLDR minimum grouping, and `format_date_ticks_in` writes date ticks through an LDML pattern via the new `locale.format_pattern` (D2105). The Windows/Linux `gfx_chart_locale` fixture checks en/de/fr/es/ja numbers and month labels, precision, negative zero and refusals; the gallery adds the `locale_axes` pair with en-US, German, Spanish and Italian axes. The new `e.gfx.chart.widget` module is the `e.ui` adapter: a `View` (spec, brush, guides, caller-owned mark storage) becomes a `widget.Custom` for `control.canvas`/`framed_canvas` whose paint lays the chart out against the rectangle the canvas receives and keeps the marks for hit testing, with the view's revision as the custom's state so unchanged charts replay (D2106). The Windows/Linux `gfx_chart_widget` fixture checks measure, re-layout across rectangles, the too-small case, the accessibility label, the pixel under a mark and the replay/revision contract through the headless `e.ui.testing` harness; the gallery adds the `ui_canvas` pair, whose PNG is a widget-runtime frame. The new `e.gfx.chart.pdf` adapter writes one PDF 1.4 page from the same layouts: the SVG adapter's mark kinds and shapes in points, opacity through ExtGState, Helvetica text aligned by Adobe's advance widths with WinAnsi mapping, caller-owned content storage and a complete cross-reference table (D2107). The Windows/Linux `gfx_chart_pdf` fixture checks number formatting, widths, escaping, opacity states, xref offsets, stream length and refusals; the gallery's `pdf_export` preview adds a PDF companion that pypdf parses strictly and a PyMuPDF rasterization matches against the PNG, and charts.html links it. `benchmarks/charts` times one workload (1,000-point line, 200 markers, grid, ticks, title, 360x240, 200 charts per pass) in Neper and matplotlib 3.9.4 in-process with nine-run medians (D2108): on Windows Neper writes SVG in 2.62 ms per chart against 16.02 (6.1x faster) and PNG in 20.28 against 17.68 (matplotlib 1.15x faster), with layout 0.16 ms and rasterization 2.0 ms, so the PNG gap is the deflate encoder; the Neper side runs on Linux with the same timings and byte-identical output. The gallery adds the `benchmark_matplotlib` pair. Closed (D2109): every planned gallery target is rendered (235 previews with SVG companions and a PDF), the scene/PNG, SVG, PDF and e.ui widget adapters and locale-aware text exist, and the engine is benchmarked against matplotlib; the R comparisons need an R installation and move to L162.

### L016 — Safety-signal detection in e.algo.stat

Pharmacovigilance mines FAERS-style tables with disproportionality scores (reporting odds ratio, proportional reporting ratio, BCPNN information component) and comedication patterns with frequent-itemset rules (Apriori/FP-growth) for drug-drug interactions. Neper has binomial proportion intervals and chi-squared/Fisher contingency tests in `e.algo.stat` and `e.algo.stat.test`, but no disproportionality or frequent-itemset surface. Keep the scores and rule mining with caller storage; exclude case-report workflows and MedDRA coding products. The catalog entry is 2266. Delivered: ROR/PRR with intervals and signal rules, BCPNN information component with credibility signal, and Apriori frequent-itemset/rule mining over u64 masks, pinned by algo_stat_safety on both hosts.

### L017 — Forecast and inventory extensions (ARIMA, EOQ/newsvendor)

`e.algo.timeseries` forecasts with Holt-Winters, STL/LOESS, GARCH, and Hawkes plus CUSUM/Page-Hinkley/ADWIN change detection, and `e.algo.combopt` solves tours (nearest-neighbor, 2-opt/3-opt, Held-Karp, Christofides, Lin-Kernighan) and VRP by savings, but there is no ARIMA for ADR-surveillance and demand series and no inventory core (EOQ, newsvendor) for supply planning. Keep ARIMA plus the two inventory policies; exclude cold-chain logistics products. The catalog entry is 2267. Delivered: ARIMA differencing, AR OLS fits, ARMA conditional-SSQ Nelder-Mead fits and forecasts plus EOQ/newsvendor inventory policies, pinned by algo_timeseries_arima on both hosts.

### L059 — VAR and structural time-series in e.algo.timeseries

lib/e/algo/timeseries.e covers Holt-Winters, STL/LOESS, CUSUM/Page-Hinkley/ADWIN, GARCH(1,1) and Hawkes, and lib/e/math/filter.e covers Kalman/EKF/UKF -- the R/Python time-series gap is VAR(p) estimation and forecasting plus a structural/state-space bridge onto the existing Kalman filter. ARIMA is already L017 and out of scope here; Prophet is a non-goal (D1785). Keep caller-storage conventions; fixtures against statsmodels values. Plan: docs/stats-coverage.md rows L059 (D1785). Delivered: VAR(p) estimation by equation-wise OLS with multi-step forecasts, the companion state-space form for e.math.filter Kalman, and local-level/local-linear-trend structural filters through that Kalman, pinned by algo_timeseries_var on both hosts.

### L062 — Specialized visualization (interactive, geographic, network, 3D)

Much of L062 landed under L061: `hit_scatter`/`selected_point_outline` and focusable SVG points (interactive selection), `choropleth` and `proportional_symbols` over e.algo.geo projections (geographic rendering), `scatter3d`, `histogram3d`, `density_surface3d` and `wireframe3d` through an explicit camera (3D surfaces), and the `e.gfx.chart.widget` canvas adapter. `network_layout` now lays out undirected graphs by deterministic Fruchterman-Reingold force direction (D2112); the `gfx_chart_network` fixture matches a Python replica and checks the karate club's structure, determinism and refusals, and the gallery's `network` pair colours it by Louvain communities from e.algo.graph.community. Chart widgets take the pointer through `chart_widget.region` (D2114): the wheel zooms a window over the plot about the pointer, a drag pans it, a double tap resets it, and hovering outlines the nearest point; e.ui regions gained a wheel gesture for it. The `gfx_chart_widget` fixture checks the outline's pixels, the zoom keeping the point under the pointer, the pan, the reset and the zoom limit. `e.gfx.chart.geojson` reads FeatureCollection polygons into choropleth arrays, and `class_of`/`class_legend` give equal-interval colour classes and their legend strip (D2115); the `gfx_chart_geojson` fixture checks holes, MultiPolygons, null geometries, both keyings, the resulting choropleth and the refusals, and the gallery's choropleth reads GeoJSON and labels its class breaks. 3-D charts orbit by dragging: `chart.orbit` wraps the azimuth and holds the elevation, and `chart_widget.Orbit`/`orbit_region` turn a canvas's camera from the press and reset on a double tap (D2116); `gfx_chart_widget` checks the wrap, the clamp, the refusals, a dragged turn that repaints a moved projection, and the reset. `layered_layout` draws DAGs in longest-path rows with alternating barycentre sweeps and refuses cycles (D2117); `gfx_chart_network` checks an uncrossing sweep, longest-path rows, downward links, self-loops and refusals. Barnes-Hut is not needed below a few thousand nodes (D2117). The network, layered, GeoJSON and widget checks pass in both the Windows and the Linux suites. Dashboards remain a non-goal (D1785).

### L001 — Hypergeometric probabilities in e.algo.stat

Both MTG Studio implementations need the same finite-population draw calculation: `mtg.studio.web/js/domain/draw-probability.js` provides exact, at-least, and at-most probabilities, while `mtg.studio.src/shared/lib/helpers/math.helper.dart` provides the hypergeometric distribution. Neper has binomial coefficients in `e.algo.combin` and broad continuous/discrete statistics, but no hypergeometric PMF or tail API. Implement with validated inputs and stable multiplicative or log-space arithmetic rather than copying the small-deck floating-point choose formula. The catalog entry is 2251. Delivered: hypergeometric PMF plus at-most/at-least tails over u64 counts in lgamma log space beside binomial_acceptance_probability, pinned by algo_stat_hyper on both hosts.

### L005 — Survival-analysis extensions in e.algo.stat

Celvyx implements Nelson-Aalen cumulative hazard, Aalen-Johansen competing-risks cumulative incidence, restricted mean survival time, and weighted log-rank tests in `src/lib/core/medical/nelson_aalen.dart`, `competing_risks.dart`, `rmst.dart`, and `weighted_logrank.dart`. Neper has general distributions and hypothesis tests but no matching survival-analysis surface. Keep the reusable estimators and tests; exclude the labelled spreadsheet grids. The catalog entry is 2255. Delivered: Nelson-Aalen cumulative hazard, Aalen-Johansen competing-risk incidence, RMST with Greenwood SE, and weighted (Breslow/Tarone-Ware/Peto-Peto/Fleming-Harrington) log-rank tests, pinned by algo_stat_survival on both hosts.

### L008 — Diagnostic-test statistics in e.algo.stat

Celvyx implements 2x2 diagnostic-table sensitivity, specificity, accuracy, predictive values, likelihood ratios, diagnostic odds ratio, and exact confidence intervals in `src/lib/core/medical/diagnostic.dart`. Neper has contingency-table tests but no diagnostic-metric API. Keep this as a small generic binary-classification/statistics module; exclude medical report grids. The catalog entry is 2258. Delivered: 2x2 sensitivity/specificity/accuracy/predictive values/likelihood ratios/diagnostic odds ratio with exact and log-method intervals, pinned by algo_stat_diagnostic on both hosts.

### L006 — Meta-analysis core in e.algo.stat

Celvyx provides odds-ratio, risk-ratio, Cohen-d, Hedges-g, and Fisher-z effect sizes plus fixed/random-effects heterogeneity, Q, I-squared, tau-squared, subgroup analysis, and meta-regression in `src/lib/core/medical/meta_effect_size.dart`, `meta_heterogeneity.dart`, and `meta_regression.dart`. Neper has resampling and ordinary regression but no meta-analysis API. Add the numerical core, not medical report formatting. The catalog entry is 2256. Delivered: log odds-ratio/risk-ratio, Cohen-d, Hedges-g, Fisher-z effects with fixed/DerSimonian-Laird random pooling, Q, I-squared, tau-squared, subgroup Q and WLS meta-regression, pinned by algo_stat_meta on both hosts.

### L002 — Robust total-least-squares line fitting in e.gfx.vision

The MTG scanner refines detected card edges with an orthogonal total-least-squares line fit and one outlier-rejection pass in `mtg.studio.web/js/domain/scan-rectify.js` and `mtg.studio.src/scan-spike/lib/rectify.dart`. Neper already has the surrounding computer-vision primitives, including homography, RANSAC, bilinear sampling, and connected components, but no reusable 2D TLS line-fit API. Keep this as a small `e.gfx.vision.fit_line_tls` candidate; do not move the card-specific detector or rectifier. The catalog entry is 2252. Delivered: orthogonal TLS line fit (centroid plus principal axis, vertical-safe) with one outlier-rejection pass, pinned by gfx_vision_tls on both hosts.

### L007 — Generalized regression extensions in e.algo.stat

Celvyx covers Poisson rate regression with exposure offsets, negative-binomial regression, conditional logistic regression for matched sets, and ordinal logistic regression in `src/lib/core/medical/clinical_poisson.dart`, `negative_binomial.dart`, `conditional_logistic.dart`, and `ordinal_logistic.dart`. Neper already has binary logistic regression in `e.ml.linear`, so this is an extension rather than a duplicate. Keep model fitting and diagnostics; exclude clinical presentation wrappers. The catalog entry is 2257. Delivered: Poisson rate regression with exposures, negative-binomial by IRLS plus golden-section dispersion, conditional logistic for matched sets, and proportional-odds ordinal logistic by Nelder-Mead, pinned by algo_stat_regression on both hosts.

### L068 — Chart parity: bubbles, ellipses, fitted curves, combo axes and axis tables

Delivered (D2120, D2121). Already under L061: bubble maps size to circle area; covariance_ellipse refuses singular covariance; regression_line and regression_interval give OLS confidence and prediction bands. New: loess_interval fits local-linear LOESS over unsorted x with a confidence or prediction ribbon from the smoother weights (s^2 = RSS/delta1), held to statsmodels LOWESS and an explicit smoother matrix (scripts/chart_loess_reference.py); combo lays out Bar/Line/PointLine/Scatter series at arbitrary x over one x domain on any number of independent axes, a NaN y being a missing value that breaks its line (the scene and SVG adapters now start a subpath at a gap; every existing preview re-renders byte-identical); side_axis draws explicit secondary and further axes; axis_table aligns rows of caller text to a layer x domain. gfx_chart_bubble, gfx_chart_overlays, gfx_chart_loess and gfx_chart_combo_axes check numeric references, singular/invalid data, layer and axis alignment, storage bounds and scene/SVG output; the two new fixtures pass on Windows and Linux and all 161 gfx_chart fixtures pass on Windows. Previews: loess_band, combo_axes.

### C099 — M4-01: aarch64 emitter for Linux, the first NeperOS stage

Planned in D2119 (NeperOS, a capability microkernel written in Neper for Google Pixel phones, starts here; this is the roadmap's M4 aarch64 emitter pulled forward), delivered in D2123 and D2124. Acceptance: `--target aarch64-linux` builds a freestanding static ELF through an aarch64 selector and A64 encoder over the existing NIR and allocator; the Linux fixture suite passes under `qemu-aarch64` with x64's output; the encoder agrees with the GNU tools on a sweep; and neper-self built for aarch64 runs under `qemu-aarch64` and emits what the x64 one does. Delivered: `codegen_a64` (AAPCS64 over the shared NIR, allocator, relocations, line table and trap protocol, NEON for `Vec` lanes) and `emit_a64` (A64 words); `link_elf_a64`, a static image or, with an `@import`, a dynamic one bound through `R_AARCH64_GLOB_DAT` slots, with the x64 image's symbols and DWARF and aarch64's frame description (`gdb-multiarch` breaks and walks frames); and `runtime_elf_a64.s`, whose `neper_os_syscall` translates `e.os`'s x86-64 numbers, flags, structures, signal restorer and seccomp filters. By-value C aggregates cross `extern fn` and `@cc` by AAPCS64's own rules (D2124): a homogeneous float aggregate of up to four members in vector registers, any other aggregate up to 16 bytes in one or two general registers, a larger one by reference to a copy, an aggregate that no longer fits whole on the stack, and a large result through `x8`. `self-test` checks 110 encodings and a 63,610-encoding sweep against GNU as (`scripts/a64_encoding_sweep.py`). `scripts/a64-differential.ps1` and `.sh` build all 817 buildable link fixtures for both targets (four more are refused at build time on both, by design) and compare stdout, stderr and status: 812 agree under `qemu-aarch64` 8.2.2, among them the 139 dynamic images against Ubuntu's arm64 loader and libraries (Vulkan through lavapipe, the database client libraries) and `extern_struct` against its C library built by `aarch64-linux-gnu-gcc`. The other five are expected: `os_fs` and `fs_basics` open through openat2, which QEMU's user mode lacks; `os_gaps` installs a seccomp filter QEMU refuses; `debug_dump` gcores an emulated process; and `when_target` answers for its own architecture. The compiler built for aarch64 passes `self-test` under QEMU and is a fixed point with the x64 one: each builds the compiler, for either target, into byte-identical images. Both self-host suites pass. Tools: QEMU 11.1.0 for Windows at `D:\tools\qemu`; in WSL `qemu-user` 8.2.2, `gdb-multiarch` 15.1, `binutils-aarch64-linux-gnu` 2.42, `gcc-aarch64-linux-gnu` and the arm64 libraries from Ubuntu's ports archive.

### C100 — NeperOS 1a: an aarch64-none kernel image that boots on QEMU virt

Queued by D2125 when C099 closed; stage 1 of D2119; delivered in D2126. Acceptance: `--target aarch64-none` writes a raw image with the Linux arm64 Image header (magic `ARM\x64`, `text_offset`, `image_size` covering what the kernel zeroes) that `qemu-system-aarch64 -M virt -cpu cortex-a76 -kernel` loads and enters at EL1 with the device tree in `x0`, position-independent wherever the loader places it; no Linux runtime, only a boot stub that sets the stack, clears what the image does not carry and calls `main` with an arena carved from memory after the image; Neper reaches system registers (`mrs`/`msr`), barriers (`dsb`/`dmb`/`isb`), `wfi`/`wfe`, `hvc`/`smc` and volatile MMIO loads and stores through intrinsics that any other target refuses at check time; an exception vector table (sixteen entries, 2 KB aligned) saves the interrupted registers into a frame and calls a Neper handler; a kernel reads its memory and PL011 base from the device tree, turns on the MMU and caches with an identity map, writes to the PL011, and powers off through PSCI `SYSTEM_OFF` by the conduit the tree names. A fixture boots under QEMU on both hosts, checks the serial transcript, and takes a deliberate synchronous fault whose ESR and FAR the handler reports. A trap (bounds, overflow) reports its message and position on the console and powers off with a non-zero status. Delivered: `link_image_a64` writes the Image (header, code on a page, runtime 2 KB aligned, symbol table rebased to the image start, globals, and a bss for hook slots, a 256 KB stack and the arena -- 16 MB unless `--arena` says otherwise -- inside `image_size`); `runtime_none_a64.s` is the entry (FPEN on, vectors installed, the device tree as `args[0]`), the vectors and a 304-byte frame the handler may rewrite before `eret`, the console, exit and exception hooks (`os.set_console`, `os.set_exit`, `os.set_exception`), the trap printed through the console with its backtrace, and the machine as runtime calls seeded for aarch64-none alone: `load8`-`load64`, `store8`-`store64`, `barrier` (`dsb sy; isb`), `memory_barrier`, `tlb_flush`, `wait_for_interrupt`, `wait_for_event`, `send_event`, `hvc`, `smc`, and `mrs`/`msr` over a table of 45 system registers (anything else is reported and exits 136). Elsewhere `os.mrs` is refused where it is written (`E-NAME-9999`, fixture `kernel_refuse`). `em_link` resolves `aarch64-none` artifacts as aarch64 words, and `scripts/embed-elf-runtime.ps1 -Arch none` refuses a runtime with relocations. NeperOS is `neperos/src` (`fdt`, `pl011`, `psci`, `mmu`, `a64`, `main`): the 36 KB image finds the console through `/chosen`'s `stdout-path`, PSCI's conduit and RAM in the tree, maps the 39-bit space identity (Device gigabytes, 2 MB Normal write-back blocks over RAM), turns on the MMU and caches, reads past the 39-bit space and takes the translation fault (ESR 0x96000004), whose handler answers zero and steps over the load, then sends and waits for an event and powers off. Both suites boot it under qemu-system-aarch64 (QEMU 11.1 on Windows, 8.2 in WSL with `qemu-system-arm`, `-nic none`), check the transcript, and boot a copy loaded 2 MB higher (`text_offset` 4 MB) with `-append trap`, whose failed bounds check prints `trap[bounds]`, its position and `at main.main (src/main.e:...)`, and exits 134 through the kernel's PSCI hook. The first boot is the user's screenshot `welcome-neperos.png`. Both self-host suites pass.

### C101 — NeperOS 1b: interrupts, the timer and preemptive threads at EL0

Queued by D2125 after C100; stage 1 of D2119; delivered in D2127. Acceptance: the GICv3 distributor and redistributors found in the device tree, the generic timer driving a preemptive round-robin scheduler, user threads at EL0 in their own translation tables (ASIDs, no shared kernel writable mappings, execute-never set), system calls by `svc`, and a QEMU fixture that runs EL0 threads interleaved by timer interrupts and kills one that touches kernel memory. Delivered: `gic` finds the controller at `/intc` (distributor and redistributor as its two `reg` regions, so `fdt.region_n`), turns on affinity routing and group 1, wakes the redistributor, and acknowledges/ends by `ICC_IAR1_EL1`/`ICC_EOIR1_EL1` through the registers already in the runtime table; `timer` arms the virtual timer (PPI 27) a hundredth of a second ahead. `thread` is a round-robin scheduler over a fixed table: a switch is a frame copy in place plus a `TTBR0_EL1` write, distinct ASIDs so no flush; the first tick captures the kernel's idle context and starts the first thread, the last to finish returns the kernel there and the boot loop powers off. `svc` gives console write (0, copied out of the caller's own bounds-checked region), exit (1) and yield (2). `vm` builds an address space as its own L1 over a copy of the kernel identity map plus one gigabyte at 0x80000000 mapped to the thread's pages EL0-RW and privileged-execute-never; the kernel's pages stay privileged-only, so an EL0 access into them faults -- the isolation. Page-table pages are over-allocated and aligned to 4 KB (an unaligned `TTBR0` broke the kernel's own fetch after the first switch). The user program is the new target `aarch64-neperos`: the same position-independent Image, `link_image_a64(program=true)` appending `runtime_neperos_a64.s` (entry from registers, console/exit/yield as `svc`s, `os.yield` the one extra intrinsic) and sizing `image_size` to the file; the header's first reserved word now carries the globals' offset. QEMU loads it with `-initrd`; the kernel reads `/chosen` `linux,initrd-start`/`-end`, copies it into three address spaces, and runs threads A, B and X. A and B interleave under the timer and finish; X, handed a second argument the kernel points at kernel RAM (0x40000000), faults on the read (EL0 permission abort) and is killed alone while A and B run on -- nothing forges a pointer, the kernel plants the one protected reference to prove the page tables stop it. Both suites build the program and kernel and boot them under `qemu-system-aarch64 -M virt,gic-version=3` on both hosts (QEMU 11.1 on Windows, 8.2 in WSL), check that all nine round tokens appear, that X is killed and never reads protected memory, and that the kernel powers off 0; the `trap` boot still ends 134 (handled before the controller and initrd). Both self-host suites pass.

### C102 — NeperOS 1c: capabilities and synchronous IPC

Queued by D2125 after C101; stage 1 of D2119; delivered in D2128. Acceptance: every kernel object (untyped memory, thread, address space, endpoint, notification, IRQ handler, device frame) is reached only through a capability in the caller's capability space; untyped memory retypes into objects so the kernel allocates nothing after boot; endpoints carry synchronous IPC with capability transfer, notifications deliver interrupts to user drivers; capabilities derive with reduced rights and revoke recursively; the console moves to a user-mode server; a QEMU fixture checks that a thread without the console capability cannot print, that a derived read-only frame cannot be written, and that revocation reaches every derived capability. Delivered: each thread has a capability space (eight slots in its control block); endpoint, console, frame, notification, device and untyped objects are reached only through a capability with the right bits. Synchronous IPC over endpoint capabilities -- `send`/`recv` block and rendezvous (a new BLOCKED scheduler state the round-robin skips, the kernel idling when a block leaves nothing runnable), and carry one word plus an optional granted capability (transferred on the rendezvous when the endpoint capability has the grant right, a fresh root in the receiver's space). The console `write` is refused without a console capability; `cap_derive` copies with rights cleared and a parent link; `cap_revoke` nulls every capability derived from a slot through the chain; `frame_protect` walks the thread's own tables and flips a page's AP[1] by the frame capability's write right; a notification hands the timer interrupt to a user driver (the handler signals it before switching, the waiter wakes with the bits, the signaller never blocks); the console moves to a user-mode server K that alone holds the UART device capability and writes a client's line with `device_write` (one call, interrupts masked, so it is never split -- a raw EL0 store would be dropped as a dead store without a volatile the language lacks); and untyped memory retypes into objects (an untyped capability's budget bounds `retype`, which assigns an object slot reserved at boot, so the kernel allocates nothing afterward). Fourteen threads run together under the timer and prove it on both hosts under `-M virt,gic-version=3`: A/B/X interleave and X is killed reading kernel RAM (0x40000000); S/R rendezvous (R7 R8 R9); N without a console capability is refused and prints nothing; V derives a two-link chain, revokes the root and a receive on the revoked capability fails (V revoke ok); W derives a read-only frame capability, re-protects and faults on the next write (killed at 0x80040000); G grants its console capability to H, which held none and only then prints (H got console); D wakes three times on the timer notification (D0 D1 D2); K prints `console server up` for client P over its device capability; U retypes two endpoints from an untyped budget of two and the third is refused (U retype ok). Both suites check every expected line appears and none of the five boundary-crossing lines does; the `trap` boot still ends 134. New `aarch64-neperos` intrinsics `os.send`/`recv`/`cap_derive`/`cap_revoke`/`frame_protect`/`notify_wait`/`device_write`/`retype` (svc 3-10). Both self-host suites pass.

### C103 — NeperOS 1d: virtio over PCI in user-mode drivers, closing stage 1

Queued by D2125 after C102; begun in D2129, transport and entropy driver in D2131, block driver in D2132, console transmit in D2133, EL0 memory-access surface in D2134, location-agnostic DMA pool in D2135, EL0 device-MMIO mapping in D2137, entropy driver as an EL0 user-mode server in D2138, all three drivers as EL0 servers in D2139, negative isolation prober in D2140, interrupt-driven drivers in D2141, console receive/echo and closure in D2142. Acceptance: the PCI ECAM window read from the device tree, the modern virtio-pci transport, and virtio console, block and entropy drivers running as EL0 servers that hold only their device's frames and interrupt; a QEMU fixture reads and writes a disk image and echoes the virtio console. Closing this item closes D2119 stage 1 and queues stage 2 (the AVF guest on a Pixel). Done (D2129): `pci` reads the generic ECAM host from `/pcie` (base 0x40_1000_0000 on virt, in gigabyte 256 the kernel's identity map covers as Device memory), addresses configuration space at `base + (bus<<20) + (slot<<15) + (function<<12) + offset`, reads vendor and device ids, and assigns BARs in the 32-bit MMIO window (QEMU's ECAM host leaves them unassigned); a modern virtio-pci function is vendor 0x1af4 with device id 0x1040 plus the virtio type, and the kernel scans bus 0 reporting each (`virtio entropy at pci slot 1`, `virtio block at pci slot 2`). Done (D2131): the modern virtio-pci transport in `virtio.e` -- `discover` walks the vendor-capability list (cfg_type 1-4) to the common config, notify, ISR and device-config structures; `negotiate` runs the status handshake and accepts only VIRTIO_F_VERSION_1; `read_entropy` builds one split virtqueue (desc/avail/used rings and the buffer in identity-mapped kernel RAM, so VA==PA for DMA), publishes a device-writable descriptor, notifies, and polls the used ring. The kernel's `drive_entropy` prints `entropy N bytes: XX ...`; both suites assert eight random bytes. Verified on both hosts (Linux `neper-self` and Windows `neper-self.exe`), each booting the kernel under QEMU to a different eight-byte sequence. Done (D2132): the virtio-blk driver `block_rw` reuses the transport over a three-descriptor chain (16-byte header the device reads, 512-byte data buffer, one-byte status the device writes), writes a deterministic pattern to sector 0 with VIRTIO_BLK_T_OUT and reads it back with VIRTIO_BLK_T_IN, checking every byte; the queue plumbing is factored into shared `setup_queue`/`ring_wait`, and the block device's BAR is assigned from the cursor the entropy device left so their MMIO windows are disjoint. The kernel prints `block rw ok sector 0: 11 36 5b 80`; both suites assert that exact line. Verified on both hosts under QEMU with a fresh 1 MB disk. Done (D2133): the virtio-console driver `write_console` transmits over port 0's queue 1 without negotiating MULTIPORT (QEMU forwards port-0 tx to the chardev directly); this needed the transport's notify value to carry the queue index (Ring.index), since queue 0 made a literal 0 accidentally correct. The kernel prints `console tx ok` and writes `hello from the neper virtio console` to the port; both suites attach `virtio-serial-pci` with a file-backed `virtconsole`, assert the mark and that the line reached the chardev file, and each driver's BAR is assigned from the previous driver's cursor so the three windows are disjoint. Verified on both hosts under QEMU. Done (D2134): the EL0 memory-access surface -- os.load8/16/32/64, store8/16/32/64 and barrier added to the `neperos` target (resolve.e seed, check.e signatures, runtime_neperos_a64.s bodies, runtime .e regenerated), the floor a user-mode driver needs to touch mapped MMIO and rings without a per-access svc. Gated by g.os==neperos so the compiler's self-compilation is unchanged; surface + lint pass; proven by demo thread Z doing a store/barrier/load round-trip at EL0 (`Z mem ok`), verified by rebuilding neper-self on Windows and booting under QEMU. Done (D2135): the transport's DMA allocation is now a location-agnostic module-level bump pool (pool_set/dma_region) instead of a *mem.Arena, so the same transport runs in the kernel or an EL0 server; read_entropy/block_rw/write_console/setup_queue dropped their arena param and virtio.e no longer imports e.mem; behaviour unchanged, verified under QEMU. Done (D2137): vm.map_range_el0 maps a physical range into an EL0 space at identity VA as Device or Normal memory, splitting the copied kernel L1 block / shared L2 into fresh owned tables (clone_l2/clone_l3) so the untouched remainder stays privileged (confinement); the kernel leaves a driver's addresses in an aux area (put_aux). Proven by prober thread Y reading the entropy device's PCI vendor id (0x1af4) from a kernel-mapped config page at EL0 (`probe vendor ok`), booted under QEMU with no kernel fault. Done (D2138): the entropy driver now runs OUT of the kernel as a capability-confined EL0 user-mode server. The loaded user program moved to neperos/src/init.e so it shares the kernel's modules (`use virtio`); start_entropy_server discovers the device, maps its BAR (Device) + a 128 KB identity DMA pool (Normal) into the server with map_range_el0, leaves common/notify/notify_mult/pool addresses in the aux area, grants a console cap; the `E` branch runs the SAME virtio.read_entropy at EL0 and prints `el0 entropy 8 bytes: ...` (both suites assert it). It holds only its device's frames. Done (D2139): block and console now run as EL0 servers too, so ALL three virtio drivers are capability-confined EL0 user-mode servers and nothing virtio is driven in the kernel. The per-driver kernel setup is one function start_driver_server(..., want_type, name) threading a BAR cursor mmio->E->F->O; drive_entropy/block/console removed; MAX_THREADS raised 16->24. init.e `E`/`F`/`O` share read_device + say_bytes_line (whole line in one os.write so preemption does not interleave output); they print `el0 entropy 8 bytes:`, `el0 block rw ok sector 0: 11 36 5b 80`, `el0 console tx ok`, and the console line reaches the chardev file. Both suites assert all three el0 marks. Verified by rebuilding neper-self and booting under QEMU, no kernel fault. Done (D2140): a negative isolation prober -- thread Q is handed the PCI ECAM base (device memory no driver granted it) via the hostile-arg path, reads it at EL0, faults, and the kernel kills it (`thread Q killed, el0 fault at 0x0000004010000000`) before its post-read line prints, proving the driver confinement from outside (where X shows a thread cannot read kernel RAM, Q shows it cannot read un-granted device MMIO); both suites assert the kill line. Done (D2141): the drivers now hold their device's interrupt, and the entropy server is notification-driven -- pci.enable_device clears the INTx-disable bit, gic.enable_spi enables the four QEMU-virt PCIe INTx SPIs (INTIDs 35-38) routed to this core, the exception handler reads every virtio ISR to ack (no storm) and signals notification 1, each server is granted that notification cap; the transport split into ring_submit/ring_poll + entropy_begin/collect_written so the entropy server submits, os.notify_wait(1), then collects (bounded-spin fallback), and the timer also signals notification 1 as a wake-up safety net so a mis-routed interrupt never hangs. The kernel prints `virtio irq ok` when a real device interrupt fired; both suites assert it. Verified under QEMU. Done (D2142): the console server is full duplex -- virtio.console_echo sets up port 0's receiveq (queue 0) and transmitq (queue 1), transmits the prompt, posts a device-writable receive buffer, and echoes the bytes the host feeds it; run.sh attaches the virtconsole chardev with input-path (a Linux-QEMU feature) feeding `echo-me` and asserts both the prompt and `echo-me` appear in the output file (the receive->transmit round-trip), while run.ps1 omits input-path (Windows QEMU rejects it) so the receive times out gracefully and it asserts the prompt alone. Verified on both hosts. C103 COMPLETE: PCI ECAM, modern transport, three EL0 driver servers holding only their frames and interrupt (entropy notification-driven, all confined -- a stray device access kills the offender), disk read/write, console echo. Closes NeperOS D2119 stage 1; stage 2 (the AVF guest on a Pixel) is next. Block and console poll their rings (they hold the interrupt cap and their interrupts are handled; blocking on it as entropy does is a later refinement). The byte-identical stage2==stage3 and Linux boot run in the full suite (needs a host that completes the Linux self-host build).

### C105 — NeperOS shell 1: processes loaded from the initrd

Queued by D2148 (phone shell, path A). Begun D2150 (os.launch/os.reap syscall surface). CLOSED D2151, verified on QEMU virt (no crosvm): the initrd becomes a program archive (4-byte magic 0x4E455041, count, per-program 8-byte offset+length, programs 8-byte aligned; assembled by scripts/build-shell-archive.py from separately built aarch64 neperos images), selected by a shell boot argument so the default A-Z capability demo is byte-unchanged. On -append shell the kernel parses the archive and starts program 0 as init in its own address and capability space. A process is a thread with a parent (the launcher), an exit code and a reaped-child slot; launch(index) svc 11 builds a process parented to the caller, reap(child) svc 12 returns an exited child code or blocks, exit svc 1 records os.exit code and a fault records the all-ones sentinel, either waking a parent blocked reaping that child and freeing its slot. Boot shows: shell init up; el0 prog A exit 7; el0 prog B faulting; thread child killed el0 fault at 0x0; shell child A code 7; shell child B killed; shell init done; all threads done; neperos: exit 0 -- archive loading, the three syscalls, and a fault in one process not stopping another. Added to run.ps1 and run.sh as a second NeperOS boot. Next: C106 (filesystem server on virtio-block).

### C106 — NeperOS shell 2: a filesystem server on virtio-block

Queued by D2148. Foundation D2152 (block layer, on-disk format, fswrite/fsread direct-access boot). CLOSED D2153, verified on QEMU virt on BOTH hosts (Windows run.ps1, Linux/WSL run.sh), two boots on one disk image. The filesystem is an EL0 user-mode server (fs_server.e) started via start_driver_server so it ALONE holds the block device's capability; clients reach it only over IPC. On-disk format gains directories: mkdir allocates a 16-entry directory block and links it under its parent (kind DIR), paths resolve component by component; fs.e adds stat (open/size), list (newline-separated entry names) and remove (clears the entry). IPC protocol (fsproto.e) over thread.e's one-word synchronous rendezvous: op word, length-prefixed path bytes, write data likewise; reply result word then read/list payload or open size; op 0 = quit. The fsserver boot assembles an archive of three programs: fs_server (block cap + request endpoint slot 2 recv, reply endpoint slot 3 send); fs_client (request-send slot 1, reply-recv slot 2, scenario from the boot arg); fs_denied (NO endpoint granted, so its first send is refused with the all-ones sentinel -- the capability gate). The server owns formatting and formats only a blank disk, so a reboot keeps what was written; server ASID 1, clients from 2 (last_server_index carries the server's thread index out of start_driver_server). Boot 1 (fresh, fswrite): fs server formatted, fs denied, mkdir /docs ok, write /docs/greeting ok, open size 17, close ok, list /docs: greeting, list /: docs. Boot 2 (same disk, fsread): NO reformat, `fs client read: hello neperos fs` read back byte for byte across the reboot through the server, remove ok, empty list /docs. Fixtures assert each line independently (the scheduler orders the denied vs real client differently per host). open/read/write/close/list/mkdir/remove all served over IPC; persistence and the capability refusal both proven. Default A-Z, C105 shell, and D2152 fswrite/fsread boots unchanged.

### C108 — NeperOS shell 4: a virtio-gpu display server

Queued by D2148. CLOSED D2159, verified on QEMU virt on BOTH hosts. A virtio-gpu 2D driver (virtio.gpu_* in neperos/src/virtio.e) runs as an EL0 user-mode server that alone holds the scanout (start_driver_server, pci.VIRTIO_GPU=16): over the control queue it reads the display mode (GET_DISPLAY_INFO -> 1280x800), creates a BGRA resource (RESOURCE_CREATE_2D), attaches a framebuffer as backing (RESOURCE_ATTACH_BACKING), paints a deterministic pattern, sets the scanout (SET_SCANOUT), transfers the backing to the host (TRANSFER_TO_HOST_2D) and flushes it (RESOURCE_FLUSH) -- the full 2D path, reusing the block driver's 2-descriptor chain. The framebuffer is ~4 MB so start_driver_server's pool size became a module var (driver_pool_bytes) the `-append gpu` boot raises to 4 MB. scripts/neperos-screendump.py boots with virtio-gpu-pci + a QMP socket, waits for the flush line, QMP-screendumps the scanout and prints its SHA-256; the suite checks the golden d505a446eda5a1fcd82529d0167bcf6f4784f91c91cb00825b96bb2ba60aa1be, identical on QEMU 8.2 (WSL) and 11.1 (Windows). gpu_test.e holds the scanout with a bounded spin after flush so the capture wins before poweroff. Trap: channel values u8(x)/u8(x+y) overflow past 255 (narrow-check traps) -> mask & 255. Fixtures in run.ps1/run.sh. Default A-Z/shell/fs boots unchanged.

### C109 — NeperOS shell 5: touch and key input over virtio-input

Queued by D2148. CLOSED D2160, verified on QEMU virt on BOTH hosts. A virtio-input driver (virtio.input_open/input_next, pci.VIRTIO_INPUT=18) runs as an EL0 server (input_server.e) that alone holds the device and the notification the kernel bound to its interrupt: it posts device-writable 8-byte event buffers on queue 0, blocks on os.notify_wait until input arrives (interrupt-driven), drains the burst and pushes each event to a client over endpoint 0 as one packed word (type<<48|code<<32|value, single-word rendezvous so multi-sender/multi-word never interleaves); a sentinel (type 0xFFFF) ends the stream. The event shape is the Linux input_event, so the same driver serves a keyboard and an absolute-pointer tablet. input_client.e holds only the receive endpoint (slot 1), unpacks and prints. The `-append input` boot = archive [input_server, input_client] with the endpoint caps wired. scripts/neperos-input.py boots with virtio-keyboard-pci or virtio-tablet-pci + a QMP socket and injects via input-send-event. Verified: key 'a' -> EV_KEY 30 down/up + EV_SYN; tap -> EV_ABS x/y (3 0 16384, 3 1 16384) + EV_KEY BTN_LEFT 272 down/up -- all over IPC, both device kinds, the client receiving the stream. Fixtures in run.ps1/run.sh. Default A-Z/shell/fs/gpu boots unchanged.

### C110 — NeperOS shell 6: a compositor and the e.ui backend for NeperOS

Queued by D2148. Acceptance: app surfaces in shared frames, damage-only flush to the C108 display server, input from C109 routed to the focused surface; an e.ui window backend over it drawing with the existing CPU rasterizer (gfx/scene) and fonts read from the filesystem; an existing e.ui sample renders on NeperOS with the same pixel hash as its host render at the same size. BEGUN D2161: the existing CPU rasterizer draws on NeperOS. The virtio-gpu pipeline (C108) split into gpu_begin (mode+resource+backing+scanout, returns the framebuffer) / gpu_present (transfer+flush), so a program paints its own pixels (gpu_bringup = begin + test pattern + present, C108 golden byte-unchanged). neperos/src/ui_scene.e draws with e.gfx.paint (the rasterizer e.gfx.scene uses, pure over geometry+math, compiles for neperos with nothing new): background + panel + an anti-aliased triangle rasterized to a coverage mask and composited into the framebuffer, then flushed. Screendump golden 172a747560e4f73a0de393838fb20f3a8d750cb77e6b9a65328d657fa4cbd86c identical on QEMU 8.2 and 11.1, so NeperOS pixels equal a host render of the same scene. D2162: a compositor over SHARED surface frames -- vm.map_phys_at maps one physical surface into two spaces at vm.SHARED_FRAME_VA (thread.ttbr_of exposes each space); the `-append compositor` boot runs comp.e (owns the gpu display) + comp_app.e (draws a e.gfx.paint scene into the shared surface, signals over an endpoint); the compositor composites it into the display and flushes; golden 1e78b507... both hosts. D2163: input from C109 routed to the focused surface -- the compositor boot grows to comp + comp_app + the C109 input_server on two virtio devices (input MMIO threaded past comp_bar); three endpoints (app-ready, input-in, route-out); a QMP key travels keyboard -> input_server -> compositor -> app, which prints `app input ev 1 30 1` then `app done`, both hosts. D2164: damage-only flush -- gpu_present_rect transfers+flushes just the app's rectangle after a full background present; compositor golden unchanged (1e78b507), now via the damage path; the input server is optional (started only with a third archive program + an input device) so one compositor binary serves both the screendump and routing boots. REMAINING: the e.ui window backend over e.gfx.scene + fonts from the filesystem with an e.ui sample matching its host render -- the large part needing e.gpu CPU backend, e.gfx.scene and e.ui compiled for NeperOS. D2165: e.gpu's CPU backend now COMPILES and LINKS for aarch64 neperos -- added os.Lib/dlopen/dlclose/dl_lookup/current_thread_id to os.neperos.e (dl_lookup satisfies the intercepted os.dlsym; Unsupported, Vulkan path pruned under the CPU backend) and futex wait_u32/wake_one/wake_all stubs to the runtime (single-core cooperative schedule -> a lock is a correct spin). It does not yet RUN: gpu.open(.Cpu) fails because the program arena is only 64 KB (vm ARENA_SIZE) -- the next prerequisite is a large program arena (a user-address-space change), then e.gfx.scene + e.ui atop it, the window backend on the compositor's shared surface with fonts from e.fs, and an e.ui sample matching its host pixel hash. Existing fixtures byte-unchanged (C108 golden d505a446 verified). D2166: e.gpu's CPU backend RUNS on neperos -- a program can be given a large arena in its own mapped EL0 region (driver_arena_bytes + with_big_arena, in start_driver_server and start_process), and the kernel arena grew 16MB->64MB (link_image_a64) to carve it; `-append gpu bigarena` gives a 16MB arena and gpu_cpu.e prints `gpu cpu open ok` both hosts (C108 golden d505a446 unchanged). D2167: e.gfx.scene renders through e.gpu's CPU backend on NeperOS -- scene_test.e compiles a two-rectangle scene to a display list, renders it into an offscreen Bgra8 target and folds the read-back pixels to a hash (2632735557), identical on NeperOS and the host because the rasterizer is pure; the suite renders the same source on the host, reads its hash and requires the QEMU run to print it. Blocker was e.gpu's reentrant device mutex: os.neperos.current_thread_id() returned 0, read as 'no owner', so a nested device lock on the one thread re-locked a held mutex and hung; it now returns a fixed non-zero id (one thread per NeperOS program). C108 golden d505a446 and the other neperos fixtures byte-unchanged. D2168: the FULL e.ui stack renders on NeperOS matching its host hash -- neperos/src/ui_test.e is the host ui_testing fixture verbatim (e.ui.testing over e.ui.widget -> e.gfx.scene -> e.gpu CPU backend: a box+button tree pumped, found, pressed, snapshotted, compared to a golden; plus e.ui.animation), snapshot folds to hash 2725760869 identical host==neperos, suite checks the host hash + `ui testing ok`. Built: (1) os.neperos.e window/window-event/clipboard/monitor/accessibility types+fns (window.e/input.e/accessibility.e type-check against them), all Unsupported since the headless path is pruned; (2) THE BUG -- the EL0 window was a fixed 512KB region, so a >512KB program overran vm.create's unbounded image copy into kernel memory (wild kernel fault). vm.create now sizes the window to the image (image|arena|args|stack), caps at the 2MB L3 reach, carries arg_off+size in Space, bounds console/device writes by the thread's window; map_stack scans skipping the window. C108 d505a446, ui_scene 172a7475, compositor 1e78b507, fsserver persistence, D2167 scene hash all byte-unchanged both hosts. D2169: the e.ui window backend PRESENTS over the compositor -- os.neperos.e window_open/metrics/present/poll stopped being Unsupported (a NeperOS window IS the compositor's shared surface): window_present blits the Bgra8-as-u32 pixels into vm.SHARED_FRAME_VA and signals the compositor on slot 1, window_poll answers ok/no-event. neperos/src/ui_window.e opens an e.ui.window 256x256, renders a 3-rect e.gfx.scene through the e.gpu CPU backend into window.draw_target, presents via window.request_frame -> os.window_present; wired as the compositor-boot app, the compositor composites+flushes it -- screendump golden 08af9c12 identical QEMU 8.2+11.1, serial `ui window presented`/`comp composited flushed`. The compositor boot gives its app the 16MB arena on `bigarena` (so comp golden 1e78b507 boot unchanged). CPU backend renders cross-queue (renderer's queue vs window's), so no queue accessor needed. D2170 CLOSES C110: e.ui text renders from a font READ FROM THE FILESYSTEM -- neperos/src/ui_font.e (program 1 of an fsserver archive) stores a synthetic TTF in the C106 server via fs.write_file, reads it back via fs.read_file, registers the reloaded font and renders a glyph through e.gfx.scene DrawText over the e.gpu CPU backend; frame hash 173685445 identical QEMU 8.2+11.1, `ui font from fs` proves the round trip; fsserver boot gives program 1 the 16MB arena on `bigarena`. Acceptance met across D2161-D2170: shared-frame surfaces (D2162), damage flush (D2164), input routing (D2163), e.ui window backend over the compositor (D2168 renders/D2169 presents) with fonts from the filesystem (D2170), and an existing e.ui sample matching its host pixel hash (D2168 hash 2725760869).

### C111 — NeperOS shell 7: system status services

Queued by D2148. Acceptance: one status protocol with subscription for battery (level, charging), Wi-Fi and cellular signal and type (5G/LTE), wall clock and notification count, plus a notification service that apps post to; QEMU providers answer what virt has (no battery, no radio) and say so rather than inventing values; the D2148 Android bridge later supplies the real ones behind the same protocol. D2171 CLOSES C111: neperos/src/status_server.e is an EL0 status service holding battery/Wi-Fi/cellular/wall-clock/notification-count and serving one protocol over a request endpoint (subscribe/query/post/quit) and a reply endpoint (a five-word snapshot). Each provider word has a present bit; QEMU virt has no battery or radio so those are 0 (read as unavailable, not invented); the clock is real via os.clock(.Wall); the notification service is the post op (count rises, pushed to the subscriber). status_client.e subscribes, reports each field, posts and reports the count 0->1. `-append statussvc` boot, no device/disk; verified both hosts (clock value varies -> presence asserted). Snapshot layout holds real battery/signal/type for the D2148 Android bridge behind the same protocol.

### C112 — NeperOS shell 8: the launcher -- wallpaper, 8x5 icon grid, top bar

Queued by D2148. Acceptance: a launcher process the init program starts after boot; a PNG wallpaper from the filesystem scaled to cover; an 8-row by 5-column grid of app icons with labels, paged when there are more than 40; a top bar showing battery, Wi-Fi, 5G, clock and notification count from C111; a tap launches the app as a process and Home returns to the launcher; QEMU screendump golden plus a launch-and-return round trip. BEGUN D2172: neperos/src/ui_launcher.e renders the launcher's visual skeleton -- a cover wallpaper fill, a top bar with five status ticks, and the 8x5 icon grid (one shaded tile per cell) -- through e.gfx.scene over the e.gpu CPU backend into a 256x256 surface; frame hash 3700568229 identical host==neperos (QEMU 8.2+11.1), suite reads the host hash and requires the neperos run to print it. (module-scope `const X: f32` trips the location-less E-TYPE-9999, so layout constants are inline.) Not yet: a PNG wallpaper from the filesystem scaled to cover; labels and real app icons; the live C111 status in the top bar; presentation over the compositor; a tap launching an app as a process and Home returning to the launcher; the screendump golden and launch-and-return round trip. D2173: the launcher is PRESENTED OVER THE COMPOSITOR -- neperos/src/launcher.e opens an e.ui.window (the shared surface), renders the launcher layout and presents via window.request_frame -> os.window_present; wired as the compositor-boot app, the compositor composites+flushes it; screendump golden 132a969b identical QEMU 8.2+11.1, serial `launcher presented`/`comp composited flushed`. A visible launcher on the display. D2174: a PNG WALLPAPER from the filesystem scaled to cover -- ui_wall.e encodes a small image to PNG (e.fmt.png/deflate), stores it in the C106 server (fs.write_file), reads it back (fs.read_file), decodes (png.decode) and draws it with DrawImage over the whole 256x256 surface (scale-to-cover), then the top bar and grid; frame hash 3999367205 both QEMU, `ui wall from fs` proves the round trip. Needed the EL0 stack grown 128KB->512KB (deflate is stack-heavy; faulted EC 0 at a prologue) -- still under the 2MB window, goldens re-verified unchanged. A C106 file is one 512B block, so the source is 4x4 (PNG 136B). D2175: the top bar shows the LIVE C111 STATUS -- launcher_status.e subscribes to the C111 service, posts a notification, and renders the top bar with a tick per provider (dim since battery/Wi-Fi/cellular are absent on virt) and a lit tick per notification; it reports each field read (battery/wifi/cellular absent, notifications 1) and folds the frame to hash 155713317 both QEMU (clock not drawn, so deterministic). The status boot grants a rendering client the 16MB arena on `bigarena`; the D2171 plain client is unchanged. D2176: app-icon LABELS -- ui_launcher.e gained a built-in 3x5 bitmap digit font and draws each icon's 1-based index (1..40) on its tile (each lit pixel a scene FillRect); hash 3700568229->3820471609 host==neperos both QEMU (the D2172 fixture reads the host hash so no golden edit). Real app-name labels need a multi-glyph font, which needs multi-block C106 files (a TTF exceeds the 512B block; no reusable bitmap font; e.asset needs a project build) -- index labels render the path meanwhile. D2177: the launcher PAGES past 40 icons -- ui_pages.e renders a 45-app launcher, page 0 icons 1..40 + page 1 icons 41..45 each with a page-dot row; the two pages fold to different hashes (2270960265 / 587139337) identical host==neperos both QEMU. Real app-NAME labels still want multi-block C106 files; index labels (D2176) stand in. D2178: TAP-TO-LAUNCH + HOME round trip -- tap_launcher.e (program 1 of the input boot, app program 2) receives a forwarded key (C109 path), on the first key-down launches the app (os.launch index 2), reaps it (os.reap -> code 5) and returns Home; serial `launcher tap`/`launched app`/`tap app ran`/`app code 5`/`launcher home` both QEMU. All C112 feature clauses now demonstrated (D2172-D2178). D2192: the UNIFIED SHELL now exists -- neperos/src/shell.e is one binary that renders the launcher over the real compositor AND is interactive: archive [comp(0), shell(1), input(2), app(3)], the `compositor bigarena` boot runs comp+shell+input, shell presents the launcher (compositor composites it to the display), takes a LIVE key the compositor routes to it (C109 path), os.launches the app (program 3), reaps it (code 5) and returns Home. Verified via neperos-input.py: `comp ready`/`shell presented`/`comp composited flushed`/`shell tap`/`shell launched app`/`tap app ran`/`shell app code 5`/`shell home`, fixtures in run.sh+run.ps1. Built on the proven compositor-input topology (one start_process beside comp+input), which SIDESTEPS the prodshell AUX heisenbug entirely (comp reads its AUX at boot, before any runtime os.launch); neperos-input.py now adds the virtio-gpu for `compositor bigarena` too. C112 -> 0.98: a single launcher binary hosts apps over the compositor with live tap input (the hard part of the gap clause). D2193: the shell now also shows live STATUS -- it reads the wall clock directly (os.clock -> PL031 RTC) and renders the current HH:MM in its top bar, printing `shell status HH:MM` (seen `shell status 10:49`); a DIRECT read inside the one shell process (not a separate C111 status-server, which would be a 2nd start_process = the heisenbug trigger). So the single binary wires compositor+input+status(+app-launch); fixtures assert `shell status`. C112 -> 0.99. The last gap-clause item is the fs WALLPAPER (the shell draws a baked fill, not one read from the C106 server): the fs server is a 2nd start_process = the heisenbug trigger, so strict 1.0 needs the heisenbug fix OR a decision that a baked/direct wallpaper + direct status satisfy fs+status in the clause. D2194: the heisenbug was never a kernel bug -- the boot word prodshell contained shell, so has_word started the shell init beside the compositor; has_word now matches whole words. D2195: the unified shell now reads the C111 status SERVICE as a second process (boot `compositor bigarena unified`, archive comp/shell/input/app/status, endpoints 3 request and 4 reply): it subscribes, posts a notification, draws a tick per provider and the notification, and the clock from the snapshot (`shell status service notes 1`, `status server done`). An ASID collision (input server and status process both ASID 3) faulted the status server until next_asid was set above it. D2196: the WALLPAPER now comes from the C106 filesystem inside the unified shell -- the fs server (program 5, sole holder of a virtio-blk disk, ASID 5, endpoints 6 and 7) and a loader process (wall_loader.e, program 6) that writes and reads /wall.png and sends the 136 bytes to the shell over endpoint 5 (e.fs fixes its endpoints at slots 1 and 2, which the shell's compositor and input already hold); the shell decodes the PNG and draws it scaled to cover under the top bar and grid (`shell wallpaper from fs`, screendump checked by eye on QEMU 11.1). C112 -> 1.0: one boot hosts compositor, input, status service, filesystem wallpaper and tap-launch-return.

### C117 — NeperOS networking: a virtio-net driver, TCP/IP, DNS and TLS for the apps

Queued by the user (2026-10-08). NeperOS runs with `-nic none` and has no network, so every app that needs the internet is blocked: Stocks live data (C118), Weather, the AI chat app, Mail, Browser. Acceptance: (1) a virtio-net driver server on the QEMU virt machine (user-mode networking), (2) IPv4 with ARP, DHCP, ICMP echo, UDP and TCP, (3) a DNS resolver, (4) TLS 1.3 client with certificate validation against a bundled root set (e.crypto has the primitives), (5) a socket-like capability for apps (connect, send, receive, close) under the capability model, (6) a fixture on QEMU that resolves a name and fetches an HTTPS page from the host through user-mode networking. Not queued here: IPv6, a server side, Wi-Fi or cellular drivers. DONE: (1) virtio-net driver (D2244); (2) ARP, DHCP, ICMP echo, UDP in inet.e and a stop-and-wait TCP client in tcp.e (D2244, D2245); (3) DNS A-record resolver; (4) TLS 1.3 over the TCP client with the chain and the host name validated against a trust store shipped as an initrd archive entry (the 105 Mozilla roots e.crypto can verify with), entropy from a random server over IPC (D2246, D2247); (5) the socket capability: two endpoint slots to a network server that resolves, connects and runs TLS, protocol netproto.e, client netclient.e; the unified boot starts the servers when a network device exists and grants every launched app the two ends, checked by hand with an app launched from the home screen (D2247); (6) the fixture, in both run scripts: the app resolves neper.test through a host DNS responder, fetches a page over TLS 1.3 and over plain HTTP, is refused under a wrong name and a closed port; passes on Windows (QEMU 11.1) and WSL (QEMU 8.2.2), 4 s. Measured on the real internet: www.python.org validates against the Mozilla roots and answers 200. LIMIT: e.crypto verifies only SHA-256 signatures over RSA and P-256, so chains with ECDSA-SHA384, a P-384 root or RSA-SHA384 (example.com, github.com, wikipedia.org, letsencrypt.org, stooq.com) are refused -- C144; the suite fixture does not cover the unified-boot path. D2248: a 64-byte aux area overwrote the network server's image (462 KB), which showed as a 260 KB string literal decoding to garbage; fixed, aux now has a page of its own. FINAL: C144 landed, so the Mozilla roots now validate the chains of example.com, github.com, letsencrypt.org, stooq.com and google.com as well as python.org (D2249).

### C144 — NeperOS TLS: SHA-384, ECDSA P-384 and RSA-SHA384/512 verification, so the real internet's chains validate

Queued 2026-10-08 from C117. The network server validates a TLS chain against the Mozilla roots, but e.crypto verifies only Ed25519, ECDSA P-256 with SHA-256 and RSA with SHA-256, so any chain carrying an ECDSA-SHA384 signature, a P-384 key or an RSA-SHA384/512 signature is refused: of the sites tried only www.python.org validates; example.com, github.com, wikipedia.org, letsencrypt.org (ECDSA-SHA384, P-384 roots) and stooq.com (RSA-SHA384) do not. Acceptance: (1) e.crypto.hash sha384 (SHA-512 with its own IV, truncated), checked against published vectors; (2) ECDSA verification over a P-384 curve in e.crypto.sign with SHA-384 and SHA-256 digests, checked against Wycheproof or NIST vectors; ECDSA P-256 verifying a SHA-384 digest (leftmost 256 bits); (3) RSA PKCS1 v1.5 with SHA-384 and SHA-512 and RSA-PSS with SHA-384 in x509 chain verification; (4) x509 parses P-384 public keys and the TLS client accepts ecdsa_secp384r1_sha384 and rsa_pss_rsae_sha384 CertificateVerify; (5) scripts/gen_roots.py keeps the P-384 roots (40 are dropped today); (6) net_real.e reaches example.com, github.com and wikipedia.org over TLS on QEMU user-mode networking, and the new vectors pass on Windows and Linux. DONE (D2249): sha384; ECDSA P-384 in Montgomery form with SHA-256/384/512; P-256 over SHA-384/512 digests; RSA PKCS#1 v1.5 and PSS with SHA-384/512; x509 P-384 keys and the ecdsa-SHA384/512 and sha384/512WithRSA algorithms; TLS offers and verifies the new schemes; the trust store keeps the 40 P-384 roots; EncryptedExtensions tolerates supported_groups. crypto_sign_wide (72 checks against hashlib and Python's cryptography) passes on Windows x64 and Linux x64 (WSL); example.com, github.com, letsencrypt.org, stooq.com and www.google.com answer 200 over validated TLS on QEMU user-mode networking, wikipedia.org answers 403.

### C115 — NeperOS shell 11: the Pixel 9 Pro screen, the Neper crater wallpaper, SVG icons and the lunar look

Queued by the user (2026-10-07). Acceptance: (1) the display is the Pixel 9 Pro's 1280x2856 (20:9): the compositor, virtio-gpu scanout and pool, shared frame, window region and renderer arena are sized for it and refuse a surface they cannot hold with a message; (2) the wallpaper is the Desktop neper-crater image, resampled offline to the panel and shipped as an initrd archive entry that a loader reads through a kernel call (research: docs/neperos-display-research.md; the C106 file is one 512-byte block), decoded once and drawn 1:1 as a static layer; (3) e.gfx.svg, a documented SVG subset drawn into e.gfx.scene, with a pixel-probing fixture on every host; (4) rectangular app icons and top-bar icons authored as .svg files and drawn through it; (5) the look follows the lunar theme specs (Desktop pixel_9_pro_lunar_theme_typography_specs.md): Jost for the clock, date and launcher labels, Sora for notification headers and widget titles, Space Grotesk for system status, Exo 2 for notification bodies, all OFL, with the mock-up's layout (clock, date, moon-phase card, notification card, dock). DONE: e.gfx.svg (D2198): shapes, paths with arcs, transforms, currentColor, style declarations, opacity; fixture gfx_svg passes on Windows x64 and Linux x64 (WSL); modules.json, modules.md and module-apis.md updated. Research note written (D2199). D2200: eight rounded-rectangle app icons (clock, calculator, tasks, settings, camera, files, gallery, messages) and five top-bar glyphs (wifi, cell, battery, bell, moon) authored as .svg under neperos/assets/icons, embedded by scripts/gen_icons.py into neperos/src/icons.e, drawn by the shell's launcher grid and top bar (status glyphs dim when a provider is absent, the bell amber with notifications) and by icon_sheet.e, a host contact sheet. D2201: the display path is 1280x2856 end to end -- virtio-gpu scanout (QEMU xres/yres), a 16.6 MB compositor pool, a shared frame of 3570 pages mapped across seven level-3 tables at USER_BASE + 2 MB (vm.map_shared), a 64-bit-copy compositor, window_present at the new stride, a shell arena sized from the screen (160 MB) on a 400 MB-arena display kernel and a 1 GB machine; the shell lays out in dp (412 wide, scale 3.107) with a four-column icon grid; the comp, ui-window and launcher screendump goldens are re-pinned and identical on QEMU 11.1 (Windows) and 8.2.2 (WSL); the unified shell boots to its tap-launch-return round trip in about 9 s. D2202: the neper-crater wallpaper -- scripts/make_wallpaper.py resamples the Desktop JPEG (688x1552) offline to exactly 1280x2856 (cover fit, Lanczos, 8-bit grey PNG, 1.84 MB), shipped as an eighth archive entry that the kernel maps into the shell and passes as args[1] (read in place); the shell decodes it, uploads it as a texture and draws it 1:1 under the icons; the whole unified boot takes about 13 s under QEMU; the filesystem-loader wallpaper still works for a seven-entry archive. D2203: icons for every app in the Desktop ux folder -- twelve new rounded-rectangle SVG icons (phone, mail, browser, maps, compass, chat as the Lunar Comms satellite, meet, recorder, translate, steps, lunatris, mfa) beside the existing eight (messages, camera, gallery for photos, clock, calculator, tasks, files, settings): twenty, shown as five rows of four on the home screen. D2204: the lunar fonts and the lock screen -- Jost Bold/Regular, Sora Medium, Space Grotesk Regular and Exo 2 Regular (SIL OFL, cut static and subset by scripts/make_fonts.py, 75 KB in all) ride in the initrd as archive entries 8-12 and reach the shell as args[2..6]; neperos/src/text.e lays text out with e.text.layout and draws it through e.gfx.scene; the shell boots to a lock screen (clock, date, a Moon-phase card computed from the wall clock by lunar.e, a notification card, a dock) over the crater wallpaper, a key unlocks it to the home screen (status bar, twenty icons with names), a second key launches an app; the compositor takes the second frame through a lockstep protocol the shell announces; Phone is redrawn as a ringing smartphone, Comms is now Chat with two faces talking, Steps is footprints; fixtures in run.ps1 and run.sh (two key presses). D2205: icon taps and the first app screen -- the shell tracks the tablet's pointer, hit-tests the home screen and launches the tapped icon's app; Lunar Calc (lunar_calc.e, from ux/calculator.jpg) is a real calculator on cream cards (digits, point, + - x /, =, C, +/-, sqrt, DEL; 7 x 6 + 9 = 51 verified by taps) over appkit.e, the shared plumbing for full-screen apps (window, scene in dp, taps from the routed events, the compositor's per-event answer); the kernel starts a launched app with a 205 MB arena, the fonts as arguments, the shared frame and the two endpoints; a tap on the home bar returns to Home. Verified on QEMU 11.1 and 8.2.2 (WSL). D2206: Calc (renamed from Lunar Calc; the Lunar and Moon wording is dropped from the app) gains three tabs -- Basic, Scientific (sin, cos, tan with a DEG/RAD tag, log, ln, exp, pi, x^y, verified: sqrt 9 = 3, sin 30 = 0.5, 2^10 = 1024) and Convert, with the ten categories of Android's unit converter less currency (length, area, volume, mass, temperature, time, speed, data, energy, angle; verified 100 C = 212 F); the virtio-input driver now returns each event buffer to the device. D2207: Clock -- the app behind the Clock icon, with the parts of Android's Clock: Alarm (up to five, repeat days, on/off, edit with steppers, Snooze and Dismiss when one rings), Clock (UTC time, date, up to six cities with standard-time offsets, a city picker), Timer (typed HH:MM:SS or presets, Start, Pause, Reset, +1:00, Time's up), Stopwatch (Start, Stop, Lap, Reset, a lap list) and Bedtime (wake-up time and sleep goal give the time to go to bed); the input server sends a 500 ms tick in the unified boot so the running displays update. Verified on QEMU 11.1. D2208-D2210: every Clock tab follows Android's layout (rows, round buttons, bottom navigation; the Stopwatch has the analogue dial and sub-dial) in the cream, amber and dark palette. Tasks (neperos/src/tasks.e, D2211): lists, round checks, due chips, stars, Completed section, add/edit sheet with an on-screen keyboard, verified on QEMU. Messages (neperos/src/messages.e, D2212): conversation list, bubbles, compose bar with the keyboard, Start chat; the archive limit rose from 16 to 32 entries; Stocks, Weather and SSH icons added (six grid rows). CLOSED 2026-10-08: all five acceptance points are delivered and verified on QEMU; the shell later grew to 29 apps, every one opening on sample data (D2212-D2243), each with a fixture in tests/selfhost/neperos-apps.txt that passes on Windows and WSL. The leftovers this record once listed are their own items: alarms that ring with the app closed (C145), daylight saving in the Clock's cities (C146), and a full suite run that completes on this machine (C147).

### C116 — NeperOS Secure app: one vault for passwords and MFA codes

Queued by the user (2026-10-08). The Secure app (home icon 'Secure', index 18, the shield with a keyhole) keeps both passwords and MFA codes in one place. Acceptance: (1) a list of entries, each a login (site, user name, password, copy and reveal) or an MFA entry (a TOTP secret showing the current six-digit code with a countdown ring), searchable and in the cream, amber and dark look of Calc, Clock, Tasks and Messages; (2) add, edit and delete an entry on the app's own on-screen keyboard; (3) TOTP computed from the secret with HMAC-SHA1 over the wall clock (RFC 6238; e.crypto has the pieces), checked against the RFC test vectors; (4) entries encrypted at rest under a key derived from a master password, which unlocks the app; storage waits on the filesystem server; (5) a fixture on QEMU that adds a login and an MFA entry and reads the code back. Not queued here: sync, autofill into other apps, passkeys. DONE (D2252): the vault is encrypted on disk (PBKDF2-HMAC-SHA-256 key from the master password, AES-256-GCM records with fresh nonces and the record name as additional data) and kept through the filesystem server, one file per entry; create, unlock, wrong-password refusal, add, edit, delete, search, Generate, a code screen; vault.e checked against hashlib and Python's cryptography (11 checks, both hosts); the secure_vault fixture (create, add a login and a code, leave, reopen, wrong password, unlock, read the code back at the RFC 6238 time, search, delete) passes on Windows and WSL. Copy has no clipboard to copy to: C148. The kernel now starts the filesystem and random servers in the unified boot when their devices exist and grants Secure alone the storage and random endpoints (thread.CAPS 8 to 10).

### L069 — Chart parity: 3-D scatter, histograms and density surfaces

Planning only (D1816). Specify the missing 3-D part of L062: scatter points, bivariate histogram columns and density surfaces over existing e.gfx.mesh/scene and statistics. Require count/KDE reference fixtures, projection/camera and clipping/depth checks, non-finite and degenerate-domain refusal, caller-storage bounds and rendered examples. Share the planned 3-D adapter with existing surface/wireframe work. Full acceptance gates and official sources: docs/charting-engine-plan.md, vendor comparison additions L068-L075. DELIVERED under L061/L062 (D2105-D2121): `scatter3d`, `histogram3d` (over `bin2d`), `density_surface3d` (over `e.algo.stat.kde2d`) and `wireframe3d` share one camera and viewport (`viewport3d`/`project3d`), with fixtures gfx_chart_scatter3d, gfx_chart_histogram3d and gfx_chart_surface3d and the previews scatter3d, histogram3d, density_surface3d and wireframe3d. CLOSED (D2253) with the missing gates: scripts/chart_3d_reference.py writes the gfx_chart_3d_reference fixture (51 checks, Windows x64 and Linux x64): the cube frame under three cameras (azimuth 42/-120/200, elevation 30/15/-40, distance 4.5/3/6) against an independent re-derivation of the projection and viewport fit including the single-precision rounding; a six-point cloud's projected points, f64 depths, far-to-near order and normalised extents; the density surface against a direct product-Gaussian double sum (1e-12) and its grid; the histogram's counts (maxima in the last bin, top row first) against a Python binning; and the refusals -- NaN and infinities in x, y or z, a length mismatch and an empty cloud, azimuth beyond +-360, elevation beyond +-90, distance under 3 and a NaN camera, zero and negative bounds, a flat-elevation histogram, zero columns, an inverted or NaN histogram range, a point outside the histogram domain (refused, never clamped or dropped), an inverted density domain, zero, negative and NaN bandwidths, a NaN sample, a one-node grid, a short value array (TooLarge) and an empty sample, and each of the six scatter storage arrays one element short.

### L070 — Chart parity: choropleth and proportional-symbol maps

Planning only (D1816). Specify the missing geographic part of L062: choropleth and proportional-symbol maps, projections, region-key joins and geographic legends. Reuse e.algo.geo and the common scene backend with caller-provided boundary data. Require projection reference fixtures, area-scaled symbols, missing-region behavior, polygon holes, antimeridian and clipping checks plus previews. No mandatory remote map service. Full acceptance gates and official sources: docs/charting-engine-plan.md, vendor comparison additions L068-L075. DELIVERED under L061/L062 (D2105-D2121): `choropleth` and `proportional_symbol_map` over e.algo.geo's `map_project` (equirectangular and Mercator windows, antimeridian-centred windows, holes, key joins, missing regions), the GeoJSON reader with class legends, scene and SVG adapters, fixtures gfx_chart_maps and gfx_chart_geojson, previews choropleth and proportional_symbol_map. CLOSED (D2254) with the missing gates: scripts/chart_map_reference.py writes gfx_chart_map_reference (78 checks, Windows x64 and Linux x64, mutation-checked): the projections on three windows (equirectangular, an antimeridian window centred on 180 degrees, Mercator as the closed form asinh(tan(lat))) at 21 points to 1e-12; circle area proportional to the value (diameters 2R sqrt(v/max), area ratios 4, 25 and 100, positions from the projection, an absent site drawing nothing and not setting the scale, a zero value drawing nothing); choropleth fractions with a negative minimum, regions with no metric left unfilled, a metric naming no region ignored, equal metrics at the middle and no metrics at all, and ring winding (outer one way, holes the other, whatever order the data came in) against a shoelace sum of the projected vertices; and refusals -- projection: longitude beyond 180, latitude outside the window, a point beyond the half span, NaN and infinities, a zero or over-wide span, a centre beyond 180, a flat or inverted latitude range, a pole, a Mercator window beyond 85 degrees; symbols: negative, NaN, empty key, outside the window, zero or NaN radius, empty input, short output (TooLarge), bad bounds; choropleth: duplicate or empty keys, a NaN or duplicate metric, a hole before its outer ring, a two-vertex ring, a zero-area ring, a vertex outside the window, too few rings, no regions, bad bounds, and each of its three storage arrays one element short. No remote map service is required anywhere; boundary data is the caller's.

### L071 — Chart parity: advanced SPC, ANOM, capability and measurement-system variants

Planning only (D1816). Missing variants: ANOM; Laney P-prime/U-prime; rare-event G/T; Hotelling T-squared, generalized variance and multivariate EWMA; normal/nonnormal/attribute/batch capability; Gage bias/linearity, attribute agreement and Gage run charts. Extend existing planned SPC, capability sixpack and Gage R&R without duplicating them. Keep statistical estimators and subgroup/phase rules outside the painter. Require published numeric fixtures for limits/intervals and special-cause flags, small/invalid-sample cases, singular covariance and common-mark previews. Full acceptance gates and official sources: docs/charting-engine-plan.md, vendor comparison additions L068-L075. CLOSED (D2255) with independent gates: algo_stat_spc_reference (56 checks) and gfx_chart_spc_multivariate_reference (28 checks) against numpy/scipy on Windows and Linux. Defect fixed: hotelling_t2_individuals used alpha/2 for a one-sided statistic; limits now match published values and gfx_chart_hotelling_t2 bounds are tightened.

### L072 — Chart parity: ribbons, gauges, KPIs, decomposition trees and filter/drill events

Planning only (D1816). Missing reusable business visuals: ribbon/rank-over-time, gauge and KPI/target-status compositions and aggregate decomposition trees. Build cross-filter/drill events over L062 selection and reuse chart marks, e.ui collection controls and existing table aggregation. Require tie/missing-category cases, target semantics, child totals, selection identity and accessible labels with rendered examples. Applications bind filters/navigation; preserve D1785's dashboard-framework non-goal and require no AI or Power BI service. Full acceptance gates and official sources: docs/charting-engine-plan.md, vendor comparison additions L068-L075. CLOSED (D2256): audit found the visuals delivered; added hit_rect and tree_subtree_mask (drill/cross-filter selection over rectangle marks and decomposition-tree nodes) with checks in gfx_chart_aggregate_tree on Windows and Linux.

### L073 — Chart parity: mekko, Venn/Euler and word/tag clouds

Planning only (D1817). Missing top-50 BI composition layouts: mekko/marimekko areas, Venn/Euler overlap areas and word/tag-cloud layouts over existing rectangle, set and text marks. Require frequency-proportional areas, overlap semantics, token weighting, stop-word/exclusion policy, small-token legibility, empty-input refusal, caller-storage bounds and scene/SVG output with accessible labels. Full acceptance gates and official sources: docs/charting-engine-plan.md, vendor comparison additions L068-L075. CLOSED (D2257): mekko, euler2, venn3 and word_cloud checked against numpy/scipy references (gfx_chart_composition_reference, 54 checks, Windows and Linux); venn3 now vertically centred.

### L074 — Chart parity: operational state timelines and status histories

Planning only (D1817). Missing Grafana-style categorical-over-time bands: state timelines and status histories over existing segment marks and time scales, distinct from control/run charts. Require abutting-interval coalescing, gap/missing-data rendering, legend identity, out-of-order input refusal and scene/SVG output. Flame/traces stay with e.gfx.trace profiling; no log-agent dependency. Full acceptance gates and official sources: docs/charting-engine-plan.md, vendor comparison additions L068-L075. CLOSED (D2258): state_timeline checked against a Python replay (gfx_chart_state_timeline_reference, 8 checks, Windows and Linux); no library change.

### L075 — Chart parity: paginated reporting compositions

Planning only (D1817). Missing paginated-reporting compositions: in-cell data bars, in-cell sparklines and cross-tab/matrix report bands over existing bar/line marks and table aggregation. Require per-row normalization scope, null handling, header/total bands and scene output; page layout and print drivers stay with host services. Full acceptance gates and official sources: docs/charting-engine-plan.md, vendor comparison additions L068-L075. CLOSED (D2259): cross_tab_report, matrix_report (scopes, subtotals, nulls), in_cell_bars and sparkline checked against a numpy replay (gfx_chart_report_reference, 175 checks, Windows and Linux); no library change.

### L092 — ML-diagnostics plots: PDP/ICE, silhouette, missingness maps

Planning only (D1824). Celvyx datasci parity gap: partial-dependence/ICE curves, silhouette plots and missingness maps over existing line/scatter/matrix marks and e.ml statistics; residuals, lift/gain, calibration and confusion matrix are already planned. Fixtures against reference values plus empty-cluster and all-missing refusal paths. CLOSED (D2260): added ice_curves, silhouette_plot, missingness_map (e.gfx.chart) and silhouette_samples (e.ml.cluster); gfx_chart_ml_diagnostics_reference 109 checks vs numpy and scikit-learn, Windows and Linux; three gallery previews.

### L093 — 2.5D chart styling: 3-D-effect columns, bars and pies

Planning only (D1824). Excel-style 2.5D effect variants (rotation/walls/bevel on 2-D bar/column/pie geometry) are distinct from true 3-D in L069 and unplanned. Minor eye-candy: reuse D1822/D1823 area and rectangle marks with fixed projection parameters. Fixtures for geometry and scene/SVG parity. CLOSED (D2261): extrude_bars and pie_25d added; gfx_chart_25d_reference 76 checks vs a numpy replay with shoelace and wall-arc invariants, Windows and Linux; previews column_25d and pie_25d.

### L094 — Compound pie charts: pieOfPie and barOfPie

Planning only (D1824). Excel compound parity missing: pieOfPie/barOfPie callouts composing the D1822 pie slices with a secondary stacked-bar breakout. Fold into composition work; fixtures for slice-to-breakout totals, connector geometry and small-slice grouping. CLOSED (D2262): compound_pie and small_tail_count added; gfx_chart_compound_pie_reference 65 checks vs a numpy replay with chord-sector area invariants, Windows and Linux; previews pie_of_pie and bar_of_pie.

### L095 — Bioassay plots: Schild, parallel-line, potency, standard curves

Planning only (D1824). Celvyx medical parity gap: Schild plots, parallel-line assays, relative-potency and standard-curve layouts over existing fitted-curve marks; the fits ride queued L015 (Emax/Hill, Michaelis-Menten) but the plot geometries are unplanned. Fixtures against reference bioassay values. CLOSED (D2263): parallel_line_assay (common-slope fit, F parallelism test, Fieller potency limits), schild_plot and standard_curve_readback added; gfx_chart_bioassay_reference 54 checks vs numpy/scipy on Windows and Linux; three previews. Nonlinear Emax/Hill fitting stays with L015.

### L096 — ROC extensions: decision curves, partial AUC, Youden index

Planning only (D1824). Small add-on to planned ROC/PR: net-benefit decision curves, partial-AUC regions and Youden-index markers over the ROC geometry with numeric reference fixtures. No new mark types. CLOSED (D2264): ROC extensions checked against scikit-learn and numpy (gfx_chart_roc_reference, 122 checks, Windows and Linux); no library change, no new preview.

### L097 — QC/agreement extensions: Levey-Jennings, Lin CCC, symmetry, Box-Cox

Planning only (D1824). Small add-ons to SPC/diagnostic plans: Levey-Jennings clinical QC charts, Lin concordance correlation, symmetry plots and Box-Cox transformation plots over existing control-chart and distribution marks, with reference fixtures and small-sample refusals. CLOSED (D2265): levey_jennings (Westgard rules), concordance_plot, symmetry_plot, box_cox_profile and stat.concordance_cc / box_cox_llf added; gfx_chart_qc_agreement_reference 65 checks vs numpy and scipy on Windows and Linux; four previews.

### L076 — Filename-mask matching (TMask parity) in e.text

Planning only (D1819). Delphi TMask parity: `*?[]` sets/ranges with escaping over caller storage, no filesystem coupling (e.fs consumes separately). Pure table fixtures incl. character sets, ranges, negation, escaping and invalid patterns. Ranked pure-testable: zero I/O. Follow-on (D1873): pathspec gitwildmatch (`**`, dir-only markers) for ignore-file parity. CLOSED (D2266): e.text.mask added (matches, matches_any, valid; * ? [set] ranges ! ^ negation, \ escapes, UTF-8 code points, ASCII case folding); text_mask fixture checks 600 fnmatch pairs plus hand tables on Windows and Linux. The gitwildmatch follow-on (D1873) is not done.

### L077 — Dimensioned unit-conversion registry in e.math

Planning only (D1819). ConvUtils/StdConvs parity: dimension registry plus standard length/mass/time/temperature/data families over e.math factors. Pure table fixtures against known conversions. Out of scope: live currency rates. Ranked pure-testable. CLOSED (D2267): e.math.units added (79 built-in units in 7 families, caller-extensible registry, affine conversion); math_units fixture checks 990 pair conversions against exact rational definitions plus identities, round trips and the registry on Windows and Linux.

### L078 — TOTP/HOTP one-time codes in e.crypto

Planning only (D1819). OATH parity missing from e.crypto: HOTP/TOTP generation plus verification-window helper over the existing HMAC-SHA1/SHA256, byte-exact against RFC 4226/6238 vectors. No secret-storage policy (host boundary). Ranked pure-testable. CLOSED (D2268): e.crypto.otp added (HOTP/TOTP over HMAC-SHA1/256/512, look-ahead and skew verification returning the matching counter, zero-padded formatter); crypto_otp fixture checks the RFC 4226/6238 vectors and 310 seeded cases against Python hmac on Windows and Linux.

### L079 — NTP/SNTP packet codec in e.time.sync

Planning only (D1819). Clock-sync algorithms exist (Marzullo/Berkeley/Cristian) but no wire codec: RFC 5905 48-byte NTP encode/decode with pure packet fixtures. Transport stays caller-driven UDP via e.net. Ranked pure-testable. CLOSED (D2269): NTP/SNTP codec added to e.time.sync (ntp_decode/ntp_encode, ntp_request, era-pivoted timestamp conversion, 16.16 shorts, offset_delay, ntp_check_reply); time_ntp fixture checks 150 packets plus conversions against struct and datetime on Windows and Linux.

### L080 — SOAP envelope and WSDL-type codec in e.fmt

Planning only (D1819). Enterprise doc glue missing: SOAP 1.1/1.2 envelope build/parse and WSDL/XSD-type mapping over e.fmt.xml and e.net.http, faults as typed errors. Canned-XML fixtures, no server side. Ranked pure-testable. CLOSED (D2270): e.fmt.soap added (SOAP 1.1/1.2 envelope builder and parser, typed faults, mustUnderstand, WSDL 1.1 operation reader, XSD built-in mapping); fmt_soap fixture compares 32 canned documents, 10 built envelopes and 4 WSDL documents with an ElementTree reference on Windows and Linux; fixed unqualified Role/Detail in the 1.2 fault builder.

### L081 — XSD validation and XSLT core for e.fmt.xml

Planning only (D1819). e.fmt.xml parses but cannot validate or transform: XSD built-in datatypes plus structural validation, and XSLT 1.0 core templates without extension functions, against W3C fixtures. Ranked pure-testable. PART 1 DONE (D2271): e.fmt.xsd built-in datatypes (39 types, lexical validity after whitespace handling) checked on 4,048 libxml2 cases plus a 90-entry spec table on Windows and Linux. Remaining: XSD structural validation (element and attribute declarations, sequence/choice/all, occurs, facets, lists, unions) and the XSLT 1.0 core with an XPath expression evaluator. PART 2 DONE (D2272): e.fmt.xsd.schema structural validation (elements, attributes, all facets, list/union, complex types with sequence/choice/all/any, extension/restriction, ID/IDREF, nillable) checked on 1,810 libxml2 instances with 1,287 error paths plus hand tables on Windows and Linux. Remaining: the XSLT 1.0 core with an XPath expression evaluator. PART 3a DONE (D2273): e.fmt.xpath, a full XPath 1.0 engine (all operators, 12 axes, node tests, predicates, core functions, current/generate-id), checked on 3,302 libxml2 cases plus hand tables on Windows and Linux. Remaining: the XSLT 1.0 core on top of it. Part 3b (D2274): e.fmt.xslt, the XSLT 1.0 core, 645 stylesheet/document pairs equal to libxslt after C14N, plus load refusals. L081 complete.

### L082 — SMTP send transport in e.net

Planning only (D1819). e.fmt.mail parses only: SMTP send (EHLO, AUTH PLAIN/LOGIN, DATA, TLS via e.net.tls) with loopback fake-server fixtures asserting bytes sent. No mailbox storage. Ranked loopback-testable; harnesses exist (net, net_http, net_tls). D2275: e.net.smtp, SMTP submission client with STARTTLS, AUTH PLAIN/LOGIN/XOAUTH2, MAIL/RCPT/DATA with dot-stuffing; scripted byte-exact servers plus a live STARTTLS session on Windows and Linux. L082 complete.

### L083 — IMAP/POP3 fetch in e.net

Planning only (D1819). Mailbox fetch missing: IMAP SELECT/FETCH and POP3 RETR over canned-transcript plus loopback fixtures, reusing the e.fmt.mail parser. No local store. Ranked loopback-testable. D2276: e.net.pop3 and e.net.imap, mailbox fetch clients with STARTTLS; scripted byte-exact servers plus live STARTTLS sessions on Windows and Linux. L083 complete.

### L084 — FTP/FTPS client in e.net

Planning only (D1819). File-transfer client missing: FTP control-channel codec with loopback data-connection fixtures, FTPS via e.net.tls. No server side. Ranked loopback-testable. D2277: e.net.ftp, FTP/FTPS client with real passive data connections; scripted byte-exact control channel plus three live loopback sessions (EPSV, PASV fallback, FTPS) on Windows and Linux. L084 complete.

### L085 — LDAP bind/search codec and client in e.net

Planning only (D1819). Directory access missing: LDAP bind/search over e.fmt.asn1 BER with loopback fixtures; complements queued L045 (JOSE/OIDC/SAML/SCIM). Ranked loopback-testable. D2278: e.net.ldap, LDAPv3 client (BER, RFC 4515 filters, binds, search/compare/add/modify/delete, StartTLS) checked against ldap3 on 241 filters and a 13-request conversation plus a live StartTLS session, Windows and Linux. L085 complete.

### L086 — mDNS/DNS-SD discovery in e.net

Planning only (D1819). LAN discovery missing: mDNS packet codec plus browser/responder with multicast loopback fixtures; pairs with e.dist for the sync half (Tethering discovery parity). Ranked loopback-testable. D2279: e.net.mdns, mDNS/DNS-SD responder, browser cache and discovery, checked against python-zeroconf (17 responder cases, cache expiry/goodbye/flush) plus a loopback UDP exchange, Windows and Linux. Multicast group join is not in e.net. L086 complete.

### L087 — Ribbon-style command UI in e.ui.navigation

Planning only (D1821). Office-ribbon parity missing with no equivalent planned: contextual tabs, groups, galleries and quick-access bar over the existing command/action model, tabs and collections, with collapsed mode, keyboard traversal and accessible roles. Vcl.Ribbon units are absent from this snapshot too; no third-party dependency. Fixtures for tab switching, gallery layout, collapse and semantics. D2280: navigation.ribbon, an Office-style ribbon over the command/action model: quick-access bar, tabs with contextual bands, groups of large/small/toggle/split/dropdown/gallery commands, collapsed mode with a floating panel, tab and panel keyboard traversal, accessible roles; fixture ui_ribbon on Windows and Linux, previews in docs/ui-previews. L087 complete.

### L088 — Custom title-bar panel in e.ui.window

Planning only (D1821). TTitleBarPanel parity missing (verified: only an incidental local in navigation.e): app-rendered caption with title, caption buttons, drag region and maximized/fullscreen states, per-capability button order, with the host still owning real chrome unless frameless is granted. Fixtures for layout, caption hit regions, platform button order and accessibility roles. D2281: app-drawn caption: window.caption_layout/hit_region/caption_intent (per-platform button order, drag region, resize ring, fullscreen/maximised/host-chrome states) and navigation.title_bar over it; fixture ui_title_bar on Windows and Linux, preview in docs/ui-previews. Host-side move/resize/minimise calls and frameless windows are not in e.os. L088 complete.

### L089 — Banded report designer engine in e.ui

Planning only (D1821). QuickReport/FPReport parity missing at engine level: header/detail/footer/group bands over e.db and L032 aggregation, text layout, pagination and phase-4 print jobs; L075 covers chart-side compositions only. PDF export waits on a PDF writer (none in e.fmt). Designer canvas stays app-side on e.ui primitives; engine first with band-layout and pagination fixtures. D2282: e.ui.report, a banded report engine (bands, groups, sorting, template aggregates, wrapping and growing text, pagination with page header/footer, keep-together, repeated headers, break-before, [PAGES]) checked against a second implementation on 80 random reports plus a hand-computed one, Windows and Linux. Rendering/print/PDF and a font-backed Measure are not included. L089 complete.

### L090 — Spreadsheet grid control in e.ui.collection

Planning only (D1824). Celvyx parity missing the visual half: virtualized grid with merged cells, in-cell editing, charts-in-cells and fill/border styling over e.ui.collection virtualization, complementing queued L026-L029 (formula) and L032 (table query) with no grid of their own. Fixtures for windowing, merges, edit commit/cancel and embedded content bounds. D2283: e.ui.sheet, a spreadsheet grid: pure geometry (sparse axes, merges, frozen panes, windowing, hit test, selection and navigation over merges, reveal) checked against brute force on 120 random sheets, and the control (headers, windowed cells, fills/borders, selection tint and ring, editor, embedded content at embed_rect, pointer/key/wheel events) with fixture ui_sheet on Windows and Linux; previews in docs/ui-previews. Formulas, copy/paste, fill handles and header resizing are not included. L090 complete.

### L091 — Flow/node-graph editor widget in e.ui.collection

Planning only (D1824). Celvyx ETL-canvas parity missing: interactive node-graph editor (canvas, palette, inspector, lint strip) over the planned flowchart/network diagram geometry plus e.ui selection and drag. Diagrams alone do not edit. Fixtures for node move/connect, palette drop, inspector binding and lint markers. D2284: e.ui.flow, a node-graph editor: pure model and geometry (ports, hit testing, curves, connection rules with reasons, lint, panes) checked against closure-based brute force on 150 random graphs, and the editor (palette, canvas, inspector, lint strip; move, connect, refuse, add, rename, delete, pan) with fixture ui_flow on Windows and Linux; preview in docs/ui-previews. Zoom, multi-select, undo wiring and auto-layout are not included. L091 complete.

### L003 — Ristretto255 hash-to-group primitives in e.crypto

Chit-chat implements custom Edwards25519 point validation, complete addition, scalar multiplication, point encoding, and hash-to-point in `protocol/lib/src/crypto/edwards25519.dart`, then uses those operations for DH-PSI in `protocol/lib/src/crypto/psi.dart`. Neper already has Ed25519, X25519, and ML-KEM in `e.crypto`, but no Ristretto255 surface. Consider only a standardized, constant-time, test-vector-backed prime-order group API; do not copy chit-chat's application-specific PSI exchange. The catalog entry is 2253. D2287: lib/e/crypto/ristretto.e (RFC 9496 decode/encode/add/sub/neg/mul/map/derive) over e.crypto.sign, constant-time masks, no PSI protocol; fixture crypto_ristretto passes on Windows and Linux against scripts/ristretto_reference.py, an independent integer reference that agrees with the RFC multiples and bad encodings (409 cases); found and fixed the missing (d-1)^2 factor in map. Left to callers: OPRF/VOPRF/PSI and expand_message_xmd.

### L004 — Padme length bucketing in e.algo.privacy

Chit-chat uses the Padme ceiling in `protocol/lib/src/crypto/crypto_session.dart` to collapse encrypted frame lengths into logarithmic size classes while keeping padding overhead bounded. Neper has privacy and framing code but no reusable Padme size-bucket helper. Keep the candidate to a pure `padme_ceil` operation with boundary tests; do not import chit-chat's encrypted-frame format or cover-traffic policy. The catalog entry is 2254. D2288: privacy.padme_ceil(length) -> (u64, err): Padme rounding with S significant bits (overhead <= ~12%, 222 classes for 200001 lengths), 0 and 1 unchanged, overflow past 2^64 refused as Invalid; fixture algo_privacy_padme checks 1039 reference pairs (from an independent search definition) and the monotone/idempotent/overhead properties over every length to 200000 on Windows and Linux.

### L018 — Deterministic dependency topo-order with cycle errors

Petcow src/engine/order.rs:16 is a Kahn topo-sort with for_each[..] expansion, logical_id tie-break for determinism, and fail-closed cycle and unknown-dep errors; appdor src/grid/gantt-deps.js plus src/scheduling/dependencies.js is the same Kahn plus cycle-guard shape. Port as one pure e.algo.graph/e.algo.schedule function with fixtures: linear, diamond, deterministic order, cycle, unknown dep, for_each set. Plan: docs/petcow.md A5. D2289: schedule.dependency_order(a, nodes) -> (DependencyOrder, err): Kahn with id tie-break, target[...] set matching, UnknownDependency/SelfDependency/Cycle with node, dep and stuck; fixture algo_schedule_order checks petcow's six tests and 500 seeded graphs against a literal Python transcription of topo_order, on Windows and Linux.

### L019 — IPv4 CIDR subnet math (cidrsubnet/host/subnets)

Petcow src/interp.rs cidrsubnet/cidrhost/cidrsubnets is pure IPv4 prefix arithmetic with Terraform-compatible semantics; neper e.net has no CIDR surface. Port with fixtures from petcow tests plus edges: hostnum out of range, prefix lengths 0 and 32, multi-subnet allocation. Plan: docs/petcow.md A1. Follow-on (D1881): IPv6 prefix arithmetic to match. D2290: new e.net.cidr: parse, subnet, host, netmask, subnets (size-aligned packing) and text forms, Terraform semantics (host bits masked, no leading-zero octets, named refusals); IPv6 not covered; fixture net_cidr checks 663 cases against Python ipaddress and Terraform/petcow examples on Windows and Linux.

### L020 — Numeric version comparison and civil-day arithmetic

Petcow src/currency.rs:341 version_at_least compares dotted components numerically (lexical compare reports 10.2 < 9.6) with prerelease ordering, and days_from_civil is a proleptic-Gregorian day count used for baseline-age reporting. Extend e.fmt.semver and e.time.calendar with fixtures from src/currency.rs:373. Plan: docs/petcow.md A7. D2291: semver.at_least/cmp_loose (numeric dotted compare, suffix below the release, saturating components) and calendar.iso_day_count/age_days (validated YYYY-MM-DD prefix, days from 1970); fixtures fmt_semver_loose (720 pairs vs a transcription of version_at_least) and time_calendar_iso (730 pairs vs datetime.toordinal) pass on Windows and Linux.

### L021 — Terraform-compatible string helpers

Petcow src/interp.rs substr (negative length), chomp, indent, trimprefix/trimsuffix, slash-pure basename/dirname, title, strrev, startswith/endswith/strcontains. Port into e.text.* with per-function fixtures over chars (not bytes), keeping the slash-pure basename/dirname contract. Plan: docs/petcow.md A2. D2292: new e.text.edit: substr (characters, negative length to the end, OffsetRange), chomp, indent, trim_prefix/suffix, title (simple uppercase), reverse (scalars), slash-pure base_name/dir_name; invalid UTF-8 refused where characters are read; fixture text_edit passes 4609 cases against Python string operations on Windows and Linux. startswith/endswith/strcontains are e.str.

### L022 — Terraform-compatible collection operations

Petcow src/interp.rs flatten/distinct/matchkeys/zipmap/transpose/setproduct/one/element/range/slice/compact/sum/product/min/max/pow/log/signum/parseint. Port into e.algo.* keeping the guards: 1M-element range cap, log failing on non-finite, parseint base 2-36, fixtures incl. error cases. Plan: docs/petcow.md A3. D2293: new e.algo.collect over e.fmt.json values: flatten, distinct, compact, slice, element, one, matchkeys, zipmap, transpose, setproduct, range (1M cap, zero step refused), sum/product/minimum/maximum, pow, log (NotFinite), signum, parse_int (2..36); fixture algo_collect checks 5770 cases against Python on Windows and Linux.

### L023 — Encoding wrappers over existing codecs (base64/url/json/yaml/csv)

Petcow src/interp.rs base64encode/decode, UTF-8-only textencodebase64, urlencode, jsonencode/decode, yamlencode/decode, csvdecode. No new codec code: thin wrappers over e.fmt.{json,yaml,csv} and e.crypto.hash keeping the fail-closed UTF-8 rule (require_utf8_encoding). Plan: docs/petcow.md A4. D2294: new e.fmt.encode: base64_encode/decode (UTF-8 only, NotUtf8 otherwise), text_encode_base64/text_decode_base64 (UTF-8 charset only), url_encode (RFC 3986), json/yaml encode and decode, csv_decode (header row to string objects, Ragged); fixture fmt_encode checks 1667 cases against Python base64/urllib/json/csv on Windows and Linux.

### L024 — Stable finding IDs with idempotent merge

Petcow src/scan.rs:50 stable_id (FNV-1a hex over resource/tool/rule) plus merge_owned (preserve accepted state, auto-fix disappeared findings, per-tool namespace so one scanner never clobbers another). Reusable reconciliation pattern for any e.valid/e.algo.check integration; fixtures from src/scan.rs:589. Plan: docs/petcow.md A6. D2295: new e.algo.findings: stable_id (FNV-1a 64 hex over parts joined by |), tool_key, finding_id, merge (match by id keeps state/justification/expiry/detection time, new open, owner tool disappeared -> fixed, others kept, sorted) with Opt texts; fixture algo_findings checks 167 cases against a transcription of petcow scan.rs, including idempotence flags, on Windows and Linux.

### L025 — Data-driven policy predicate subset (spartan)

Petcow src/spartan/filter.rs, predicate.rs, eval.rs evaluate value rules and predicate-heavy checks (port-range, all-protocols, wildcard-principal) over resource instances; src/spartan/builtin.rs native rules become fixture rows. Port predicates only into e.algo.query/e.valid, not the full policy engine. Plan: docs/petcow.md A8. D2296: new e.algo.predicate: Spartan filter parse (named refusals) and eval (all operators, regex via e.text.regex, glob, any/all/count with element sub-filters, three built-ins) over e.fmt.json values; fixture algo_predicate checks 952 cases against a transcription of petcow filter.rs/predicate.rs on Windows and Linux.

### L026 — Spreadsheet formula engine core (tokenize/parse/evaluate)

Appdor src/formula/tokenizer.js, parser.js (recursive descent, 10k maxNodes cap), evaluator.js (errors-as-values, lazy IF/LET/MAP, 2M maxSteps, cycle-aware resolveCell with DFS topo order), registry.js with aliasing and volatility flags. Pure and dependency-free. Port as e.algo.formula; recount functions on landing (measured 279 vs documented 184-193). D2297: new e.algo.formula core: tokenize/parse (UTF-16 diagnostics, node cap), registry with lazy/pass_errors entries, evaluator (errors as values, blank propagation, JS number text and %, loose equality, ISO compare, step budget, cycle-aware sibling formulas), dependencies/detect_cycle/evaluation_order/infer_type, LET/LETS; fixture algo_formula checks 718 cases against appdor's own engine on Windows and Linux. Default registry recount: 279 entries, 353 names.

### L027 — Formula function library (12 groups)

Appdor src/formula/{logical,information,math,text,datetime,convertion,random-hash-encode,array,lookup,reference,extraction,finance}.js plus LET/LETS. Extend e.math/e.text/e.time/e.fmt/e.data per category with the per-category test vectors; keep arity checks, error-pass-through flags, and pushdown annotations. DELIVERED (D2298): the 279 functions of appdor's default registry as lib/e/algo/formula/{basic,math,text,datetime,convert,misc,library}.e beside the core (D2297): 43 logical/information/lookup/finance, 74 math, 49 text (UTF-16 positions, e.text.regex), 58 datetime (ISO and numeric legacy parsing, time zones, English locale, DATERANGE records), 4 convert (toFixed), 49 random/hash/encode/array/reference/extraction (MD5/SHA1/SHA256/CRC32/BASE64/URLENCODE, lambda MAP/FILTER/REDUCE/SORT/ANY/ALL with V8's sort order, host references through Context.host/prior/meta, JSONQUERY/XMLQUERY). `library.build` registers LET, LETS and every group: 279 functions, 330 distinct names (the D2297 count). Each group is checked against appdor's own JS engine run under node (scripts/formula_functions_reference.mjs; basic 1,139 cases, math 2,047, text 1,363, datetime 3,527, convert 294, misc 4,461; arities, error pass-through and messages included); fixtures algo_formula_{basic,math,text,datetime,convert,misc,library} pass on Windows and Linux. Context gained host/prior/changed/is_new/meta; GETRECORDS/GETFIELDVALUES/CHILDREN/ANCESTORS answer #N/A without a host callback, as appdor's do. Random functions are compared on refusals only. The per-function pushdown flags the item names are the classification table of the SQL compiler and land with L029.

### L028 — Formula dialect-compat tables (7 spreadsheet dialects)

Appdor src/formula/compat/dialects.js maps airtable/monday/clickup/smartsheet/quickbase/notion/appsheet to canonical calls as DATA tables (to/reorder/addArgs/negateArg plus field-ref normalization), with translate/detectDialect/translateBatch returning converted, converted-with-warnings, or failed. Port as e.algo.transpile; the data-not-code approach is the point. DELIVERED (D2299): lib/e/algo/transpile.e, e.algo.transpile: translate (field-reference normalization, Quickbase var/comment folding, tree rewrite by the data table, precedence-aware canonical text, converted / converted-with-warnings / failed with a structured report) and detect over the seven dialects, which are 45 table rows generated from appdor's dialects.js. Checked against appdor's own translate/detectDialect over 872 cases (scripts/transpile_reference.mjs, fixture algo_transpile) on Windows and Linux.

### L029 — Formula-to-SQL compiler with pushdown classification

Appdor src/formula/sql-compiler.js compiles the formula AST to parameterized Postgres (blank to NULLIF, loose equality to IS NOT DISTINCT FROM, half-up ROUND, floored MOD, error to NULL guards) and pushdown.js classifies full/partial/no pushdown. Port into e.algo.sql/e.db.query with the sql-conformance fixtures; direct fit for neper e.db. DELIVERED (D2300): lib/e/algo/formula/sql.e, e.algo.formula.sql: compile_formula (parameterized PostgreSQL, the evaluator's blank/equality/ordering/rounding/modulo rules, NULL guards for domain errors, boolean-position refusal, DATEADD/DATEDIF units from an allow-list, the 32,768-character bound), boolean_fragment, is_pushdownable and classify (full/partial/none with reasons). Checked against appdor's own compileToSql/classifyPushdown over 9,179 cases (scripts/formula_sql_reference.mjs, fixture algo_formula_sql) on Windows and Linux. The sql-conformance runs against a live Postgres belong to the e.db drivers' fixtures; the text and params here are identical to appdor's.

### L030 — Identifier checksum suite (IBAN/Luhn/ISBN/VIN/Verhoeff/GS1)

Appdor src/fields/specialized.js (IBAN mod97, LEI, Luhn, ISBN10, EAN13/ISBN13/UPC, ISIN, VIN, Verhoeff, LOINC), barcode.js (GS1 right-anchored mod10, Code39 mod43), nace.js (Rev2.1 table). All pure and test-backed. Best port candidates: e.algo.checksum plus e.data.validate wrappers. DELIVERED (D2301): lib/e/algo/checksum.e, e.algo.checksum: the 26 specialized validators (IBAN, LEI, ISIN, ISBN, EAN/UPC, VIN, BIC, EU VAT, HS, UN/LOCODE, ICD-10, SNOMED/Verhoeff, LOINC, NDC, MAC, NACE, ...), the barcode symbology rules with scan capability and scan-to-value narrowing, and the NACE Rev. 2.1 classification (parse, titles en/bg). Checked against appdor's own validators over 3,146 cases (scripts/checksum_reference.mjs, fixture algo_checksum) on Windows and Linux. The e.data.validate wrappers the item names belong to L031.

### L031 — Record validation core (rules, conditional, bulk)

Appdor src/validation/validators.js (anchored linear regexes, ISO3166 assigned set), index.js validateRecord (required/format/min/max/pattern/membership/validIf/unique, hidden-field skip), conditional.js (non-constraining suggestions), bulk.js (reject/skip/flag plus intra-batch uniqueness). Port as e.data.validate. DELIVERED (D2302): lib/e/data/validate.e, e.data.validate: validate_record (required/format/min/max/length/pattern/membership/validIf/unique, hidden-field skip, record rules, per-code severity, custom and catalogue messages), field and container behavior, suggestions, initial values, auto-set, computed-write violations, validate_import (reject/skip/flag with intra-batch uniqueness), backfill_check and find_duplicates, with the format validators unioned over e.algo.checksum. Checked against appdor's own validation engine over 1,010 cases (scripts/validate_reference.mjs, fixture data_validate) on Windows and Linux; appdor's CIDR quirk (last-octet check) reproduced and recorded in D2302.

### L032 — Table query: filter/sort/group/summarize/pivot

Appdor src/views/query.js (nested AND/OR eval, stable multi-level sort empty-last, grouping with explicit No value), src/grid/multi-sort.js and filter-tree.js, src/pivot/index.js (totals via charts/aggregate), src/charts/aggregate.js plus server-aggregate.js (bucketing, topN-Other, reason-coded server refusal). Port into e.algo.sort/filter/group/agg/pivot. DELIVERED (D2303): lib/e/algo/view.e (e.algo.view: filter trees over the field-type operator tables, stable multi-level sort, grouping, 25 summary functions, row color, quick search, apply_view, immutable filter-tree and sort-level edits, bucket keys) and lib/e/algo/pivot.e (e.algo.pivot: aggregate, chart data with buckets/split/top-N Other, KPI with comparison and thresholds, pivot, summary report, server-aggregate planner and group shaping). Checked against appdor's own engine over 1,698 cases (scripts/query_reference.mjs, fixture algo_view) on Windows and Linux. localeCompare is a root-collation approximation, documented in D2303.

### L033 — Keyset paging, windowed rows, bulk and undo ledgers

Appdor src/grid-ops/records-engine.js (sort-plus-id-tiebreak keyset paginate with base64 cursor, monotonic SI-prefixed key minter), src/grid/virtual-rows.js and performance/limits.js (ROW_CAP 100000, truncation plan), bulk.js (chunked ledger with resume), undo-redo.js (per-table inverse stack). Port into e.algo.page/window/batch/undo. DELIVERED (D2304): lib/e/algo/page.e (e.algo.page: record key minter, keyset paginate with base64 cursor and V8 sort order, duplicate_table with self-link rewrite, plan_rows, load_plan, limits, budgets, percentile) and lib/e/algo/batch.e (e.algo.batch: run_batch ledger, plan/run/summarize bulk mutation, per-editor per-table undo/redo with prepare/commit settlement). Checked against appdor's own engine over 543 cases (scripts/page_reference.mjs, fixture algo_page_batch) on Windows and Linux.

### L034 — Full-text search with indexing pipeline

Appdor src/search/index.js (AND-term scoring with title/prefix/body weights plus record-key fast path, index-time field allowlist, client/server plan at 1000 rows) and indexing-pipeline.js (trim-before-rank, cursor-idempotent outbox consumer with batch coalesce, dead letters, recents). Port into e.algo.fulltext/queue. DELIVERED (D2305): lib/e/algo/fulltext.e, e.algo.fulltext: tokenized AND scoring with title/prefix/body weights, record-key fast path, index-time field allowlist, find-in-table snippets, client/server plan; the document index with realm boundary (fail closed, counts and suggestions from the scoped set), permission trim before truncation, the cursor-idempotent outbox consumer (batch coalesce, dead letters, wedge) and recents/favorites. Checked against appdor's own search over 252 cases (scripts/search_reference.mjs, fixture algo_fulltext) on Windows and Linux.

### L035 — Project scheduling (CPM, working calendars, workflow cron)

Appdor src/scheduling/index.js (criticalPath with forward/backward passes, ganttLayout on working-day offsets, rollUpProgress, workload with capacity overrides), working-calendar.js (UTC working-day arithmetic), dependencies.js (normalize plus forward-only cascade), src/workflow/schedule.js (5-field cron with TZ, nextFire/catchUp, single-concurrency). Port into e.algo.sched plus e.time.cron/calendar. DELIVERED (D2306): lib/e/algo/project.e, e.algo.project (working calendar, typed dependencies with lag/lead, critical path with cycle chain, Gantt layout with baseline variance, duration-weighted roll-up, month grid, workload with capacity overrides, cascade reschedule) and lib/e/algo/trigger.e, e.algo.trigger (5-field cron on a zone's wall clock with the stated DST policy, schedule normalization, next-fire previews, one-catch-up/skip/all with the 1000 cap, fire plans, overlap decisions, due-date stamps, duration in state, scheduled scans). Fixtures algo_project (880 cases) and algo_trigger (1377 cases) against appdor's engine on Windows and Linux. Not carried: src/scheduling/views.js.

### T038 — Agent-ingestible queue and decision digests

Planning only (D1898). decisions.md is 2.4 MB and queue evidence runs to KBs per item: nothing is ingestible whole and routine greps overflow tool caps. Emit a compact machine index (ids, scores, one-line status) plus an evidence-length budget in the renderer, keeping render_tasks.py per-item files as the deep layer. DELIVERED (D2309): scripts/render_digest.py, docs/digest/queue.tsv and docs/digest/decisions.tsv, an advisory 4,000-byte evidence budget reported on each render, --check for staleness, AGENTS.md routing.

### T043 — Demand-ranked library breadth order from agent measurements

Planning only (D1954). 155 library items stand open at combined 0.96 with no demand order: rank breadth work by what agents actually hand-roll, from lang-stats script evidence and repair clusters, as a generated ranked view. Re-rank on new measurements; never reorder the serial head by hand. Pickup immediately after the chart cluster. DELIVERED (D2310): scripts/library_demand.py and docs/digest/library-demand.tsv, a regenerated ranking of open library items by hand-rolled and reinvented function names in agent transcripts.

### T037 — lang-stats: OpenCode harness split and honest pricing

Planning only (D1898). lang-stats pools opencode-database rows under DeepSeek with no opencode split and prices everything at Opus rates, so free-model harness work is invisible and mispriced. Split the harness, read model identity where recorded, and price free tiers at zero before any ctx-cost claim is trusted. DELIVERED (D2314): lang-stats --harness opencode, model identity from the opencode database, free tiers (model id :free or recorded zero cost) carry effort and no dollars, reported on the period line. 30-day reading: 1642 free steps, no landed Neper source.

### T031 — Four-way CM importer (ansible/salt/puppet/chef to os resources)

Petcow src/migrate.rs:1013 migrate_ansible plus :1414 salt, :1816 puppet (subset lexer), :2193 chef map modules to os.{package,service,file,command,user,group,cron,line_in_file,sysctl,hostname,timezone,mount,authorized_key,git,pip,symlink} with warn-instead-of-drop. Ship as an x.migrate tool with the cross-matrix pip/pkg/service/user/group/cron/file/symlink fixture. Plan: docs/petcow.md F4. LANDED (D2318): lib/x/migrate/migrate.e, x.migrate.migrate.{ansible,salt,puppet,chef,write} over e.fmt.yaml; fixtures/link/x_migrate (372 cases: cross-matrix pip/pkg/service/user/group/cron/file/symlink, refusals, 90 seeded random documents per tool) differential against petcow's migrate.rs built as a crate by scripts/migrate_reference.py, passing on Windows and Linux (WSL); registered in run.ps1/run.sh and library-fixtures.json. Differences from the reference are documented in the module header.

### L036 — Durable workflow runtime with FSM guard

Appdor src/workflow/runtime.js (journal-replay executeRun, if/case/foreach/fork-join/try/delay/wait-signal/approval, retry with idempotencyKey, SSRF guard, stepBudget 10000), flow-engine.js (inline sync flows), src/workflows/definition.js and guard.js (validateWorkflow incl. reachability, permitsActor, optimistic-version commit, bulk partial/atomic). Store and effects stay injected. Port into e.algo.workflow/fsm/dag. PART ONE DELIVERED (D2307): lib/e/algo/fsm.e, e.algo.fsm: workflow definition/validation/diff/templates/open workflow and the guard (allowed transitions, explain, execute with optimistic concurrency, history and event, compiled post-function steps, status-write resolution, bulk partial/atomic, simulate, time in state); fixture algo_fsm 864 cases against appdor on Windows and Linux. NOT DONE: the durable runtime (workflow/runtime.js, ir.js, journal.js, the Jinja template engine, flow-engine.js), e.algo.workflow/dag. PART TWO (D2331): lib/e/algo/journal.e, e.algo.journal -- the run journal (create_run, entries, commits with optimistic seq, apply_commit, index queries, record_clock, summarize_run, in-memory store); fixture algo_journal, 160 operation scripts against appdor's journal.js on Windows and Linux. NOT DONE: ir.js, runtime.js (the interpreter), flow-engine.js, the Jinja engine, e.algo.dag. PART THREE (D2332): lib/e/algo/ir.e, e.algo.ir -- step and trigger catalogues, plugin step registry, normalize, walk, validate (every step and trigger type, schedule via e.algo.trigger, routing injected), execution/loop/fork keys; fixture algo_ir, 180 operation scripts, 940 operations and 40 validator messages against appdor's ir.js on Windows and Linux. NOT DONE: runtime.js (the interpreter), flow-engine.js, the Jinja engine, e.algo.dag. PART FOUR (D2333): lib/e/algo/workflow.e, e.algo.workflow -- the durable interpreter (replay, if/case/foreach/fork/try/stop/fail, delay/wait-signal/approval, set/log, effects with idempotency keys, retries, dry-run gate, run driver) with clock, templates, trace, URL check and handlers injected as Hooks; fixture algo_workflow, 150 random workflows against appdor's runtime.js with its real Jinja on Windows and Linux (forks asserted separately: sequential branches). PART FIVE (D2334): lib/e/algo/flow.e, e.algo.flow -- flow-engine.js, the inline synchronous engine (condition/branch/loop/find/set/CRUD/email/notification/http/run-workflow, retries, redaction, step budget, cascade guard, unknown_step), formulas on e.algo.formula, effects/filter trees/dataset/script/ai injected; fixture algo_flow, 400 random flows against the real engine on Windows and Linux (script and ai steps and filter trees not generated). COMPLETE (D2335): the Jinja engine is injected by design (Hooks.render_value/render_text); there is no appdor DAG source -- step traversal is e.algo.ir.walk_steps and graph ordering is e.algo.graph.topological.

### L038 — CSS tokenizer, grammar, and selector parser

lib/e/fmt/css/syntax.e (e.fmt.css.syntax: Syntax-3 tokenizer with byte offsets and never-fail recovery, rule and declaration grammar) and lib/e/fmt/css/selector.e (e.fmt.css.selector: selector model, parser, An+B, :is/:where/:not/:has, specificity); fixtures text_css_syntax (420 inputs) and text_css_selector (520 lists) against Vaper's own Dart code on Windows and Linux (D2340). Matching stays in e.fmt.css.

### L039 — CSS value microsyntax and animation interpolation

lib/e/ui/interpolate.e (e.ui.interpolate: lerp, ARGB lerp, cubic-bezier, 2D affine decomposition and interpolation; fixture ui_interpolate, 400 operations) and lib/e/gfx/cssvalue.e (e.gfx.cssvalue: parseLength with calc/min/max/clamp/abs/hypot/mod/rem/round, numeric math, angle, time, light-dark, parseColor in every syntax incl. relative colours, color-mix, contrast-color, transforms, origin; fixture gfx_cssvalue, 1,060 values) against Vaper's own Dart code on Windows and Linux (D2341, D2342).

### L041 — HCL read-only codec (e.fmt.hcl)

lib/e/fmt/hcl.e (e.fmt.hcl: the read-only HCL2 parser with hcl-rs's quirks: right-nested binary chains, the negative number literal, prefix operators applied before postfix, heredoc indent stripping, template parts) and lib/x/migrate/terraform.e (x.migrate.terraform: migrate_hcl -- resource/variable/locals/data/output/provider/module, count/for_each/depends_on/lifecycle/dynamic, reference rendering, warn-instead-of-drop); fixtures fmt_hcl and x_migrate_terraform (530 random documents against petcow's own migrate_hcl) on Windows and Linux (D2344). Docs: petcow.md F1. The reference is a small crate built from src/migrate.rs lines 1-988 with the error and module-source shims.

### L042 — Scanner finding parsers and Mermaid emitter

e.fmt.mermaid and x.lint.scan against petcow's scan.rs and diagram.rs, 610 cases on Windows and Linux (D2345).

### L043 — WOFF1 and WOFF2 font decoders

e.fmt.woff and e.fmt.woff2 against Vaper's woffToSfnt and woff2ToSfnt, 480 cases on Windows and Linux (D2346).

### L044 — XLSX worksheet decode with vendor importer maps

e.fmt.xlsx sheet normalisation and x.migrate.typemaps against Appdor's xlsx.js and importer maps, 700 cases on Windows and Linux (D2347).

### L045 — Dependency-free identity protocol logic

x.identity.jose, oidc, scim, xml and saml against Appdor's identity sources, 2,000+ differential cases on Windows and Linux (D2348-D2350).

### L046 — HTTP policy helpers: cache, cookies, SSRF gate, CORS/CSP, filter lists

e.net.policy (cache, cookies, CORS, CSP, private network, filter lists) and e.net.ssrf against Vaper and Appdor, 997 differential cases on Windows and Linux (D2351).

### L047 — Declarative REST driver core with provider-trait shape

x.cloud.rest and x.cloud.manifest against Petcow's declarative.rs, mod.rs and manifest.rs, 1,168 differential cases on Windows and Linux (D2352, D2353).

### L049 — Webhook envelopes, auth-scheme table, MCP and OpenAPI builders

x.net.webhook, x.net.authscheme, x.mcp.protocol and x.api.openapi against Appdor's sources, 649 differential cases on Windows and Linux (D2355).

### L050 — Host facts and inventory helpers (key=value facts, group merge, dynamic hosts)

x.ops.inventory against Petcow's facts.rs, inventory.rs and naming.rs, 140 differential cases on Windows and Linux (D2356).

### L051 — Packet codecs and pcap I/O (e.net.packet, e.net.pcap)

e.net.packet and e.net.pcap against an independent spec implementation, 341 differential cases on Windows and Linux (D2357).

### L052 — Executable format readers (e.fmt.elf, e.fmt.pe)

e.fmt.elf and e.fmt.pe delivered and closed (D2358): ELF32/64 headers, program and section tables with names, symbol and dynamic tables; PE32/PE32+ headers, directories, sections, RVA mapping, imports and exports; fmt_exe replays 169 cases against an independent struct writer/reader on Windows and Linux, readelf agrees on sample files. Mach-O deferred by design.

### L053 — Multi-pattern signature scanning (YARA-lite subset)

e.text.sig delivered and closed (D2359): YARA-lite rule compile and scan (text and hex strings, wildcards, jumps, ascii/wide/nocase/fullword, boolean conditions, at, counts, filesize, N of sets); text_sig replays 183 cases on Windows and Linux against an independent re-based matcher. Aho-Corasick already existed in e.text.search.

### C118 — NeperOS Stocks live data: Stooq daily prices, bring-your-own-key providers, crypto

NeperOS Stocks live data delivered and closed (D2251, D2285, D2360): httpc.e and a rewritten Stocks app; live crypto from Coinbase Exchange daily candles (keyless) and crypto Find over Coinbase /products (keyless, online pairs); stocks from Twelve Data time_series, Alpha Vantage TIME_SERIES_DAILY and Polygon /v2/aggs with the API key typed in the Key sheet (provider chosen there, key cleared on change); stock Find over Twelve Data symbol_search; add/remove/search of tickers, sample data as the offline fallback with a source label, Sync on ticks. Fixtures stocks_live, stocks_providers and stocks_crypto_search run against recorded replies in tests/selfhost/fixtures/neperos/net (host_services.py/record.py); stocks_live and stocks_providers pass on Windows and WSL, stocks_crypto_search verified by compile (aarch64/neperos) and by recomputing its taps from the sheet layout, to be booted on a suite-capable host. Out of scope / won't-do, by design or external: Stooq acceptance (1) dropped (JS proof-of-work bot check); the typed key survives only the session until an app can reach storage (C116 Secure, C125 Files); Finnhub (free tier has no daily history); crypto symbol search beyond pairs; a real Polygon recording (Polygon has no public key, so record.py records it only when POLYGON_API_KEY is set and the committed reply stays the documented /v2/aggs shape).

### C126 — NeperOS Settings: settings that act on the system, kept across restarts, searchable

NeperOS Settings delivered and closed (D2361-D2374): settings_server.e, a server in the capability model, holds the 40 values and the system word, serves the shell and every app (GET/SET/RESET, the uninstalled mask, the dynamic-app registry), persists /settings, /hidden and /dyn through the filesystem server; every app asks it at each frame so Dark theme, font size, high contrast, 24-hour clock and brightness follow live, and the shell reads it at boot (restart fixtures theme_kept, acts_kept, uninstall_kept, dynamic_kept, timeout_kept, zone_kept). Acting recipients: shell clock and date (24-hour, time zone), brightness (dimming layer in the app kit and shell), screen lock None, Do Not Disturb, Screen timeout, and the network server (Airplane, Wi-Fi and Mobile gate its connections). Search by name and keyword; Storage from the disk (fs OP_STATS); Apps with real program sizes, an app info page and Uninstall (home grid reflows); Wi-Fi from the network server's SCAN/JOIN with a password sheet (the wired link, plus a recorded air in the test boots); Battery through the status service (recorded 78% in the test boots); Dynamic apps in the server's registry, listed and removable. Fixtures run on QEMU on Windows (WSL not yet run). The parts with nothing yet to receive a setting (audio volumes, fingerprint, per-app notification permission, Bluetooth and Hotspot, a real battery provider) and a real installed Dynamic app are queued as C149 and C124.

### C125 — NeperOS Files: real storage through the filesystem server, file hand-over between apps

NeperOS Files on real storage delivered and closed (D2375-D2382): with a disk the Files app drops its sample tree and browses and edits the real filesystem behind fs_server.e: list, create folder and file, rename (OP_RENAME), delete into a /Trash that empties after thirty days, move (OP_MOVE, choosing a folder), copy, multi-select Delete and Move, search by name and type, a Recent view, sizes in bytes, entry modification days (OP_STAT's fourth word, stamped from the guest clock) and the storage card from OP_STATS; files of several blocks (up to 4 KB, a run of blocks); Open hands a file to Document (or Photos) through /handover and the shell's exit-code hand-over. Fixtures files_real, files_move, files_sel, files_open and their restart rows, files_real_later (clock moved forty days on, NEPEROS_RTC) run on QEMU on Windows (WSL not yet run). Re-queued as C150: the capability model (each app its own directory, which needs badged endpoints), Share and the Camera/Wallet/Mail saving into Files (those apps are C121, C122, C128), the grid view with image thumbnails, zip browse and extract, external storage as a second root, and files over 4 KB.

### C124 — NeperOS Dynamic: apps from a prompt, compiled in Neper on a server, scanned, installed

NeperOS Dynamic's device side delivered and closed (D2383-D2388): the app package (neperos/src/package.e: manifest, image, Ed25519 signature, api level, capabilities; checked against Python's cryptography), the kernel's launch from an image in the caller's memory (vm.translate, the install word), the shell verifying a package against server_key.e and adding its icon after the built-in apps, the first-run prompt (Allow/Cancel, capabilities listed), the kernel granting only the manifest's capabilities (network, storage), the package kept in /apps through files of any size (OP_RESERVE/WRITE_AT/READ_AT, packed pieces) and found on the next boot, and a source-level security scan (neperos/src/scan.e). Fixtures install, install_cancel, install_kept and install_kept_again run on QEMU on Windows (WSL not yet run); package_test and scan_test run natively on both hosts. Re-queued as C151: the generation server (the protocol over TLS, the model, the compile-and-repair loop, signing and revocation, a local test server with a canned answer, a large GET streamed into the filesystem), the Dynamic app calling it instead of its three templates, several installed apps, removal and updates with rollback, and the NIR walk of the scanner.

### C123 — NeperOS Document: a viewer for PDF, Word, PowerPoint, Markdown and text, with syntax highlighting

NeperOS Document delivered and closed (D2389-D2394): a viewer for files from the disk, handed from Files or listed on the device: Word and PowerPoint text through the new e.fmt.ooxml (zip + XML), PDF page text through e.fmt.pdf (page tree, Flate, text operators), Markdown rendered, source highlighted by e.text.highlight (32 languages, table-driven, checked byte for byte against an independent implementation), plain text, large files paged (26 lines, 16 KB), find, three text sizes. Fixtures document_office, document_pdf, document_markdown, document_code, document_paging, document_find, document_device on a disk seeded by scripts/make_fs_image.py run on QEMU on Windows (WSL not yet run); fmt_ooxml, fmt_pdf and text_highlight run natively on both hosts. Re-queued as C152: PDF images, vector paths, outline and search of a rendered page, Word tables and images, PowerPoint shapes, pinch zoom (the touch layer), the match highlighted on the page, shebang detection, opening from Mail attachments and Wallet pages (C128, C121), files over 16 KB, and the TIOBE list refreshed from tiobe.com.

### C122 — NeperOS Camera: a real sensor feed, files in Photos, video, focus and exposure

NeperOS Camera delivered and closed (D2395-D2397) as far as software goes: the shutter writes the viewfinder frame as a PNG in /DCIM through the filesystem server and Photos decodes and lists it; tap to focus (ring), exposure steps and a 3 s / 10 s timer on the input server's ticks; Scan finds the page, straightens it by a homography and writes SCAN_nnnn.png. Fixtures camera_file, photos_file, camera_timer, camera_scan on a disk. The sensor, video, flash and the QR reader are re-queued as C153; handing a scan to Wallet stays with C121.

### C121 — NeperOS Wallet: real codes, scanning with the Camera, encrypted storage, more validators

NeperOS Wallet delivered and closed (D2399-D2402): e.barcode (QR Code 1-10 encode, decode with Reed-Solomon correction and image search, Code 128, EAN-13) checked against the qrcode and python-barcode packages; Wallet draws a real QR symbol on passes, tickets and health cards and a real Code 128 on loyalty and transit cards; e.valid gained ISIN, LEI, VIN, Verhoeff, BIC, card expiry and the passport MRZ check digits (against python-stdnum); the add form refuses a wrong card number, expiry or IBAN with a message; a document shows the newest Camera scan read from /DCIM. Fixtures barcode, barcode_scan, valid, wallet_code, wallet_form, camera_scan_more. The encrypted store, the MRZ read from an image, editing a card and the Camera feeding qr_scan are re-queued as C154.

### C120 — NeperOS SSH: a real SSH client behind the Termius-style app

NeperOS SSH delivered and closed (D2404-D2406): e.text.terminal (UTF-8, cursor and erase, insert and delete, scroll region, 256 and true colours, alternate screen, scrollback; checked cell by cell against pyte), e.net.ssh (a sans-IO SSH-2 client: curve25519-sha256, ssh-ed25519 host key shown for confirmation, chacha20-poly1305@openssh.com, password and ed25519 key login, pty and shell, resize, flow control, exit status; checked against asyncssh), and the app: Connect opens a live session over the network server's new POLL op, password typed masked, host key fingerprint confirmed, the shell drawn in a terminal grid with keys sent as tapped. Fixtures text_terminal, net_ssh, ssh_live. Credentials in Secure and the Keychain, saved hosts in storage with groups and snippets, forwarding and SFTP, Esc and Ctrl keys and a monospaced face are re-queued as C155.

### C119 — NeperOS Weather live data: a keyless forecast source, places and units

Queued by the user (2026-10-08). The Weather app (D2214) ships on a seeded sample forecast; this item replaces it once C117 (networking) exists. Acceptance: (1) a keyless forecast source (Open-Meteo or the Norwegian MET API; no account) giving the current temperature and condition, the hourly strip, seven days, humidity, wind and UV, with the sample data as the offline fallback and a visible 'updated' time; (2) places: search by name, add and remove, the current location by the user's choice, kept in storage; (3) units (C and F, km/h and mph) remembered; (4) sunrise and sunset, precipitation chance and alerts; (5) a condition for each hour (the sample strip shows today's condition for all eight hours, so it cannot show a change coming), precipitation chance per hour, and hours and weekdays in the place's own time zone (the sample follows UTC). Fixtures run against recorded responses, not the live internet.  DONE (D2286): Open-Meteo forecast (current, 24 hours with a condition and rain chance each, 7 days, sunrise and sunset, humidity, wind, UV) in the place's own time zone with an updated time and the sample as fallback; place search (Open-Meteo geocoding), add and remove; C/F and km/h/mph; fixtures weather and weather_live pass on Windows and WSL.  DONE (D2408): the places, the selected one and the unit are kept in /weather and come back on a restart (fixtures weather_kept and weather_kept_again). The current location (GPS, C131) and weather alerts (a source that has them) are re-queued as C156.

### C127 — NeperOS Call: a real telephony stack, the contact store, voicemail

NeperOS Call delivered and closed as far as software reaches (D2409): e.fmt.vcard (parse and write vCard 2.1/3.0/4.0, checked against vobject) and the contact store kept in /contacts.vcf with New, Edit and Delete on the on-screen keyboard, loaded at start (fixtures fmt_vcard, contacts_kept, contacts_kept_again). The telephony stack and the audio path, sharing the store with the other apps, favorites, search, import and export, recents kept, missed-call notifications, voicemail, emergency numbers and the SIP fixture are re-queued as C157.

### C128 — NeperOS Mail: a real mail client over IMAP and SMTP

NeperOS Mail delivered and closed as far as a fixed test account reaches (D2411-D2413): the inbox fetched over IMAP (LOGIN, SELECT, FETCH read by e.fmt.mail) and a reply sent over SMTP, both on TLS 1.3 first with plain text as the fallback; opening a message sets \Seen and deleting one expunges it on the server, seen by a later session (fixtures mail_live, mail_live_delete, mail_live_after against mail_services.py). Accounts typed in the app with their passwords in Secure, OAuth, other folders and sync, threads, labels, search, archive and swipe actions, HTML rendering, attachments, compose from Files and Photos, drafts and signatures, the contact picker, notifications and push are re-queued as C158.

### C129 — NeperOS Browser: a real engine: HTTP over TLS, HTML and CSS, images, forms

NeperOS Browser delivered and closed as far as a text browser reaches (D2415): an address typed in is fetched over HTTPS, parsed by e.fmt.html and laid out as headings, wrapped paragraphs, bullets, preformatted lines and links, scrolled, followed, refetched on Back, Forward, tab switch and reload; the sample sites and searches stay. Fixture browser_live against the test boot's pages. CSS and a layout engine with boxes, images and fonts, forms, cookies, redirects, a cache, HTTP/2, plain HTTP, bookmarks and a persistent history and tabs, downloads into Files, permissions and incognito are re-queued as C159.

### C130 — NeperOS Maps: real map data, location, search and navigation

NeperOS Maps delivered and closed as far as the sample city reaches (D2417): routes are the shortest path (e.algo.graph.dijkstra over e.data.graph) around closed roads, drawn on the map with the closures marked, with the planned distance and walking time on the card (fixture maps). Map data from files or vector tiles with labels, icons and rotation, drag and pinch, a location service and its permission, search by name and category, place cards with network data, driving and transit routing with turn-by-turn instructions, and saved places are re-queued as C160.

### C131 — NeperOS Compass: the magnetometer, GPS and the declination

NeperOS Compass delivered and closed as far as a simulated sensor reaches (D2419, D2420): e.algo.magnetic (WMM2025 against pygeomag, tilt-compensated heading, hard-iron calibration), the settings server's new SENSOR op serving a scripted magnetometer and accelerometer trace through the capability slots every app holds, and the Compass computing its heading from those readings with the hard-iron offset found by Calibrate and the declination from the model (fixtures algo_magnetic, compass). A separate sensor server with a magnetometer driver for the Pixel's hub, the gyroscope, GPS and the location service shared with Maps, and a fixture driven by a recorded sensor trace file are re-queued as C161.

### C132 — NeperOS Level: the accelerometer and gyroscope for the bubble level and protractor

NeperOS Level delivered and closed as far as the simulated sensors reach (D2421): the accelerometer and the gyroscope read through the settings server's sensor service (kind 1 and 2, scripted trace), the roll and pitch from gravity and a complementary filter in e.control (roll_from_accel, pitch_from_accel, complementary, checked in control_loop) giving the steady tilt, and the calibration offsets kept in /level and read back at start (fixtures level, level_kept, level_kept_again). A 50 Hz source, the self-test on a flat surface, the edge mode switched from the real orientation, per cent and ratio readings, a beep or vibration when level, and the Kalman filter are re-queued as C162.

### C133 — NeperOS Flashlight: the real LED, its levels and a faster beat

NeperOS Flashlight delivered and closed as far as a simulated torch reaches (D2422): a torch capability served by the settings server (TORCH level 0 to 5, the device's state held and logged: a simulated LED under QEMU, where the Pixel's camera flash will answer), driven by the app with every change of its light and brightness step (fixture flashlight: torch level 5 and 0 as the SOS pattern flashes). A finer timer so a Morse unit can be 100 ms and a strobe can reach ten flashes a second with a speed control, the quick toggle from the status bar and the lock screen, user patterns, turning off when the camera opens and on a timeout, and the beat-time fixture are re-queued as C163.

### C134 — NeperOS Chat: a real team chat service

NeperOS Chat delivered and closed as far as a loopback server reaches (D2423): the app joins a chat server over a WebSocket on the network server's connection (the upgrade and masked text frames in wsc.e over a buffered reader, netio.e; the library's e.net.ws needs e.net which this platform lacks), says a message in a room the server knows and shows what the server relays, the second person's answer included, as posts, polled on the ticks (fixture chat_live against chat_services.py). TLS (wss) with a poll over it, accounts, presence and typing, delivery and read marks, history in storage with search and threads, reactions on the server, files, notifications, Meet and end-to-end encryption are re-queued as C164.

### C135 — NeperOS Meet: real video calls: signalling, media transport, capture

NeperOS Meet delivered and closed as far as signalling reaches (D2424): joining a meeting opens a WebSocket to the room server (the wsc and netio of Chat), which names the people in it and who is speaking as it changes; the grid shows those names and rims the speaker, the mic switch and hand are sent, End says goodbye (fixture meet_live against chat_services.py; the offline demo meeting stays when there is no server). Media transport (ICE, DTLS-SRTP or an SFU), capture from the camera and microphone, codecs, speaker layouts from audio levels, screen sharing, captions, echo cancellation and the two-client media fixture are re-queued as C165.

### C136 — NeperOS Recorder: real capture and playback, storage and transcription

NeperOS Recorder delivered and closed as far as a scripted microphone reaches (D2425): a recording is the scripted source's samples encoded as a 16-bit mono 8 kHz WAV (e.fmt.wav) and written to /Recordings through the filesystem server with the wave built from the samples' peaks, listed again after a restart from the files (length from the WAV header, wave from the data), played with its sample-byte checksum logged (2927 in both sessions) and deleted with its file (fixtures recorder_kept, recorder_kept_again). The microphone and the speaker through e.audio, Opus, rename, share and search, the transcript from a speech-to-text model with tap-to-seek, background recording with its notification, and the lock-screen control are re-queued as C166.

### C137 — NeperOS Translate: a real translation model, more languages, camera and voice input

NeperOS Translate delivered and closed as far as a server model reaches (D2426): a text outside the six-language phrase book is sent on Done to the translation server over HTTPS (a word-for-word dictionary through English in the test boot) and shown as the translation of exactly that text and those languages (fixture translate_live). A real model with forty languages and auto-detect, offline packs, the fonts and shaping for the other scripts, voice, camera and handwriting input, history and saved phrases, speak the result, conversation mode and the small-model fixture are re-queued as C167.

### C138 — NeperOS Steps: the step sensor, history and goals in storage

NeperOS Steps delivered and closed as far as a scripted accelerometer reaches (D2427): e.algo.pedometer (a three-sample moving average and a peak rule over the mean plus half a standard deviation, a 250 ms gap, a cadence class; checked on synthetic walks of four cadences within two per cent and a phone on a table, fixture algo_pedometer), the settings server's walking-accelerometer stream, and the Steps app feeding twelve samples of it a tick to the detector and adding what it counts to today, written to /steps with the goal and read back (fixtures steps, steps_kept, steps_kept_again). Counting in the background at a low-power rate, the history of days, weeks and months with streaks and a weekly report, calories from a profile in Settings, the goal notification and widget, and a replayed recorded walk are re-queued as C168.

### C139 — NeperOS Blocks: held keys, hold, a ghost piece, high scores, sound

NeperOS Blocks delivered and closed as far as taps reach (D2428): a hold piece (swap once a piece), a ghost piece showing where the piece lands, wall kicks (a turn tried a cell and two to either side and a cell up), hard-drop points, and the best score kept in /blocks and shown (fixtures blocks, blocks_kept, blocks_kept_again; the seeded 7-bag was already there). The finer timer, auto-repeat on held keys and drags (the touch layer), the score board and last game, sound and music through e.audio, and the scripted-sequence score fixture are re-queued as C169.

### C140 — NeperOS Secure: otpauth import, SHA-2 and eight-digit codes with their own period

NeperOS Secure delivered and closed as far as it reaches without new capabilities (D2429): e.crypto.otp parses otpauth:// URIs (parse_uri, percent_decode; pyotp oracle), Secure computes every code with otp.totp from the entry's algorithm, digits and period (stored as three trailing record bytes; old records read as SHA-1/6/30), counts down each period, and an Import pill reads /otpauth.txt into a sealed entry (fixtures secure, secure_vault, secure_import). The encrypted vault itself was D2235/D2252. HOTP in the app, QR scan, export, clipboard service and autofill, biometrics, the breach check and cards are re-queued as C170.

### L122 — Seeded fake-data generators in e.algo.rand

Delivered (D2560): e.algo.rand.fake, seeded fake-data generators pinned against an independent PCG; shapes (Luhn, UUID, IP, MAC, date) checked. AutoFixture-style graphs over e.meta remain open.

### L131 — Parser-combinator kit in e.parse

Delivered (D2561): e.parse.comb checked against parsy on 325 expression and 212 key/value inputs.

### L128 — Snapshot testing in e.test

Delivered (D2562): e.test.snapshot, review-and-accept snapshots against pytest-snapshot (60 pairs and the mode workflow).

### L129 — Statistical bench harness in e.test

Delivered (D2563): e.test.bench against Python statistics and Student t.

### L123 — Layered configuration with watch in e.cli

Delivered (D2564): e.cli.config layered configuration with reload and watch against ChainMap (40 scenarios). Watcher not run under inotify.

### L133 — Terminal line editor with history and completion

Delivered (D2565): e.cli.line terminal line editor against a readline-semantics model (120 sessions).

### L130 — Diagnostic report rendering for applications

Delivered (D2566): e.text.report diagnostic rendering against a second canvas renderer (150 reports); measures terminal columns itself.

### L103 — Recurrence rules and flexible date parsing in e.time

Delivered (D2500): e.time.recur (RFC 5545 expansion) and e.time.parse against python-dateutil (1,500 rules, 357 dates, 92 durations).

### L105 — Platform directories (platformdirs parity) in e.path

Delivered (D2501): e.path.dirs for XDG, macOS and Windows against platformdirs (2,000 cases).

### L106 — Env-file loader (python-dotenv parity) in e.fmt

Delivered (D2502): e.fmt.dotenv against python-dotenv (1,800 files).

### L108 — PEP 440 specifiers and requirements for e.fmt.semver

Delivered (D2503): e.fmt.semver.pep440 against packaging (8,000+ lines). Cargo caret/tilde ranges not done (no oracle).

### L111 — JSON-path queries (jmespath parity) in e.algo.query

Delivered (D2504): e.algo.query.jmespath against python-jmespath (270 hand-written, 9,000 random).

### L056 — Elementary inferential completions in e.algo.stat

Delivered (D2540): e.algo.stat.infer (z/proportion tests, chi-square, Levene, Bartlett, Tukey HSD, power) against SciPy and statsmodels, 119 cases.

### L057 — Regularized and robust regression in e.ml.linear

Delivered (D2541): elastic net, polynomial features, quantile and Huber regression in e.ml.linear against scikit-learn and statsmodels.

### L058 — Multivariate core in e.ml.reduce / e.algo.stat

Delivered (D2542): e.ml.multivariate (LDA/QDA, factor analysis, CCA, MANOVA) against scikit-learn and statsmodels. Oblique rotations and factor scores not done.

### L064 — Tidy-data verbs atop L032

Delivered (D2543): e.algo.tidy (tidy-select, joins, pivots, window functions, missing values) against pandas, 178 cases. complete/expand not done.

### L063 — ML production core (histogram GBM, CV, pipeline, calibration)

Delivered (D2544-D2546): e.ml.hgb, e.ml.select, e.ml.calibrate against scikit-learn. Sample weights, early stopping, multiclass calibration not done.

### L117 — Password-hashing KDFs in e.crypto: bcrypt, argon2, scrypt

Delivered (D2520): Argon2d/i and PHC encode/verify (Argon2, scrypt) in e.crypto.kdf on top of the bcrypt/scrypt/Argon2id already there, against argon2-cffi, hashlib and bcrypt (186 checks).

### L121 — SOCKS5 client in e.net

Delivered (D2521): e.net.socks, a SOCKS5 client (CONNECT, BIND, UDP ASSOCIATE, username/password) against PySocks transcripts and loopback sessions.

### L119 — Virtual filesystem: memory, overlay and union mounts

Delivered (D2522): e.fs.vfs memory, overlay, union, sub and host filesystems against host-filesystem traces.

### L120 — RAR and 7z archive decoders in e.fmt

Delivered (D2523): e.fmt.sevenzip and e.fmt.rar, decode only (7z Copy/LZMA/LZMA2/Deflate/BZip2/Delta/BCJ; RAR5 store and LZ) against py7zr, liblzma and libarchive. PPMd, BCJ2, AES, RAR filters and encryption not supported.

### L124 — Extended image decoders: BMP, GIF, TIFF, QOI plus EXIF

Delivered (D2524): e.fmt.qoi, bmp, gif, tiff and exif decoders against Pillow and qoi (109 checks). Encoders, TIFF tiles/BigTIFF not done.

### C141 — NeperOS AI: a real bring-your-own-key client (non-streaming)

NeperOS AI delivered and closed as far as a blocking request reaches (D2430): httpc.post, the conversation sent in Anthropic, OpenAI, Google and OpenAI-compatible local shapes, the answer read from the JSON, and plain-word errors for a refused key, rate limit, missing model, no network, unreachable host and TLS failure (fixture ai_live against the test server's echo model; fixture ai for the no-network path). Streaming, the key kept in Secure, stored conversations, files and images, a tool loop and the key check on Save are re-queued as C171.

### C142 — NeperOS Document: Office, PDF, OpenDocument and Markdown readers; highlighting for 32 languages

NeperOS Document delivered and closed as far as the text of documents goes (D2431, with D2237 and C123): e.fmt.pdf, e.fmt.ooxml and the new e.fmt.odf read PDF, Word, PowerPoint, OpenDocument text and presentations; Markdown renders; e.text.highlight is table-driven for 32 languages with a fixture of snippets; files open from Files with large files paged, and a search (fixtures document_office, _pdf, _markdown, _code, _paging, _odt, fmt_odf). PDF vector and image painting, pinch zoom, CommonMark tables and the shared HTML view, spreadsheets, and the open-with sheet are re-queued as C172.

### C143 — NeperOS Dynamic, step one: package trust (signing, verification, revocation)

Delivered as far as package trust goes (D2432, with C124): the manifest and package format, Ed25519 signing key and device verifier, the installer with its first-run capability prompt and launch with declared capabilities were already there; revocation is added here (a /revoked list by name and version, checked on every adopt, fixtures package_test with 25 checks and install_revoked on QEMU). The scanner over the built app's NIR, the versioned app kit with its prompt prefix, a server-signed revocation list, removal and the build-sign-install-launch-remove fixture are re-queued as C173.

### C145 — NeperOS Clock: alarms, timer and stopwatch kept across exit and reboot

Persistence delivered (D2433): the Clock keeps its alarms, cities, bedtime, timer and stopwatch in /clock through the filesystem server, with the timer end and stopwatch start as wall-clock times so time spent away counts (fixture clock_kept). The background service that rings with the app closed, the notification and Snooze/Dismiss, and the ring fixture are re-queued as C174.

### C146 — NeperOS Clock: daylight saving in the world-clock cities

Delivered (D2434): each world-clock city carries its POSIX TZ rule in neperos/src/zones.e, resolved through e.tz; the displayed offset, hour and day word follow the rule at the drawn instant, across transitions and in both hemispheres. zones_test (64 checks against Python zoneinfo, every city in January and July 2026 and both sides of each 2026 transition) runs in both runners; the Clock builds for NeperOS with it.

### C148 — NeperOS clipboard: Copy in Secure, Paste in AI, through the settings server

Delivered (D2435): a one-value clipboard with an owner in the settings server (ops CLIP_SET/CLIP_GET, 32 bytes, expiry, replaced by the next copy, text never logged), Secure's Copy for a password and a one-time code, ui.field_paste and AI's Paste pill, fixture clipboard (Secure to AI). The lifetime is 90 s rather than 30 (D2435). Paste in every text field and the keyboard, the lifetime as a setting and clearing on lock are re-queued as C175.

### C149 — NeperOS settings recipients: per-app notification permission enforced at the status service

Delivered as far as item 3 (D2436): the status service counts a per-app notification only when the app's switch is on (OP_POST_APP / OP_SET_ALLOWED), the settings server pushes the mask at start, on a switch change and on reset; checked by the statussvc boot and the settings fixture. Audio server and volumes, fingerprint unlock, Bluetooth and Hotspot link layers, a battery provider and per-app permission values are re-queued as C176.

### C113 — NeperOS shell 9: the Clock and Calculator apps

Closed (D2437): Clock and Calculator exist as full apps launched from the home grid with tap-driven QEMU fixtures (C115 Clock and Calculator, C145 Clock persistence, C146 daylight saving; fixtures clock, clock_kept, calc); they supersede the earlier gpu-boot faces this item began with. The screendump-hash form of the fixture was not carried over; the fixtures assert markers.

### C114 — NeperOS shell 10: the Tasks and Settings apps; the shell milestone closes

Closed (D2437): Tasks keeps its list in /tasks (fixtures tasks_kept and tasks_kept_again across two boots on one disk), Settings is served by the settings server and persists in /settings across reboot (fixtures settings, settings_theme, settings_search); both apps are the full ones from C115/C126, superseding the earlier gpu-boot faces. The D2148 shell milestone is closed; its next phase, the Android bridge over vsock, stays with C104.

### L137 — Micro-slivers II: DHCP, SNMP, Gemini, gopher, finger, QR

Delivered (D2438): e.net.dhcp (BOOTP/DHCP message codec, 19 checks vs an independent struct encoder), e.net.snmp (BER codec, v1/v2c Get/GetNext/Set and response decode, 24 checks vs an independent BER encoder) and e.net.retro (Gemini, Gopher and Finger codecs, 41 checks); QR encode/decode was already in e.barcode. Codecs only: DHCP client timers, SNMPv3/GetBulk and the transports are left to callers.

### L113 — SQL migration runner over e.db

Delivered (D2680): e.db.migrate, a migration runner over e.db (ordered versions, checksums, replay vs SQLite; 72 checks). Only SQLite run; no statement splitter, advisory lock or file loader.

### L112 — ORM layer over e.db: struct mapping, relations, hooks

Delivered (D2681): e.db.orm struct mapping, relations (belongs_to, has_many) and hooks over e.db, emitted SQL replayed through sqlite3 (71 checks). Many-to-many, nested preload, tags and soft delete not done.

### L159 — Composable test matcher library

Delivered (D2682): e.test.match composable matchers (53 checks). Five subject shapes; no regex or custom matcher extension.

### L118 — Mock and stub framework for e.test

Delivered (D2683): e.test.mock mock and stub framework with matchers, ordering, stubs and a spy log (53 checks). No generated typed doubles from a comptime interface.

### L142 — BDD/Gherkin runner with e.meta step binding

Delivered (D2684): e.test.bdd Gherkin runner (38 checks). Doc strings, Rule and i18n unsupported; captures int/word/quoted only.

### L143 — Mutation testing in e.test

Delivered (D2685): e.test.mutate mutation testing with 32 enumerated mutants and a scored harness (17 vector-driven checks). Equivalent-mutant detection and statement deletion not done.

### L144 — Architecture-rule testing over module dependencies

Delivered (D2686): e.test.arch architecture-rule testing over module dependencies (39 checks); prefix and layer-range rules only.

### L158 — Generic object pool with eviction

Delivered (D2687): e.data.objpool generic object pool with eviction (69 checks, 400-op differential vs a Python model). Caller ticks evict; no keyed pools or max_age.

### L100 — XLSX worksheet encode for grid and report export

Delivered (D2600): e.fmt.zip.write (stored zip writer) and e.fmt.xlsx.book (workbook encode/decode over the Sheet/Cell model), byte-equal to an independent writer, openpyxl/XlsxWriter files decoded (79 checks). No charts, pivots, DEFLATE on output or DataGrid wiring.

### L145 — PDF document generation in e.fmt

Delivered (D2601): e.fmt.pdf.write, a PDF writer with Helvetica metrics, byte-equal to an independent writer, accepted by pypdf strict and pdfminer (45 checks). Own greedy wrapping rather than e.text.layout; no embedded fonts, images or compression.

### L146 — Word document generation over OOXML

Delivered (D2602): e.fmt.docx, Word document generation (41 checks; python-docx opened the output). No tracked changes, headers/footers, hyperlinks or merged cells.

### L153 — Unified document text-extraction facade for search

Delivered (D2603): e.fmt.extract, a text-extraction facade over PDF, Office, OpenDocument, email, HTML, Markdown and text (122 checks on 23 samples). No OCR, legacy binary Office or non-UTF-8/Latin-1 charsets. Found: e.fmt.pdf reads FlateDecode only.

### L155 — Graph interchange formats: GraphML, GEXF, GML

Delivered (D2604): e.fmt.graph, GraphML, GEXF and GML read/write checked with NetworkX (145 checks). No hypergraphs/ports, GEXF dynamics or viz.

### L132 — HTML sanitizer in e.fmt.html

Delivered (D2605): e.fmt.html.sanitize, an allowlist sanitizer with byte parity against nh3 on 32 inputs and 4 configs (238 checks). Differences from ammonia recorded: no tbody insertion/adoption agency; cite is URL-checked; depth past 64 is an error. The L066 viewer is not wired.

### L110 — Statistical legacy-charset detection in e.text.encoding

Delivered (D2720): e.text.encoding detect_legacy/detect_name/legacy_name, single-byte charsets only (12 models); 222/232 held-out vectors, same as chardet 7.6 (258 vectors). No CJK multi-byte or language model.

### L104 — Terminal kit: progress meters and rich text tables

Delivered (D2721, D2439): e.text.termkit, a tqdm-style meter, rich markup to SGR and boxed tables, byte-for-byte against tqdm and rich (517 checks). No Windows VT enable, prompts, wide-character widths or truecolour.

### L102 — Process and system info (psutil parity) in e.proc

Delivered (D2722): e.proc.sys (+.format, .host) psutil-shaped system info (261 parser records, live shape checks, also run in WSL). No other-process CPU/memory, open files, connections or sensors.

### L116 — Prometheus exposition and OTLP export for e.metrics/e.trace

Delivered (D2723): e.metrics.export Prometheus/OpenMetrics text, scrape negotiation, OTLP/JSON metrics and spans and POST builder (140 checks vs prometheus_client and OTLP definitions). No live endpoint or collector round trip, protobuf wire, gzip or retries.

### L127 — Object-store abstraction over fs, http and memory

Delivered (D2724): e.store and e.store.http, an object-store abstraction with memory, fs and http backends under one conformance script (47 steps x 3 backends). HTTP backend exercised through a stub transport; no streaming, ranges or multipart.

### L134 — Shell completions and man pages for e.cli

Delivered (D2725): e.cli.complete bash, zsh, fish completions and man page, certified by real bash and fish (28 command lines) and groff; zsh only syntax-checked. No PowerShell/elvish or dynamic completion.

### L154 — Symbolic math: expression trees, diff, integrate, solve

Delivered (D2726): e.math.sym expression trees, parse, eval, diff, integrate (polynomials, elementary functions, simple by-parts) and solve (rational-coefficient polynomials), compared by value with SymPy (176 records). No rational integrals, factoring, series, limits or complex roots.

### L138 — Mediator: requests, notifications and pipeline behaviors

Delivered (D2727): e.mediator requests, notifications and pipeline behaviors, with stock behaviors (60 scenarios vs an independent model; no reference implementation on the host). Keyed by u32 kind plus bytes, not by type; no stream requests.

### L107 — HTTP keep-alive connection pooling in e.net.http

Delivered (D2640): an HTTP keep-alive connection pool in e.net.http (pool_new/request/hold/release/evict/close), checked against three real loopback servers (about 42 checks). Plain TCP only: no TLS session reuse, HTTP/2 multiplexing, shared multi-thread pool or pipelining.

### L109 — TLS trust-root provisioning for e.net.tls

Delivered (D2641): e.net.tls.roots, .hoststore (Windows and base variants) and .mozilla (121 certifi roots), verified with a cryptography test PKI (about 40 checks). No macOS/Android/iOS stores, capath reader, revocation or auto-refresh; Linux host store not run.

### L115 — NATS client in e.net

Delivered (D2642): e.net.nats client protocol codec and session (533 vectors against nats-py Parser). No socket loop, JetStream or reconnect.

### L114 — NoSQL wire clients: Redis, MongoDB, Elasticsearch

Delivered (D2643-D2645): x.redis.resp (RESP2/3, 381 vectors vs redis-py), x.mongodb.wire (OP_MSG, bson, SCRAM, 187 vs pymongo), x.elastic.rest (REST request encoders and response readers, 171 vs elasticsearch-py). No sockets, cluster/Sentinel, sessions or typed ES DSL; nothing run against a real server.

### L101 — gRPC transport and stubs over e.fmt.protobuf

Partly delivered (D2646): e.net.http2 (209 checks vs hpack/hyperframe/h2) and e.net.grpc client protocol (100 checks, 10 transcripts from a grpcio server). Client side only: no server, HTTP/3 binding, TLS dial, deadlines or stub generation from .proto.

### L151 — Industrial protocols: Modbus first, OPC UA and S7 follow

Delivered (D2647): x.modbus.wire Modbus PDUs and TCP/RTU/ASCII framers (222 checks vs pymodbus). No file-record/diagnostic codes or transports; OPC UA, S7 follow.

### L126 — D-Bus message codec and client for Linux desktop

Delivered (D2648): e.dbus message codec and client (444 vectors vs dbus-next). No AF_UNIX transport/fd passing, introspection or service export.

### L161 — Rules engine: Rete plus decision tables

Delivered (D2760): e.algo.rules, a Rete network (alpha memories shared) plus decision tables, 70 checks against an independent brute-force model. No beta sharing, exists/forall/accumulate or truth maintenance.

### L139 — Object-object mapper with conventions and projections

Delivered (D2761): e.data.mapper object-object mapping with name conventions and projections (64 checks). Enums, pointers, non-str slices and the comptime generation follow-on not done.

### L140 — Persistent background jobs with retries and cron triggers

Delivered (D2762): e.task.jobs persistent jobs with retries, backoff and cron triggers (about 224 checks vs croniter). Single-threaded, in-memory queue persisted through e.store (not an e.db table), fixed UTC offsets only.

### L147 — Embedded document and event store

Delivered (D2763): e.db.docstore, an embedded document/event store with a CRC-framed log and replay (93 checks, byte-exact vs an independent writer). Linear lookups, no secondary indexes or transactions.

### L141 — Virtual-actor framework over e.dist

Delivered (D2764): e.dist.actor, a virtual-actor framework with silos, placement (rendezvous hashing), reminders and failure handling (74 checks). Placement model inside one process; no networking.

### L149 — Crash and error report upload client

Delivered (D2765): e.debug.report, a crash/error report client with Sentry DSN, auth and envelope serialization byte-exact vs sentry-sdk (101 checks). Faked transport; no sessions, breadcrumbs or gzip.

### C177 — Compiler: comptime Field/Member generic arguments compare by index only

Fixed (D2440): generic_arguments_equal compares the owner of a Field or Member as well as its index; fixture generic_field_owner fails (exit 2) before and passes after, and the changed compiler rebuilds to identical bytes. Full suites not run.

### L060 — Variational inference in e.math.mcmc

Delivered (D2841): advi (mean-field Gaussian, Adam, reparameterised ELBO), elbo, variational_samples and Fit in e.math.mcmc over the same callbacks as hmc/nuts; checked against closed forms, quadrature and the BFGS optimum (correlated normal, banana, log-gamma). Not met: a Stan run as reference, e.ml.nn tape import, full-rank covariance, constrained transforms.

### L099 — Ink canvas: stroke capture and replay in e.ui.widget

Delivered (D2844): e.ui.ink, a caller-storage ink canvas (begin/extend/end with decimation, cancel, erase, bounds, hit, width_at from pressure, duration, replay_counts, path_of), driven by real e.ui.input pen Events (42 checks). Separate module rather than inside widget.e. No pixels, smoothing or serialisation.

### L152 — Micro-slivers III: CMS signing, json5, TFTP, singleflight, host lookups, log rotation

Delivered (D2802): e.crypto.cms (Ed25519 SignedData accepted by openssl cms -verify; RSA/ECDSA verification built), e.fmt.json5, e.net.tftp (RFC 1350 over loopback), e.sync.flight (singleflight), e.log.rotate (against RotatingFileHandler). CMS signing is Ed25519 only; TFTP has no timers, server or netascii; MAC addresses and some host lookups not built.

### L160 — Micro-slivers IV: robots, sitemap, test polling, fixed-width, keystores

Delivered (D2803): e.net.robots (RFC 9309, protego), e.fmt.sitemap, e.test.poll (Awaitility model), e.fmt.fixedwidth, e.crypto.jks (pyjks) and e.crypto.pkcs12 (read and write, accepted by cryptography and openssl). No JCEKS/BKS, PKCS#12 legacy ciphers or SHA-1 MACs; robots agent match is exact.

### L157 — Expression languages: JEXL, SpEL and MVEL parity

Delivered (D2804): e.algo.expr, an expression language (JEXL/SpEL/MVEL subset) checked against an independent Python implementation of the documented semantics (1121 checks); no JVM engine on this host, so not engine parity. Assignment, lambdas, new/type references, projection and regex matches absent.

### L156 — Brokerless messaging patterns: ZeroMQ and NNG

Delivered (D2805): e.net.zmtp (ZMTP 3.x NULL, REQ/REP, PUB/SUB, PUSH/PULL, DEALER/ROUTER) and e.net.sp (nanomsg SP over TCP) checked against libzmq 4.3.5 and NNG via recorded streams and scripted peers. No PLAIN/CURVE, heartbeats, reconnect, SP raw mode or devices.

### L040 — Cascade, matcher, and accessibility-name kernels

Vaper css/container_query.dart (Kleene and/or/not plus scope proximity), style_resolver id/class/tag rule-index buckets with origin/importance/specificity/order/proximity sort, selector_matcher right-to-left combinator walk (adapted off the package:html DOM), a11y role map with aria-labelledby over aria-label over native over content. Port logic kernels into e.algo.logic and e.ui.accessibility. PART ONE (D2343): lib/e/fmt/css/container.e, e.fmt.css.container -- container_query.dart; fixture text_css_container, 400 trees. PART TWO (D2343): lib/e/fmt/css/match.e, e.fmt.css.match -- selector_matcher.dart over an e.fmt.html document; fixture text_css_match, 560 cases. PART THREE (D2343): lib/e/fmt/html/accessible.e, e.fmt.html.accessible -- accessibility_builder.dart over an e.fmt.html document; fixture html_accessible, 220 documents. NOT DONE: the style_resolver kernels with no public surface to compare against (rule-index buckets, @scope proximity, declaration precedence incl. hints and layers, containersMatch over a container stack). COMPLETED (D2920): e.fmt.css.cascade covers declaration ranking with hints, layers, @scope proximity and source order, the id/class/tag rule index, containersMatch, scope-root search with donut limits, presentational hints, inline style and the full cascade with shorthand-over-longhand dropping, checked against Vaper's own StyleResolver on 130 documents / 1282 elements. Parser differences in e.fmt.html (nested li, table in cell) are outside the item.

### T022 — Reproducible-build check

Both suites check the compiler's fixed point -- stage 2 and stage 3 byte for byte -- and, since D261, that a program built twice is the same executable and that the second build's manifest carries the first's artifact SHA-256, so two builds can be compared by their manifests without the executables (D254 wrote the hash); `neper compare-manifests A B [--json]` (D482) is that comparison as a command -- identity, inputs, dependencies and artifacts by hash, not path -- and both suites hold two builds' manifests to agree and a debug one to differ from a release one by mode and artifact. The manifest carries every dependency's interface and body hash and, since D1685, every imported library's file hash; `compare-manifests` holds dependencies, libraries (requested name and SHA-256, not the resolved path) and assets to them (D1696), pinned by a zeroed kernel32 / libc.so.6 hash in both suites. Not yet: cross-host comparison (a Windows and a Linux build differ by design) DONE (D4304): compare-manifests A B [--cross-host] [--json] holds architecture, mode, root, tool_version, options, inputs, dependencies and assets to agree and skips per-target variant files; run_args built x64 windows and x64 linux shows 6 plain differences and 'manifests agree' with --cross-host; cases in both suites; stage 2 equals stage 3; dependency and library hashes were delivered by D1685 and D1696.

### L037 — Offline-first sync, conflict merge, presence, verifiable history

Appdor src/offline (coalescing enqueue, cursor pullChanges, field-level conflict detect with manual/LWW/field-merge resolve, durable queue with dead letters), src/sync (mapping propose, lease claim, doubling backoff, drift accept), src/history (diffRecords, revision replay, sha256 prev-plus-canonical tamper-evident chain), src/realtime (30s-TTL presence, version-or-LWW merge; polling transport flagged). Port into e.algo.sync/merge/queue/diff/chain/presence. PART ONE DELIVERED (D2336): lib/e/algo/chain.e, e.algo.chain -- the hash chain, diff, WAS/CHANGED predicates, history filter, field history, plan retention and export; fixture algo_chain, 220 scripts against appdor's tamper-evident.js on Windows and Linux. PART TWO (D2337): lib/e/algo/sync.e, e.algo.sync -- src/offline index.js, durable-queue.js and sync-engine.js: coalescing queue, durable outbox (backoff, dead letters, quota-aware persistence, attachment holds), cursor and delta pull, field-level conflicts and resolution, run_sync; fixture algo_sync, 260 scripts against appdor's own modules on Windows and Linux. PART THREE (D2338): lib/e/algo/realtime.e, e.algo.realtime -- presence, cell resolution, record merge, viewer filter, degradation, topic authorization, connection lifecycle, telemetry, payload trimming, view membership; fixture algo_realtime, 220 scripts against appdor's src/realtime on Windows and Linux. NOT DONE: src/offline write-queue.js, conflict-review.js, read-cache.js, access-purge.js; src/sync (mapping, lease, backoff, drift). PART FOUR (D2339): lib/e/algo/syncjob.e, e.algo.syncjob -- src/sync sync-schedule.js, sync-refusal.js and the pure half of synced-table.js with syncPlan; fixture algo_syncjob, 700 inputs against appdor's own modules on Windows and Linux. NOT DONE: src/offline write-queue, conflict-review, read-cache, access-purge; src/sync writeback.js, change-stream.js, entity-browse.js, proposeMapping/pagination parts of synced-table.js, sql-source.js. PART (D2921): e.algo.offline (write queue, read cache, conflict review, access purge) and e.algo.syncsource (change stream, entity browse) ported and checked against appdor's JS modules under node (220 scripts, 700 operations); a bug fixed in e.algo.sync (an absent field is not null). NOT DONE: writeback.js, sql-source.js, the proposeMapping and pagination halves of synced-table.js, the review renderer. PART (D3000-D3003): e.algo.writeback, e.algo.sqlsource, e.algo.syncpull, e.algo.conflictview each compared against appdor's own JS under node (900/900/700/300 generated cases, mutation checks recorded). Missing: the sample-inferred half of proposeMapping (io/infer.js). PART (D3703): e.algo.syncinfer, the inferred half of proposeMapping and a port of V8's DateParser; algo_syncinfer 1,700 vectors from appdor's JS under node all agree. Missing: coerceValue/coerceRecord of infer.js. DONE (D4600): e.algo.syncinfer.coerce_value/coerce_record ported from appdor io/infer.js; algo_syncinfer_coerce 4,259 vectors from appdor's own JS under node in four local zones (UTC, Asia/Kolkata, America/Phoenix, Etc/GMT+7), all agree; three real V8 DateParser-port defects fixed; algo_syncinfer (1,700) and algo_syncpull still pass.

### L162 — Chart benchmarks against ggplot2, base R graphics and lattice

Backlog from L061 (D2109). benchmarks/charts measures Neper against matplotlib only; ggplot2, base R graphics and lattice need an R installation, which the benchmark host does not have and which needs the user's approval to download. Add an R script beside mpl_bench.py with the same LCG data, 360x240 output, SVG text kept as text and PNG at a comparable compression level, run nine-run medians through run.py, and add the rows to benchmarks/charts/README.md and the charts field-guide post. ATTEMPT (D2845): no Rscript/R on this host; nothing installed (the item requires the user's approval to download R). Left at 0. DONE (2026-10-13, user-approved R install under D:	ools\R: R 4.6.1, ggplot2, svglite, lattice): run.py five-run medians per chart, SVG neper 3.93 ms vs base R 13.2, lattice 34.9, ggplot2 288.6; PNG neper 11.03 ms vs base 23.6, lattice 51.7, ggplot2 261.8; SVG 28-29% smaller than R's; R's PNGs are 3.5x smaller (Neper writes 32-bit RGBA, the adaptive palette encoder is not used by the benchmark); first ggplot2 chart checked by eye; table and caveats in benchmarks/charts/README.md and results/windows.json.

### C147 — Full suites complete on this machine: Windows run.ps1 and Linux run.sh

Split from C115 (2026-10-08). Neither full suite finishes here: tests/selfhost/run.ps1 trips on PowerShell's Stop preference when a native command writes to stderr, and the Linux run.sh builds with neper build, which crashes the WSL2 VM on this host. Per-feature fixtures have been run by hand on both hosts. Acceptance: (1) run.ps1 runs to its end on this Windows host without manual patching; (2) run.sh runs to its end in WSL, with the memory it needs set down in the script's header and the VM left alive; (3) each reports its last line and the count of checks, and the totals feed docs/test-results.json, the tile on the readiness page. PART (D2313): NEPER_SEED in run.ps1 (the bootstrap cannot build src/main.e under this host's commit), stale assertions fixed, fix_module_surfaces.py, -j 2 for the two huge fixtures; run.ps1 passes stage 1 and about 3,700 lines. PART 2 (D2317): NEPER_JOBS caps default workers from the environment; stale NeperOS and determinism assertions fixed; the seeded Windows run passes to line 9914 of 9937 (stops at the Flashlight timing fixture; sc500k static gate needs >3 GB free commit; network check hits a live API). NOT DONE: a complete run on either host (run.sh under WSL not run) and the test-results.json totals. RUN 17 (2026-10-10, seeded, with the sc500k static gate and the live-API network assertion excluded through an untracked copy): every row passes through the NeperOS app fixtures, including x_migrate, the capabilities golden and the --compact rows; the only stop is the Flashlight fixture's `morse done` marker, which waits on wall-clock ticks the emulated frames delay on a loaded host. DONE (2026-10-23, commit ebc03203c, D5186-D5193): both suites run to their last line on clean checkouts of that commit, unpatched and unseeded: run.ps1 in 45 minutes and run.sh in WSL in 41, the VM left alive. The memory a run needs is in run.sh's header (the VM went down twice at 3.2 GB of free commit; keep 5 GB free). The NeperOS tests, most of the old wall time, run only with NEPER_NEPEROS=1 (D5186), because NeperOS work is paused. Each suite prints scripts/check_suite_parity.py's count first (1,122 fixtures named per suite) and ends with 'selfhost tests passed'; docs/test-results.json records both runs. Fixed on the way: the e.net.ssh key-switch race (D5187), the bootstrap's one-environment-variable limit (D5188), fixtures that passed silently without their font (D5189), NEPER_REFRESH_GOLDENS=1 (D5190), the run.sh/run.ps1 parity check (D5191), 52 fixtures no suite ran (D5192), and the unbounded cli_config watch (D5193). Not part of the claim: the NeperOS fixtures, and the totals are recorded by hand, not fed by the suites.

### C180 — wasm32-wasi 1: target, whole-program emitter, dispatch-loop control flow, integer subset, runtime in os.wasi.e

Design D5213. Acceptance: (1) `emit-executable FILE ROOT wasm32 wasi OUT` and `neper build FILE --target wasm32-wasi` write a module Node instantiates (project.e target matrix, wasm_command beside spirv_command, src/wasm.e); (2) integer, bool, err and pointer instructions, calls with 0-2 results, Stack frames on the shadow stack, Load/Store/Copy/Zero, globals, strings, checked arithmetic and traps with native text and status 134; (3) lib/e/os.wasi.e defines the neper_* runtime symbols the subset reaches (write, stdout, stderr, exit, args, neper_mem_*, neper_hash_bytes, neper_trap) and _start; (4) scripts/run-wasm.mjs, `scripts/check-fixture.sh NAME --target wasm32-wasi`, and scripts/wasm-sweep.sh comparing exit status and stdout with the host x64 build of each link fixture; (5) a new link fixture wasm_basics passes on wasm32-wasi under Node on Windows and WSL and natively; (6) the sweep passes at least 20 link fixtures. DONE (D5600-D5602): the target (project.e, render_tasks.py VARIANTS), graph.load adding e.os for wasi, wasm_command beside spirv_command, src/wasm.e and src/wasm_code.e, lib/e/os.wasi.e with every neper_* symbol the subset reaches and the WASI imports, scripts/run-wasm.mjs, `check-fixture.sh NAME --target wasm32-wasi` (NEPER_COMPILER names a prebuilt compiler), scripts/wasm-sweep.sh. wasm_basics passes natively (x64-windows), on wasm32-wasi under Node 24 on Windows and Node 22 in WSL, and its traps print native's text with status 134 (overflow, divide, bounds, stack overflow); the compiler builds with the C bootstrap and stage 2 == stage 3. Sweep, stage-2 compiler, 1,127 link fixtures: 124 pass, 30 fail, 877 refused, 0 invalid, 96 skipped (parallel host builds); 16 of the 30 failures were Node aborting in process.exit and pass with the runner fixed, so 140 pass. A later run of the final compiler over the first 911 fixtures (stopped by the coordinator): 122 pass, 14 fail, 768 refused, 0 invalid, 7 skipped. The 14 failures: capacity_wide (one 6,000-block function; V8 runs out of Zone memory on the dispatch loop's br_table -- C183), freestanding (reads its own ELF headers; native-only), and 12 that use files, processes, sockets, locks, maps or watches (os_fs, os_group, os_lock, os_mapping, os_process, os_resolve, os_socket, os_watch, fs_mmap_watch, macos_poller_loss, grep, list_owning -- C182). The refusals are the next rows: 'takes a function's address' (e.io Writer/Reader interfaces: file_writer, slice_writer, push; indirect calls, C181), floating-point arithmetic (C181), and a few native-only fixtures (thread_create, libc.so.6). Node's own call stack (about 10k frames) ends deep recursion before the 8 MiB shadow stack, and the runner reports it as a stack-overflow trap.

### C181 — wasm32-wasi 2: the rest of NIR (floats, casts, f16/bf16, Switch, indirect calls, atomics, simd128)

Design D5213, D5603-D5607; src/wasm_code.e, src/wasm.e, fixture link/wasm_ops (wasm32-wasi under Windows Node and WSL Node). Floats, casts, indirect calls through one funcref table, atomics, simd128. Switch has no producer (D5607) and f16/bf16 and the ftz fence are not in codegen_a64 either (D5603, D5605). After C182 the sweep (1131 fixtures) is 978 pass, 81 fail, 65 refused, 1 invalid; every remaining failure is threads, sockets, processes, devices, host fonts or a giant function V8 refuses (C183), none an opcode bug (D5623).

### C182 — wasm32-wasi 3: the WASI surface (files, readdir, clock, random, environment) and .wasi.e variants

Design D5213, D5620-D5623; lib/e/os.wasi.e (files over path_open on the preopens, readdir, clock, random, environment, working directory, symlinks, canonical, *_at; threads, spawn, wait, reserve, commit Unsupported; wait_u32 sleeps out a finite timeout and stops a wait nothing can end (D5664), wake_* do nothing), .wasi.e variants of e.os.ident, e.os.shell, e.proc.sys.host, e.debug.dump.host, scripts/run-wasm.mjs (preopens, environment, readdir for Windows Node). fs_basics, os_clock_random and os_environment pass on x64-windows, wasm32-wasi under Windows Node and WSL Node; os_* pass as ELF under WSL. fs_basics skips three blocks WASI cannot do on wasm32-wasi (D5622).

### C183 — wasm32-wasi 4: structured control flow, operand folding, name section

Design D5213, D5635-D5639; src/wasm_flow.e (new), src/wasm_code.e, src/wasm.e, fixture link/wasm_flow, scripts/wasm-sweep.sh, scripts/wasm-bench.sh. (1) Reducible functions are written as block/loop/if/br from the dominator tree and reverse postorder (Ramsey); over the 996 fixtures that emit, 176,530 of 176,532 functions are structured and the 2 that kept the dispatch loop are irreducible (main.nested, main.mismatched_for in gpu_barrier_occurrence, which passes through it); NEPER_WASM_STATS=1 reports the counts and the sweep sums them; NEPER_WASM_STATS=dispatch forces the fallback (160 random passing fixtures all still pass). (2) Single-read values wait on the operand stack for their reader, planned per block and checked against the code written (D5636), and block-local values share locals (D5637). (3) The name section names module.function in a Node stack trace (null call: main.apply, main.outer, main.main, _start). (4) Sweep over 1,130 link fixtures: 951 pass, 45 fail, 0 invalid, 128 refused, 6 skipped (C181: 943/46/1/117/21); no fixture that passed under the C181 compiler fails; capacity_wide and gfx_vision pass. benchmarks/cpu against the dispatch loop: hash 2803 -> 1856 ms, sieve 1078 -> 688 ms, sort 1338 -> 891 ms, modules about 24% smaller (records overflows under the checks before and after). Ceiling: every value is still an i64 and source variables live in frame slots (D5600); the 45 failures are C182's surface and freestanding.

### C184 — wasm32-wasi 5: the compiler itself as neper.wasm

Design D5213, D5640, D5641; lib/e/os.wasi.e (reserve, commit, release, peak_memory), src/wasm.e (_start always calls neper_start_args), src/platform.e and src/platform.wasi.e (new: jobs, reservation, triple), src/graph.e, src/em_link.e, src/main.e, src/stats.e, scripts/run-wasm.mjs (NEPER_WASM_MEMORY), scripts/wasm-compiler.sh (new), fixture link/wasm_reserve. (1) `v2.exe emit-executable src/main.e . wasm32 wasi neper.wasm` writes a 4,689,531-byte module, 3,330 functions all structured. (2) Run from the repository root under Node 24, neper.wasm emits every link fixture for x64 windows and x64 linux: 2,266 pairs, 2,196 byte-identical to neper-try, 10 refused with the same diagnostics, 58 different only in the embedded compiler identity (device code carries the compiler file's CRC and size, D398/D1734, so two native compilers differ there too), 2 (gpu_tensor) different in a requirements constant that the native compiler gets wrong at its default worker count and right at -j 1, which neper.wasm matches (C200). neper.wasm emits the compiler itself for x64 windows byte-identical to v2.exe and v3.exe, and for x64 linux to the native output. (3) Stretch reached: neper.wasm emits src/main.e for wasm32 wasi byte-identical to the neper.wasm v2.exe wrote (wasm fixed point). (4) Cost, compiler for x64 windows: native 1.6 s (default workers) / 2.2 s (-j 1, 0.9 GB commit); neper.wasm 5.6 s, 986 MB working set, 3,368 MiB linear memory, 7.1 GB Node private bytes (V8's optimizing tier; 5.5 GB with --no-wasm-tier-up). For wasm32 wasi: native 1.8 s, neper.wasm 3.1 s, 2.5 GB. (5) Sweep 984 pass, 78 fail, 65 refused, 0 invalid, 6 skipped of 1,133 (before 978/81/65/1/6 of 1,131), no regressions. v2 == v3 after every src change.

### C210 — A module with variants for other targets only names them

Design D5682, D5690; src/project.e (NoVariant, variants_seen), src/graph.e (Graph.variant_note, resolve_source), src/main.e, tests/conformance/reject/module_variants_other, run.sh and run.ps1. (1) The 17 refusals in scripts/wasm-sweep.sh now read `use plat` has variants for linux, macos and windows and none for wasi (8 plat fixtures), and x.sqlite.capi, x.postgresql.capi, x.openssl.capi, x.microsoft.capi, x.oracle.mysqlclient the same way with their own variant lists (9 fixtures). (2) reject/module_variants_other pins `use host` has variants for aarch64 and x86 and none for x64 (E-MODULE-0001) on both hosts; module_missing keeps its own text and is byte-identical. (3) v2 == v3; 20 link fixtures emit byte-identical executables with the compiler built from HEAD~ and the new one; no other expected diagnostic changed. The new conformance case was checked with check-file on the windows host; the full suites were not run here.

### C206 — A browser host for wasm32-wasi modules: lib/wasm/neper-host.js

Design D5678; decisions D5685-D5689; lib/wasm/neper-host.js, lib/wasm/package.json, scripts/serve-wasm.mjs, scripts/wasm-sweep.sh (--host neper-host|run-wasm|both), tests/wasm/browser/index.html, tests/wasm/browser/host_files, tests/wasm/host.mjs, the wasm32-wasi block of tests/selfhost/run.sh and run.ps1. (1) wasm_basics, wasm_ops, wasm_flow, wasm_reserve, fs_basics, os_clock_random and os_environment pass through neper-host.js under Node 24.19 and Node 22.14 (wasm-sweep.sh --host neper-host: native stdout and status). (2) Full sweep, `--host both -j 3`, 1,134 fixtures: run-wasm.mjs 1,026 pass, 78 fail, 0 invalid, 23 refused, 7 skipped; neper-host.js 1,018 pass, 86 fail, 0 invalid, 23 refused, 7 skipped. The 78 are the same; the 8 more (gfx_svg_text, gfx_svg_text_faces, gfx_chart_word_cloud, text_math, web_shell, web_page_csp, ui_html_view, text_cleartype_oracle) read repository font files from the working directory, which the in-memory tree does not hold; seeded through `files`, six of them exit 0 (gfx_svg_text byte-identical to native). (3) Browser pane (Chrome 152, serve-wasm.mjs plain and --isolated): wasm_basics and fs_basics exit 0 with the native stdout on both pages; wasm_release in debug exits 134 with the trap text. (4) No browser runs in the suites; tests/wasm/host.mjs (API: URL, bytes, Module, Response, files in and out, env, args, 134, 125) runs in the wasm32-wasi block under node, on Node 22.14 and 24.19.

### C203 — wasm32-wasi sockets, resolution and the poller through neper_host

Design D5675, D5676; built as D5720-D5722. src/wasm.e (register_import accepts neper_host), lib/e/os.wasi.e (the socket, resolver, poller and send_file functions over 19 neper_host imports and fd_pread), lib/e/net.e (Wasi arms of map_error_with_code and already_connected), scripts/run-wasm-host.mjs (new: the Worker's import shims, the main thread's mailbox server, NetHost over node:net, node:dgram and node:dns), scripts/run-wasm.mjs (wires them), fixture link/wasm_net, and the six socket fixtures in the wasm blocks of run.sh and run.ps1. (1) os_socket, os_resolve, async_io, macos_poller_loss and net pass: in scripts/wasm-sweep.sh -j 3 on Windows Node 24 (host x64-windows build compared, same status, stdout and stderr), and the same modules exit 0 with the expected output under WSL Node 22.23.1 (not a WSL sweep: there is no Linux compiler here). wasm_net (refused connect named Refused, nonblocking accept, poller readiness and a latched wake, connected datagram, 300 KB in order, send_file across the 32 KiB pieces) passes on x64-windows, wasm32-wasi on Windows Node 24 and on WSL Node 22. (2) Full sweep: 1037 pass / 72 fail / 23 refused / 0 invalid / 7 skipped of 1139 against 1033 / 77 / 22 / 0 / 6 of 1138; the only pass-to-other changes are ui_pickers3_v2 and ui_presentation, which hit 'the compiler's arena is exhausted' at -j 3 (the host build of ui_presentation too) and pass alone, so no regression; the five above and wasm_net are new passes. A module that reaches no socket function imports nothing from neper_host (wasm_basics: wasi_snapshot_preview1 only), and differs from its build before this change only in trap-site constants, which are source line numbers (D5722). v2 == v3; scripts/wasm-compiler.sh 8 of 8 identical. (3) A 64-byte TCP echo between two sockets of one module (two sends, two receives): 360 us on Windows Node 24, 704 us in WSL Node 22. The 14 net_* fixtures that start a server thread still fail on thread_create (Unsupported) after reaching their socket calls, none hangs; they are C204. Not done: a Linux sweep of the socket fixtures with a native host build to compare, and a connect to a closed port on the Windows x64 build of e.os, which never completes (D5722).

### C201 — wasm32-wasi --threads: the threaded module shape and real atomics

Design D5671, D5672; built and measured in D5710-D5713; src/wasm_threads.e (new), src/wasm.e, src/wasm_code.e, src/main.e, scripts/run-wasm.mjs, scripts/check-fixture.sh, scripts/wasm-sweep.sh, fixtures link/wasm_atomics and wasm/wasm_thread_ops, the wasm block of run.sh and run.ps1. (1) The compiler from before the change and the changed one (v2) each emitted the 1,110 link fixtures that emit, plus neper.wasm (6,600,026 bytes): 1,110 of 1,110 plain modules byte-identical (482,023,829 bytes compared) and neper.wasm identical; scripts/wasm-compiler.sh 8 of 8 identical; v2 == v3. (2) link/wasm_atomics (generated from a two's-complement model): load, store, add, sub, and, or, xor, xchg, min and max (signed and unsigned), cas (hit, miss, miss by the top bit) at 8, 16, 32 and 64 bits, the four fences, and the same through a field, a local, an array element and a pointer parameter; 218 lines of the same stdout on x64-windows, wasm32-wasi plain and wasm32-wasi --threads. (3) wasm-tools validate --features threads passes on the threaded modules of wasm_basics and wasm_atomics; wasm-tools print shows (import "env" "memory" (memory 129 65536 shared)), the wasi_thread_start export, memory.init/data.drop and segments without an offset. (4) scripts/wasm-sweep.sh -j 3 over 1,139 fixtures: plain 1,034 pass, 77 fail, 22 refused, 0 invalid, 6 skipped; --threads 1,034 pass, 77 fail, 22 refused, 0 invalid, 6 skipped, the same fixtures in each class (baseline 1,033, 77, 22, 0, 6 over 1,138; the added pass is wasm_atomics). (5) The wasm block of run.sh (extracted, run against v2) and its run.ps1 rows pass, new rows included; the two full suites were not run whole, they do not finish on this machine. Not done here: running a module on more than one thread (C202).

### C211 — wasm32-wasi source maps, and line numbers for the engine's traps

Design D5683; built as D5740-D5742. src/wasm_map.e (new: VLQ, JSON, sourceMappingURL section), src/wasm_code.e (entries made in emit_folded and begin_function, made file-relative in finish_function), src/wasm.e, src/main.e (--source-map on emit-executable and build), lib/wasm/source-map.js (new: addLines), scripts/run-wasm.mjs and lib/wasm/neper-host.js (the engine error gets [path:line] per wasm-function frame), tests/wasm/null_call, the D5651 blocks of run.sh and run.ps1. (1) tests/wasm/null_call built with --source-map: both runners print `at main.fire (wasm://...:wasm-function[15]:0x1ba2) [src/main.e:13]` (the hook.run call), then main.relay [src/main.e:17], main.main [src/main.e:24]; the blocks check that first frame through run-wasm.mjs and neper-host.js, that OUT.map exists exactly when asked for, and that a build without the flag prints no line. Map: Source Map v3, sources as trap records spell them, names empty, one generated line with byte-offset columns; neper.wasm writes a 460 KB map. (2) wasm-tools validate passes on null_call and on neper.wasm built with --source-map. (3) The compiler from before and the changed one (v2) each emitted the 1,140 link fixtures: 1,112 modules written by both, byte-identical (482,412,620 bytes compared), the same 28 refused by both; neper.wasm without the flag identical to the one the new source gives without it; scripts/wasm-compiler.sh 8 of 8 identical; v2 == v3. Seven-fixture wasm-sweep.sh --host both pass. DWARF stays unwritten (D5684). The full sweep was not re-run: the modules are byte-identical and the runners change only an error text beside a .map. Node does not apply a wasm module sourceMappingURL itself (D5741); no browser DevTools check.

### C202 — wasm32-wasi threads: the thread runtime in os.wasi.e and the Node thread host

Design D5673, D5674; built as D5730-D5732. os.wasi.e: the D5672 pseudo-imports; thread_create/join/detach over D5673's block (first-fit free list, else a reservation; rt_grow covers it; tid at +4 after the spawn), rt_lock (Drepper's mutex over cas32/load32/wait32/store32/notify; the design's acquire loop would spin on 1, D5730) over reserve, release and the free list; wait_u32/wake_one_u32/wake_all_u32 over wait32/notify when wasm_threads() is 1; current_thread_id = thread.id + 1; last_error_detail in os.linux.e's 64 thread-keyed slots; mounts loaded in neper_start_args on a threaded module; rt_grow re-checks after a failed grow. Plain modules: thread calls Unsupported, the single-thread futex unchanged. scripts/run-wasm.mjs: a module importing env.memory runs under the D5674 host (main thread owns the shared memory and one node:wasi with the readdir shim, every thread a Worker proxying WASI through a 128-byte mailbox answered with Atomics.waitAsync; thread-spawn reuses an idle Worker by a start slot in the mailbox or makes one, tids from 1, -6 past 0x1FFFFFFF; non-first Workers unref'd; proc_exit through the mailbox, so ordered with other threads' output; relative-clock poll_oneoff sleeps in the Worker; stack 256 MB first, 64 MB others; neper_host per thread over one shared NetHost, scripts/run-wasm-host.mjs). scripts/check-fixture.sh now passes --threads to the wasm build (a C201 gap). Fixture link/wasm_threads (D5674's list plus a thread blocked for ever when main returns), in extra-fixtures.txt and in the wasm block of run.sh and run.ps1 (built --threads, output pinned, `exit` -> 7); wasm_thread_ops spawns only in the plain shape (its threaded spawn started a real thread on address 0, D5732). (1) wasm_threads ten runs in a row identical on x64-windows, wasm32-wasi --threads under Windows Node 24.19.0, x64-linux (WSL) and wasm32-wasi under WSL Node 22.23.1; `exit` gives 7 on both. (2) scripts/wasm-sweep.sh --threads: thread_spawn, thread_pool, thread_group, thread_perturb, sync_guard, sync_rwguard, sync_dataguard, sync_flight, os_futex, os_exit_threads, concurrent_deque_stack, concurrent_queue_map, cancel, mediator, task_pool pass; test_poll, thread_fiber, js_generator_shutdown pass; error_detail stops at os.pipe (Unsupported on WASI, before its thread section); runtime_gaps passes its thread sections and stops at mmap.map (exit 62); cli_config passes its watchdog thread and stops at watch.open (73); gpu_device_lock exits 0 but the host build found a Vulkan device and the module is CPU only. Of the 52 fixtures that use threads, 42 pass on Windows Node 24 and the same 42 under WSL Node 22; none hangs. (3) Full sweeps, -j 3, 1,141 fixtures: plain 1,040 pass / 73 fail / 22 refused / 0 invalid / 6 skipped, no pass-to-other change against the C203 tree's sweep (wasm_threads fails plain, as every thread fixture does); --threads 1,066 / 47 / 22 / 0 / 6, every plain pass passes threaded (os_wait_timeout once failed in its native host build, a 60 ms WaitOnAddress waking early under load, and passed three of three run again) and 27 more pass: cancel, concurrent_deque_stack, concurrent_queue_map, js_generator_shutdown, mediator, net_ftp, net_grpctls, net_http, net_http_pool, net_mdns, net_socks, net_sp, net_tftp, net_zmtp, os_exit_threads, sync_dataguard, sync_flight, sync_guard, sync_rwguard, task_pool, test_poll, thread_fiber, thread_group, thread_perturb, thread_pool, thread_spawn, wasm_threads. (4) The 200 spawn-and-join cycles: the whole run 148-171 ms on Windows (2 Workers), 256 ms in WSL (3). No src/ change: v2 == v3, scripts/wasm-compiler.sh 8 of 8 identical. Left to C204: net_imap, net_ldap, net_pop3, net_smtp, net_tls.

### C207 — Threads in the browser host: cross-origin isolation, the page as host

Design D5679 (on D5674's protocol); built as D5760-D5762: lib/wasm/neper-host.js (runThreads, threadWorker, importedMemory; the calling thread owns the shared memory, makeWasi and the answers, every wasm thread a Worker with mailbox WASI imports in D5731's layout, thread-spawn a host call reusing idle Workers, Atomics.waitAsync with a ping-message fallback, relative-clock poll_oneoff slept in the Worker, one isolation sentence when crossOriginIsolated is false), tests/wasm/host.mjs and the wasm block of run.sh and run.ps1, tests/wasm/browser/index.html (?messages=1, error), scripts/serve-wasm.mjs (no longer dies on a missing file), fixture link/wasm_threads (makes its own directory instead of reading the repository's tests). (1) wasm-sweep.sh --host neper-host --threads -j 3 under Node 24.19: wasm_threads, wasm_atomics and the fifteen thread fixtures all pass. (2) Browser pane (Chrome), pages from serve-wasm.mjs: with --isolated wasm_threads exit 0 with the native stdout, `exit` gives 7, and the same 17 fixtures run by run() in the page match their native stdout with Atomics.waitAsync answering and again with messages:true; without --isolated run() rejects with the isolation sentence. (3) Plain wasm_basics, fs_basics and wasm_release on both pages as in D5687 (0, 0, 134 with the overflow trap text). Full threaded sweep, 1,141 fixtures: neper-host.js 1,044 pass / 69 fail / 22 refused / 0 invalid / 6 skipped, run-wasm.mjs 1,067 / 46; nothing passes only through neper-host.js; the 23 that pass only under run-wasm.mjs are sockets (15, neper_host is ENOSYS in a page) and the eight that read repository fonts (D5686). The design missed that TextDecoder and getRandomValues refuse a view over shared memory in a browser (Node accepts), that poll_oneoff was never in the host, and that wasm_threads read the repository (D5761). No src/ change; a compiled WebAssembly.Module cannot be the source of a threaded module.

### C204 — wasm32-wasi: the net_* corpus on --threads

Design D5676; built as D5750, D5751. The five net fixtures that start a server thread and still failed after C202 (net_imap, net_ldap, net_pop3, net_smtp, net_tls) stopped at os.pipe (Unsupported), which their STARTTLS server threads use to reach the client; the other nine of the list already passed on C202's thread runtime. Built: D5677's pipe, handle_read (with the nonblocking flag pipe_read needs), handle_write and handle_close in scripts/run-wasm-host.mjs (a Pipe object over Sock's queue; blocking reads are promises, one mailbox per thread), and os.wasi.e's pipe, pipe_read and three routines reached through function values pipe() arms (D5677's routing in neper_os_read/write/close would have made every program import handle_*; the number test excludes the largest raw, error_detail's deliberate invalid handle). (1) All 47 net_* fixtures, the 14 of the list included, pass in scripts/wasm-sweep.sh --threads -j 3 on Windows Node 24 (five runs in a row, 47 of 47) and under WSL Node 22.23.1 (235 of 235, stdout against the host build; net_ssh is a client driven by arguments and exits 90 on both builds); none needed recording as unable. (2) Full sweeps, 1,142 fixtures, -j 3: plain 1,041 pass / 73 fail / 22 refused / 0 invalid / 6 skipped; --threads 1,074 / 40 / 22 / 0 / 6 (C202: 1,066 / 47 / 22 / 0 / 6 of 1,141); every fixture that passes plain passes --threads, none that passed C203's plain sweep fails; error_detail now passes both, os_pipe_threads fails plain as every thread fixture does. (3) Five consecutive runs of the passing net set, Windows and WSL, no failure. New fixture link/os_pipe_threads (same stdout on x64-windows, --threads under Node 24 and Node 22), in extra-fixtures.txt and, with net_pop3, in the wasm block of run.sh and run.ps1. No file under src/ changed: scripts/wasm-compiler.sh 8 of 8 identical; plain modules differ from the build before only in trap-site line constants and gain no import unless they call pipe.

### C208 — e.ui in a browser: CPU frames on a canvas, input through a shared ring

D5790, D5791. lib/wasm/window.js and neper-host.js run(source,{canvas}); os.wasi.e window_open, window_metrics, window_title, window_cursor, window_present, window_poll, window_capture call neper_host and answer as before on ENOSYS. (1) tests/wasm/browser/ui_counter (e.ui: title, count and button, text field with greeting, quit) in the real Browser pane on a page served with --isolated: first frame, Count: 1 after a click, Ada typed and Hello, Ada shown, Quit exits 0, the --threads build renders and counts (docs/wasm-ui/ui_counter-*.jpg); tests/wasm/window.mjs against a canvas shim plain and --threads, in run.sh and run.ps1. (2) Sweeps unchanged: ui_app/ui_window/ui_host fail with the same exit codes before and after, ui_gallery/ui_edit/ui_button/wasm_threads pass, 1,038 plain passes after a rerun of the failures a fork-starved full sweep lost (baseline 1,041, no verdict differs from a run with the old os.wasi.e). (3) A page that is not isolated rejects run() with one sentence. Design correction: an OffscreenCanvas in the Worker never shows a frame while the module runs, so frames are posted to the page. Left: C212.

### C205 — wasm32-wasi processes and pipes through neper_host (Node only)

Built as D5770, D5771. scripts/run-wasm-host.mjs: proc_spawn, proc_wait, proc_kill, proc_group_kill over node:child_process (one request buffer for argv, env and cwd; a .wasm argv[0] re-runs through the runner with the module's environment in NEPER_GUEST_ENV and its cwd in NEPER_PWD; stdio is the runner's own or a D5750 host pipe, pumped both ways; a group is a POSIX process group or taskkill /T); os.wasi.e: neper_os_spawn, neper_os_wait, spawn_with_options, wait_usage, kill, proc_group_spawn/terminate. run-wasm.mjs no longer creates process.stdout/stderr (a Worker and a node:process import set piped fds 1 and 2 nonblocking, so a child's 256 KB stderr write failed EAGAIN). Acceptance: (1) os_process and os_group pass plain and --threads on Windows Node 24 and WSL Node 22.23.1, registered in run.sh and run.ps1. (2) proc_output (new on wasm, --threads) passes on WSL 11 of 11 and stops at check 112 on Windows (a descendant orphaned before the group terminate is out of taskkill /T's reach); os_shell, os_exchange, ui_activation, ui_file_access, ui_lifecycle, ui_notification, ui_permissions, ui_print and ui_shell_ops fail on e.os.shell's wasi variant (D5623), proc_sys on missing CPU times in e.proc.sys. (3) Sweeps -j 3: plain 1,043 / 72 / 21 / 0 / 6 (before 1,041 / 73 / 22 / 6), --threads 1,075 / 40 / 21 / 0 / 6 (before 1,073 / 41 / 22 / 6 rerun the same day); the only per-fixture changes are os_process and os_group to pass and proc_output refused to fail.

### C209 — neper run for wasm32-wasi, and the runner moved into the toolchain

Design D5681. Needs nothing. Build: `dispatch` (main.e:14104) also sends `run ... wasm32 wasi ...` to `wasm_command`, which after writing the module runs it with `run_program` as node --no-warnings RUNNER OUT ARGS (node found by walking PATH, node.exe on Windows, as shell.linux.e:118 walks it; NEPER_NODE overrides; neither: E-CLI-9999 `running a wasm32-wasi module needs Node.js: node on PATH, or NEPER_NODE`); `--threads` and `--release` reach the build. scripts/run-wasm.mjs moves to lib/wasm/run-wasm.mjs and `run` finds it under the toolchain root (`own_directory(args[0])`/lib/wasm); every caller (wasm-sweep.sh, check-fixture.sh, wasm-compiler.sh, wasm-bench.sh, the D5651 blocks of run.sh and run.ps1) moves to the new path in the same commit and nothing stays at the old one. Acceptance: (1) from build/windows, and build/linux in WSL, `neper run tests/selfhost/fixtures/link/wasm_basics/src/main.e --target wasm32-wasi` prints the program's output and reports its status; (2) with node off PATH and no NEPER_NODE it prints the diagnostic; (3) wasm_release run with --release and the argument `bounds` reports 134; (4) the D5651 blocks pass with the moved runner, check_suite_parity.py passes, v2 == v3. D5650 saw `neper build --target wasm32-wasi` from a worktree stop at `the program has no main` (toolchain root build/windows): run from the toolchain as the suites do, and fix it here if it is the short form's own bug. Built as D5780: wasm_command runs the module for `run` (find_node, wasm_run), runner and host moved to lib/wasm, callers updated, tests registered in run.sh/run.ps1. Verified on Windows (wasm_basics, wasm_release bounds 134, no-node diagnostic, native run unchanged, v2==v3, sweep 1041/73/22/0, wasm-compiler 8/8). Not yet: the same on build/linux in WSL; the D5651 blocks run only piecewise (no full suite completes here). CLOSED: the whole wasm32-wasi block of run.sh (Git Bash on Windows with proc_output's Windows limit excepted, and WSL Ubuntu with the Linux compiler: all rows incl. proc_output and neper run) and of run.ps1 (pwsh 7 and Windows PowerShell 5.1) run standalone and pass; neper run wasm_basics prints and reports status from build/windows/short and build/linux/short; fixes: neper-host.js poll_oneoff, socket rows off neper-host.js, os_process runner path, parity of wasm_net/wasm_threads.

### C212 — e.ui in a browser: text from a virtual keyboard, the clipboard, newest frame only, the gallery

D5800, D5801, D5820-D5822: text from beforeinput and compositionend through a textarea beside the canvas, clipboard_text and set_clipboard_text over a copy in the ring, newest frame per requestAnimationFrame (Node test: three posted, one drawn; Browser pane burst of 200 posted, 1 drawn, last frame on the canvas), examples/ui running on a page, the mobile preset exercised with real click, type, Backspace and Return and synthetic IME events. A real device's keyboard moved to C213 (D5822).

### C200 — A launch's requirements depend on the worker count

Found in the wasm32-wasi work: gpu_tensor's image differed by three bytes between -j 1 and the default eight workers (neper.wasm, one worker, matched -j 1). Cause: a launcher gpu.launch[K] is lowered by the worker owning the instance and read K's facts (requirements & 511, ftz & 128) from its own checker's kernel_facts table, which only holds the kernels that worker checked; a warm build's Interface-declared kernel module (D1514) had no facts at all. DONE (D5700): every worker's facts merged into the program checker and back into every worker after the bodies (crew_kernel_facts), and a decoded Interface record restores its kernel's recorded facts. Regression: gpu_launch_facts (kernels in kern, launched from main; ftz f32 must flush, ftz f64 must be refused) fails with the old compiler at eight workers and warm at one; run.sh and run.ps1 now require one image hot/clean at -j 1 and at -j 2, -j 3 --perturb, -j 8 and the default for it and gpu_tensor (block passes alone on Windows for x64 windows and linux, fails with the old compiler). Stage 2 == stage 3 on both targets; every gpu_* link fixture and 42 others emit the old compiler's bytes at -j 1 apart from the compiler identity.

### C178 — AAPCS64: an extern fn that returns an HFA of three or four doubles (CGRect, NSRect)

Closed 2026-10-26 (D5854): a call into C that returns a 3- or 4-double HFA gets a c-hfa-slot slot and codegen_a64.select_call stores v0-v3 into it; macos_hfa_return (CoreGraphics CGRectOffset/Inset/Union) passes on aarch64 and x64 in the macOS corpus (1131/1131), hfa_return (3- and 4-double and 4-float HFAs from a C shared object built by cc) passes on x86-64 and under qemu-aarch64, extern_struct is byte-identical on both Linux architectures, and the macOS window code reads rects by a direct call with the KVC workaround deleted.

### L172 — OpenGL 1: registry generator for x.khronos.gl and x.khronos.egl

Closed 2026-10-27 (D5885): scripts/gen_khronos_gl.py generates lib/x/khronos/gl.e (675 entry points, the union of GL 4.6 core and GLES 3.2, each with a six-bit profile mask; 246 shared extern fn signatures) and egl.e (EGL 1.5, 51 entry points) from the registry-generated headers vendored in scripts/khronos, with the hand-written loader in gl.prelude.e and egl.prelude.e. Regeneration is byte-identical and --check runs in both suites. x_khronos_gl_load passes on x64 Windows and on Linux in WSL: every profile loads from a full resolver, a missing glDispatchCompute fails GL 4.3, GL 4.6 and GLES 3.1 by name while GL 3.3 and GLES 3.0 pass, a missing glClear fails every profile, GL_VERSION is parsed for desktop and ES, and EGL from a missing library is NoLoader.

### L173 — OpenGL 2: the loader, gl.load(profile, get_proc)

Closed 2026-10-27 (D5885, D5886): gl.load(profile, resolve, context) fills the table and fails Unsupported, naming the first required entry through gl.missing(); gl.version() parses desktop and ES GL_VERSION strings; gl.has_extension walks GL_NUM_EXTENSIONS; gl.present and egl.present ask about an optional entry by its generated *_ENTRY slot. The resolvers are egl.proc_address (eglGetProcAddress, then the library's export) and, on Windows, wglGetProcAddress with opengl32's own exports for the GL 1.1 entries. egl.load is NoLoader without a library. Checked without a driver by x_khronos_gl_load, and against real drivers by x_khronos_gl_headless: Intel Iris Xe through WGL, ANGLE on D3D11, and Mesa llvmpipe.

### L177 — OpenGL 6: samples and headless fixtures

Closed 2026-10-27 (D5886): examples/gl_triangle.e draws a colour-blended triangle with GL 3.3 core or, with --es, GLES 3.0 shaders, and screenshots were taken on Windows through WGL and ANGLE. x_khronos_gl_headless reads back a triangle with glReadPixels: interior and exterior pixels that every conforming driver agrees on, plus the whole 32x32 image against an FNV-1a golden on llvmpipe. It also checks a compute shader's SSBO. It passes on Mesa 25.2.8 llvmpipe in WSL, on Intel Iris Xe and on ANGLE D3D11. The fixtures and the example (3 frames) are registered in run.ps1 and run.sh and pass check_suite_parity. The full suites were not run here; each was run on its own on both hosts.

### C214 — OpenGL 9: the glsl GPU target in the compiler

Closed 2026-10-27 (D5888): the self-hosted compiler takes --gpu LIST (spv, ptx, glsl, none; any other item is no build), and Graph.gpu_glsl carries it into lowering. With glsl, each kernel's embedded module string gets ';' and its GLSL in hex after the SPIR-V; the launcher cuts there, and a Vulkan launch from such a build still passes (gpu_vulkan_loop, gpu_vulkan_float, gpu_vulkan_sync). The option is bit 55 of the compiler identity (OPTIONS_MASK now 55 bits). There is no target.Arch.Glsl and no K$glsl: GLSL is never a target of its own. Spec §10 gained the GL row and §13 gained --gpu glsl. Without the flag the output is unchanged: the saxpy SPIR-V golden is byte-equal and nothing follows the module. The self-hosted compiler rebuilds itself byte for byte.

### T045 — OpenGL verify 1 (verify-only): binding fixtures on Windows and Linux

Closed 2026-10-27: x_khronos_gl_load, x_khronos_gl_headless, x_khronos_gl_window and examples/gl_triangle pass on Windows (Intel Iris Xe through WGL; GLES through ANGLE D3D11 from PATH) and on Linux as cross-compiled ELF in WSL on Mesa 25.2.8 (llvmpipe through surfaceless EGL, and a window through WSLg's X server). The headless image matches llvmpipe's golden hash. Mesa EGL/GLES were already installed in WSL, and ANGLE was already on PATH (D:/tools/qemu).

### L179 — OpenGL 8: WebGL2 presentation in the browser host

Closed 2026-10-27 (D5895): lib/wasm/window.js presents each frame through webgl2(canvas), with one RGBA8 texture refilled by texSubImage2D and one texelFetch triangle, unfiltered, unblended and not premultiplied. It falls back to the 2D canvas without WebGL2 (and under Node's shim, which answers every getContext). tests/wasm/browser/webgl2_present.html reads back random frames at 64x48, 97x61 and 480x320 byte for byte ('webgl2 present ok' in Chromium). ui_counter.html runs and repaints through it, and tests/wasm/window.mjs passes. The page is run by hand: the suites have no headless browser.

### L180 — OpenGL 13: the e.gpu.gl runtime, Backend.Gl

Closed 2026-10-27 (D5889, D5897, D5898): Backend.Gl over e.gpu's shared heap-driver table, with x.khronos.compute.install() as the driver. Each device is a headless GL 4.3 core (or GLES 3.2) context on a thread of its own, with every call marshalled to it. The heap is the smaller of 256 MiB and GL_MAX_SHADER_STORAGE_BLOCK_SIZE; it and the argument block are persistently mapped SSBOs. A launch runs glDispatchCompute, then glMemoryBarrier and a fence, waited on lazily (D5875). Metal's fault block is reused. Linked programs are cached as program binaries across runs. gpu_gl, gpu_gl_exact, gpu_gl_threads and gpu_gl_cache pass on Intel Iris Xe and Mesa llvmpipe and are in both suites.

### L174 — OpenGL 3: EGL contexts on Linux, windowed and headless

Closed 2026-10-27 (D5886, D5894, D5899): x.khronos.context.linux over x.khronos.eglcontext. Headless GL 3.3/4.3 and GLES 3.0/3.1 run on Mesa's surfaceless EGL, with the pbuffer fallback exercised on the Android emulator, which has no surfaceless platform. They draw, read back against llvmpipe's golden hash and compute. GL 3.3, GL 4.3 and GLES 3.1 run on os windows through a second libX11 connection to the window id (x_khronos_gl_window), and swap_interval is set. A resize storm of twelve outside resizes leaves no stale frame (x_khronos_gl_resize): a surface whose window changed size is swapped once before its next frame, because Mesa's buffers otherwise keep the old size. All of these are in both suites and pass under WSLg.

### C217 — OpenGL 12: exact float in GLSL

Closed 2026-10-27 (D5888, D5889, D5891, D5901): every f32 variable is precise, so no multiply-add is fused. f32 division, square root and math.fma are integer sequences rounded to nearest-even (f32_div, f32_sqrt, f32_fma over f32_round, written into the shader), honouring the kernel's ftz, and every NaN result is section 11's canonical 0x7FC00000. x.khronos.compute probes denormals at open and reports DenormPreserve (llvmpipe) or Ftz (Intel). gpu_gl_exact (65,536 quotients, square roots and fused multiply-adds, special values and near-cancelling addends included) and gpu_gl's saxpy are word-equal to the CPU on Intel and llvmpipe; gpu_float_modes (plain and --release) and gpu_vulkan_float now also run every .Gl device, and check-fixture.sh builds with --gpu glsl. gpu_ftz_ops stays CPU-only, as it is for Vulkan; its divide and square root under ftz are gpu_gl_exact's. Design docs/opengl-plan.md, D5882.

### C215 — OpenGL 10: src/glsl.e, the GLSL 4.30 emitter

Closed 2026-10-27. Pinned 2026-10-27: tests/conformance/glsl/saxpy.glsl and loops.glsl (gpu_vulkan_loop's kernel) are checked in both suites through scripts/dump_glsl.py, and the Linux and Windows builds emit the same text. Helper calls added 2026-10-27 (D5892): every helper the kernels reach is a GLSL function hN in each kernel's shader, with scalars by value, aggregates as their words and shared pointers as offsets; gpu_gl's helped kernel is word-equal on Intel and llvmpipe (GL and ES). Done 2026-10-27 (D5888): src/glsl.e, ported from msl.e. Kernels become one GLSL 4.30 shader each over uint word arrays (heap, frame, shared) with byte addressing and bit-casts, using an if-chain dispatch, Metal's launch ABI and its fault block, and emulated signed division. Integer divisions get an unprovable zero added to both operands, the workaround for two Intel miscompiles. The output compiles on Intel and Mesa, and gpu_gl's kernels (saxpy, narrow stores, signed div/rem, 2-D ids, a bounds fault) are word-equal to the CPU. Subgroups closed 2026-10-27 (D5902): sid, subgroup_width and the vote, ballot, broadcast, shuffle and reduction collectives through GL_KHR_shader_subgroup, with MSL's lowest-block round so diverged lanes meet at the join; the width is the one the driver cut the workgroup into (Intel reports 32 and runs 16). gpu_gl_subgroup checks every collective lane by lane on Intel at width 16, a partial subgroup included; the ballot needs Int64, which Intel's GL lacks, and llvmpipe offers no GL subgroups, so the ballot is written but ran on no device here. 64-bit atomics stay Unsupported. Design docs/opengl-plan.md, D5878. Needs C214. Acceptance: ported from msl.e's heap-offset state machine; every access goes through uint heap[] with bit-casts; helpers are inlined; the launch ABI is Metal's; saxpy, loops and control flow are pinned in tests/conformance/glsl.

### L181 — OpenGL 14: GPU capabilities from GL extensions

Closed 2026-10-27 (D5889, D5893, D5902, D5903): Int8 and Int16; DenormPreserve or Ftz from the probe at open; Int64 where the desktop driver lists GL_ARB_gpu_shader_int64 (Mesa yes, Intel's GL no), with the emitter writing u64/i64 for it. A kernel needing anything else is gpu.Unsupported at launch through e.gpu's existing requirement check, and gpu_gl's wide kernel is word-equal on llvmpipe. Subgroup (D5902) where GL_KHR_shader_subgroup offers compute shaders basic, vote, ballot, shuffle and arithmetic (Intel yes; llvmpipe advertises none). Float64 (D5903) on desktop GL as GLSL double with canonical NaNs, word-equal to the CPU on llvmpipe over 65,536 pairs of + - * / sqrt and narrowing (gpu_gl_f64; the driver's double arithmetic is trusted where that fixture passes, and Intel cannot run an f64 kernel since it flushes and an ftz kernel holds no f64). A workgroup axis past MAX_COMPUTE_WORK_GROUP_SIZE or shared memory past MAX_COMPUTE_SHARED_MEMORY_SIZE is TooLarge at launch, not a driver compile failure (gpu_gl_limits: Intel refuses 1x1x1024, llvmpipe runs it). Float16 waits for the CPU backend's f16 (C216). Design docs/opengl-plan.md, D5882. Needs L180. Acceptance: Float64 from ARB_gpu_shader_fp64, Int64 from ARB_gpu_shader_int64, subgroups from KHR_shader_subgroup, 32-bit atomics only, and the shared-memory and workgroup limits; a missing capability is gpu.Unsupported at launch, naming the kernel and the capability.

### C218 — OpenGL 15: the GLES 3.1 profile

Closed 2026-10-27 (D5890, D5904): x.khronos.compute.install_es() opens OpenGL ES 3.2 devices, with the shader header rewritten to #version 320 es and highp at compile time, and glBufferStorageEXT where only the extension exists. gpu_gl's ES pass is word-equal to the CPU on Mesa llvmpipe. ES 3.1 devices are taken where GL_EXT_gpu_shader5 or GL_OES_gpu_shader5 gives them precise, with a #version 310 es header enabling it (D5904); without either a 3.1 device is refused, since an f32 multiply-add could be fused (ANGLE on D3D11 still is). The Linux suite runs gpu_gl a second time with MESA_GLES_VERSION_OVERRIDE=3.1, and the ES pass is word-equal under GL_OES_gpu_shader5. The heap is the driver's MAX_SHADER_STORAGE_BLOCK_SIZE up to 256 MiB, so at least ES's 128 MiB floor. ES offers no Int64 or Float64. Design docs/opengl-plan.md, D5879, D5884. Needs C217 and L181. Acceptance: #version 310 es with highp everywhere; no doubles; the heap sized up from the 128 MiB ES floor; the same fixtures pass on Mesa's GLES through EGL.

### L178 — OpenGL 7: e.ui presents through GL

Closed 2026-10-27 (D5887, D5905): e.ui.window.Presenter and set_presenter, with x.khronos.present.attach as the GL presenter (a hook, because e.* cannot import x.*). Frames go through one texture and a texelFetch triangle with vsync, and any error returns the window to window_present for the session. x_khronos_gl_present compares every back-buffer pixel bit for bit at 64x48, 96x72 and 128x96 through GL 3.3 and GLES 3.0, on Intel WGL, ANGLE D3D11 and Mesa llvmpipe, and is in both suites. examples/ui/main.e --gl and --gles run the controls gallery through it (screenshots taken; sampled pixels equal the software path's), and ui_app and ui_window still pass on both hosts. Damage uploads (D5905): e.gfx.scene.changed_box answers the pixels each render changed (its damage boxes, a scroll strip, or the whole frame), e.ui.app reports it to the window (window.report_changed), and the window hands it to the presenter, which uploads only that box through two alternating pixel-unpack buffers (UNPACK_ROW_LENGTH and SKIP_PIXELS over the box's rows); a new size uploads whole, an empty box nothing, and a window nobody reports to still uploads whole. x_khronos_gl_present now changes a box of each frame at all three scales and checks that exactly that box's bytes went up and that the back buffer equals the whole new frame, on Intel WGL, ANGLE and llvmpipe (GL 3.3 and GLES 3.0); gfx_scene_damage checks that the box holds every changed pixel and is empty for an unchanged scene; the controls gallery runs through it (--gl) without falling back. GL is opted into per window with x.khronos.present.attach on app.window_of, since e.* cannot import x.*. Design docs/opengl-plan.md, D5877. Needs L173 and a context item (L174 or L175). Acceptance: opt-in present: .Gl in e.ui.app; only the renderer's damage boxes are uploaded, through two PBOs; one full-screen triangle with nearest sampling; vsync swap; any GL error falls back to window_present for the rest of the session; the fixture's readback equals the CPU canvas bit for bit at scales 1.0, 1.5 and 2.0.

### T047 — OpenGL verify 3 (verify-only): gpu fixtures on Backend.Gl

Closed 2026-10-27 (D5906): scripts/run-gl-fixtures.py runs every gpu_* fixture that launches on Vulkan devices (22; the other gpu_* fixtures run the CPU backend only) on .Gl instead, built with --gpu glsl, each checking itself against the CPU backend. All 22 pass on Intel Iris Xe (Windows GL 4.6), on llvmpipe through GL 4.5, and on llvmpipe through GLES 3.2. The run found and fixed five GLSL gaps: a barrier reached in different rounds of the dispatch loop (workgroup rounds), acquire/release atomics and memory barriers (fences), a shared slice or pointer handed to a helper, a fault inside a helper that returns a value, and math.fma[f64] (emulated exactly). A key on a .Gl device now names no device rather than being Unsupported. gpu_subgroup_identity and gpu_subgroup_reduce skip GL on every host here: they need Subgroup with Int64, which no GL device here has together. gpu_gl_subgroup covers subgroups on Intel. The gpu_gl* fixtures and those already opening .Gl run in the suites.

### T046 — OpenGL verify 2 (verify-only): ui fixtures presented through GL

Closed 2026-10-27 (D5907): x.khronos.present.install() (install_es() for GLES) makes every e.ui.window opened afterwards present through GL, an e.ui.app's included. scripts/run-gl-fixtures.py --ui runs every ui_* fixture that opens a host window (ui_algorithms, ui_app, ui_drag_drop, ui_host, ui_taskbar, ui_window; the other ui_* fixtures draw offscreen and present nothing) with it: all six pass on Windows through Intel GL 3.3 and ANGLE GLES 3.0, and on Linux (WSLg) through llvmpipe GL 3.3 and GLES 3.0. A scratch ui_app confirmed window.presenting is true after its frames, so the GL path ran rather than the software fallback.

### C220 — OpenGL 17: the Android target, app form (needs @export)

Closed 2026-10-27 (D5908, D5909): `@export("Name")` on a `@cc(c)` function and `emit-shared-library` (ET_DYN for linux and android, x64 and aarch64, exports in .dynsym, the section headers Bionic requires). examples/android/native_activity exports ANativeActivity_onCreate; packed by scripts/build-apk.ps1, it installs and launches cold on the x86_64 Android 15 emulator as android.app.NativeActivity, and logcat shows its neper code running. shared_library loads through dlopen on Linux x64 (suite) and arm64 (qemu) and on Android x64 and arm64.

### T044 — OpenGL 19: APK packaging and signing

Closed 2026-10-27 (D5909): scripts/build-apk.ps1 builds the program as x86_64 and arm64-v8a libapp.so, writes a NativeActivity manifest, links it with aapt2 against android-35, stores the libraries uncompressed, page-aligns with zipalign -P 16 and signs with apksigner (WSL OpenJDK 17) and the debug keystore. The example APK installs (adb install) and launches on the emulator.

### L182 — OpenGL 18: os.android windows and input

Closed 2026-10-27 (D5910): os.linux.e takes a WindowHost; x.android.activity is the NativeActivity host (ANativeWindow window, AInputQueue on the app thread's ALooper, a pthread app thread, density scale, Back as Close, software frames through ANativeWindow_lock). x.khronos.context makes the EGL surface on the native window and makes it again on the window that returns after a pause. examples/android/counter (ui_counter's count and buttons; the wasm ui_counter sources are another session's work in flight) runs on the emulator through GLES: taps count, Home and back keep state and draw on the new surface, Back quits.

### T049 — OpenGL verify 5 (verify-only): Android emulator

Closed 2026-10-27 (verify-only): on the x86_64 Android 15 emulator, examples/android/counter (ui_counter's UI, D5910) runs as an APK through GLES: taps count, Home and back keep state on a new EGL surface, Back quits. The gpu fixtures run on Android (scripts/run-android.ps1, x64 and aarch64): gpu_gl and gpu_gl_exact pass with the CPU side checked and report no OpenGL compute device, since the emulator offers GLES 3.0 only; gpu_cpu passes on both. GPU compute on GLES 3.1+ needs a real phone (C219, folding into C213). The emulator dropped offline twice under the host's memory pressure during the run.

### L175 — OpenGL 4: WGL contexts on Windows, and GLES through ANGLE

Closed 2026-10-27. GL 4.6 added 2026-10-27 (D5894): a 4.6 core context draws and computes on Intel once gl.load also asks for ARB, KHR and EXT spellings, and GL 4.3 and GLES 3.0 (ANGLE) contexts on windows pass x_khronos_gl_window. Per-monitor DPI closed 2026-10-27 (D5911): the window procedure takes WM_DPICHANGED's suggested rectangle (the process is per-monitor aware v2 and reads its scale live); x_khronos_gl_dpi sends the message at 144 dpi and checks the client size, the reported metrics and a GL frame at the new size, in both suites. A real crossing between monitors of different scales is not exercised on this single-display machine. Done 2026-10-27 (D5886): x.khronos.context.windows. The WGL core context comes from a legacy context on the same device context, so no dummy window is needed. Checked on Intel Iris Xe: GL 3.3 and GL 4.3 core (compute included) headless on a hidden os window, and a GL 3.3 context on a visible window cleared, scissored, read back and swapped. wglSwapIntervalEXT is called. GLES 3.0 and 3.1 (compute included) run through ANGLE's D3D11 libEGL.dll from PATH, and examples/gl_triangle --es draws through it (screenshots taken). Remaining: a 4.6 core request, and per-monitor DPI (the viewport follows the window's Resize event, not its scale). Design docs/opengl-plan.md, D5880. Needs L173; can run at the same time as L174. Acceptance: pixel format bootstrapped through a dummy window, then wglCreateContextAttribsARB for core 3.3, 4.3 and 4.6; WGL_EXT_swap_control; per-monitor DPI; the same GLES 3.0 sample runs through ANGLE's libEGL.dll (installing the ANGLE DLLs needs the user's go-ahead).

### C216 — OpenGL 11: narrow and half types in GLSL

Closed 2026-10-27 (D5888, D5913, D5914): u8, i8, u16 and i16 load through bitfieldExtract (sign-extended for the signed ones), store into heap and tg through atomicAnd and atomicOr on the word and into the frame through bitfieldInsert, and are masked or sign-extended back after every operation. gpu_gl's u8 and i16 stores into neighbouring bytes of the same words are word-exact on Intel and llvmpipe. f16 and bf16 (D5914), once the CPU backend had them (D5913): a narrow value is sixteen bits in a uint, widened to f32, operated on and rounded once to nearest-even in integer code (packHalf2x16 is not used, so no driver rounding is in the answer); + - * / sqrt fma negation, the six comparisons and every conversion (f32, f64, 32-bit integers, f16 <-> bf16). gpu_gl_narrow runs 13 streams of 4096 words per type on the CPU and GL, word-equal on Intel Iris Xe (ftz kernels) and llvmpipe (plain kernels, f64 conversions too). It found that the CPU's math.fma never flushes under ftz, so f32_fma no longer does (D5914). Not written: 64-bit integer to narrow, a narrow subgroup add/min/max. Design docs/opengl-plan.md, D5882. Needs C215 (same file, so one at a time). Acceptance: u8, i8, u16, i16, f16 and bf16 loads via bitfieldExtract; stores via atomicAnd/atomicOr on the containing word; packHalf2x16 for f16; a fixture where neighbouring invocations race to store narrow values is word-exact.

### C221 — The root arena grows on demand: a 32 GiB default ceiling

Closed 2026-10-28 (D5912): nir.root_arena_bytes gives the default every hosted linker patches (PE, ELF x64, ELF arm64, Mach-O): 32 GiB on Windows, Linux and macOS (64 GiB was refused by valgrind, which runs fixtures up to 56 GiB); --arena overrides; wasm32 and NeperOS unchanged. Reserved and committed as touched (D340), so the ceiling costs nothing until used. Android gets 4 GiB once its target (C219) lands. link/arena_size checks the default capacity, failing before and passing after on Windows and Linux x64; images differ from the old only in the arena word; a 64 GiB compiler self-hosts at 2.9 GB peak with stage 2 == stage 3. Acceptance: default ceiling 32 GiB (user lowered it from 64 for valgrind) on desktop x64 and arm64, 4 GiB on Android, wasm unchanged, regression fixture.

### C222 — A program takes the memory it needs: a refused reservation is halved, and the default ceiling is 1 TiB

Closed 2026-10-30 (D5930): all five hosted startups halve a size the host refuses, down to a mebibyte, and report what they got; workers do the same (graph.reserve_arena); the default is 1 TiB. link/arena_retry, built with --arena 1048576g, failed with exit 111 before and passes on Windows, Linux x64 and Linux arm64 under qemu; on Linux it also passes under ulimit -v, and valgrind passes at the default; the macOS corpus passes 1,133 of 1,133 on both architectures, x64 under Rosetta 2. No cost measured: sc1m peaks at 606 MB, 946 MB of commit; a small program starts in the same 5.4-5.7 ms; stage 2 == stage 3. Acceptance: as much as needed on Windows, Linux and macOS with no flag, regression fixture, both suites and the macOS corpus.

### C223 — Memory goes back, one object can be freed, and running out is an answer

Closed 2026-10-30 (D5931-D5935). mem.reset hands back all but 128 MiB of a drop of 512 MiB or more on every hosted runtime: a 2 GiB spike leaves 132 MiB resident, from 2,051. e.mem.pages: ensure answers mem.Exhausted before the page fault, discard, reserve. e.mem.heap frees one object at a time, and the checker refuses a block used after free, freed twice or never freed. On Windows a refused commit is retried for two seconds and then reported as out of memory, status 137. The compiler touches &slice[i] given to an import. Fixtures link/mem_trim, mem_pages, mem_heap, import_touch, mem_commit_refused and check/heap_*. Acceptance: all four weaknesses addressed on Windows, Linux and macOS, both suites and the macOS corpus.

### L226 — Browser: persistent visit history, no UI

Landed: e.web.shell keeps one visit per address with a time and count (a revisit bumps the count, takes the new title and moves to the newest end), caps at 5000, skips about: and data: pages, writes them to the profile as V lines with time and count (older V lines still load), and answers search_visits (case-insensitive over address and title, newest first), delete_visit and clear_visits. web_shell cases 43 to 52 pin each of those and the profile round trip. Vaper kept {url, title, visitedAt, visitCount} per profile, deduped by URL (a revisit bumps the count and moves the entry to the front), capped at 5000, recorded on navigation commit with about: pages skipped and the title filled in when it arrives. Neper's shell has a visit log in the profile file; the gap is a store the browser writes on every committed navigation and reads back across restarts. Acceptance: e.web.shell records, dedupes, caps and persists visits to the profile; a query API (substring over url and title, most recent first, delete one, clear all); a fixture that restarts from the profile file and sees the same entries. No panel or widget.

### L227 — Browser: certificate validation result and error page

Landed: e.net.fetch reports a certificate failure from the TLS handshake (HTTP/1.1 and HTTP/2 paths) as CertificateError instead of the generic network error, the shell shows a not-private message on the error page, and net_fetch_cert runs a loopback TLS server to pin an untrusted issuer and a wrong host. e.net.tls separates CertificateExpired, CertificateName and CertificateUntrusted from the generic InvalidCertificate, fetch passes them on, and the shell error text names each; net_fetch_cert pins no roots and a wrong host. x509.verify now reports a self-signed leaf as SelfSigned (fetch.CertificateSelfSigned, with its own error text) and net_fetch_cert pins expired, self-signed, unknown CA and a valid chain that raises no certificate error. The valid chain loads end to end (status 200 and body asserted). The shell loads a generated error document naming the address and reason (shell.error_page) instead of the page body. Vaper classified a TLS handshake failure (expired, self-signed, host mismatch, untrusted CA) and showed a 'Your connection is not private' page instead of the generic error. Acceptance: the fetch layer reports a distinct certificate error kind with the reason, e.web.page turns it into an about: error document naming the host and reason and never loads the page body, a valid chain loads normally, and a fixture covers expired, self-signed, wrong host and untrusted root against local test servers. A proceed-anyway bypass is out of scope until the TLS hardening work.

### C268 — the suite builds a release compiler, and every memory figure names the build it measured

Landed. The compiler the suite runs was a debug build; a debug build fills every allocation with 0xCD (D306, section 11) and an arena pool charges what it touches, so every pool the loader sizes from the program is committed whether it holds anything or not. Measured compiling src/main.e: debug-built 6'608-8'883 MB, release-built 365 MB on Windows and 371 MB on Linux (379'672 kB, 1.16 s), for byte-identical output -- basic and x_duckdb hash the same under either compiler, module surfaces pass 498 exact against the release one, and graph-file answers the same. Seeded builds in both runners now pass --release, and the replay leaves ~7.8 GB free where the debug build left 234 MB, with the built compiler 10.74 MB instead of 12.42 MB. The C bootstrap's build has no --release and both runners say so at the flag, so the NEPER_SEED-less path is unchanged. The stale figures that cost this session hours -- a 388m peak against a 7-9 GB measurement, which were a release and a debug build -- now name their build in run.sh's header and arena note and in run.ps1's compiler comment. check_suite_parity.py fails when either runner's self-hosted compiler build loses --release, verified both ways: removing the flag reports 'run.ps1 line 44 builds the self-hosted compiler without --release' and exits 1, restoring it passes. Acceptance: both runners build the compiler with --release on the seeded path and say so where the build happens; the bootstrap path states that it cannot and why; every remaining memory figure names the build it measured; and the parity check fails if the flag is lost.

### C270 — a Gopher info item parses again: port 0 is legal when no host is named

Found when the suite could finally reach net_retro: 'a net_retro check failed: exit 31'. Exit 31 is a string assertion, not a socket: retro.gopher_item("iJust text\t\t\t0") must return ok with kind 'i', empty selector, empty host and port 0. Bisected with both the fixture and lib/e/net/retro.e pinned to the same revision: 7d5933619 passes (exit 0), 6a84de318 ('fix(retro): validate Gopher menu ports') fails (exit 31), and every later revision still fails. That commit added `if port == 0usize { ret (item, BadItem) }` to reject a menu item that names no port, which also rejects every info item -- a menu spells one as `i<text>\t\t\t0`, with no host to connect to and 0 in the port field. The same commit extended the fixture with invalid-port cases (70garbage, an empty field, 65536) and a 65535 boundary case, but left line 31 expecting a port-0 info item to parse, so it contradicted itself and the fixture has failed since it landed, unseen because the suite never reached this line. Fixed by narrowing the rule to the case it was meant for: `if port == 0usize && item.host.len != 0usize { ret (item, BadItem) }` -- an item with no host may carry port 0, an item that names a host still must name a port. All four added cases still hold (the fixture asserts them and now exits 0), and lint_bootstrap reports 0 findings.

### C271 — e.net.ssh clears the password on the path that never sends it

Found by the net_ssh unit case, which needs no server and had been failing with exit 104. Bisected the two halves of its assertion by splitting them: 106 (password not cleared) fired first, masking 107. The cause is a single insertion: 8d0bc690a ('Fix #176 partly: authenticate only after encrypted NEWKEYS') added `if !s.encrypted_out { fail(s, FAIL_PROTOCOL); ret }` ABOVE the existing `defer` that zeroes `s.password`, so every session that had not reached encrypted NEWKEYS returned before the defer was registered and kept the plaintext password in memory. The same insertion is why a bare session builds no packet, so `outbuf` can never contain it: the unit assertion's second clause predates the guard and became unsatisfiable. Fixed in two parts. lib/e/net/ssh.e: the defer is registered first, so every path out of send_userauth clears the password whether or not a packet was sent -- which is what hardening wants, since the guard's path is exactly the one that used to leak. The fixture: the unit case now asserts the clearing alone, with a comment naming 8d0bc690a, because the wire clause needs a session that is actually encrypted and the password, key and badpass modes prove that against a real server. Verified: the unit case exits 0. net_ssh still fails later, at host-key verification (status FAILED, failure FAIL_HOST_KEY), which is a separate question: it needs no assertion of mine to explain, and the guard commit and d34f944ab (the host-key hold) are both recent changes to that path.

### C272 — strict KEX: the sequence numbers restart at NEWKEYS, and only chacha noticed they did not

Landed. The client offers kex-strict-c-v00@openssh.com, so the peer negotiates strict KEX, which restarts the packet sequence numbers at zero when NEWKEYS is exchanged (asyncssh: if pkttype == MSG_NEWKEYS and self._strict_kex: self._send_seq = 0). This client never reset them, so after three key-exchange packets it decrypted the peer first encrypted frame as sequence 3 while the peer had encrypted it as sequence 0. Proven by walking the captured stream and checking Poly1305 tags, which cannot match by chance: exactly one frame verified, at the byte the client was looking at, with sequence 0. AES-GCM hid it because its nonce is a separate invocation counter rather than the packet sequence number. Fixed by zeroing seq_out at both places NEWKEYS is sent (after the packet goes out under the old counter) and seq_in after the increment for a received NEWKEYS, in take_packet rather than in the key-install handlers because the increment would otherwise overwrite it. Applies to rekey the same way. Verified: all twelve net_ssh cases pass against a real asyncssh server -- unit, password, early, key, badpass, badhost, gcm256, gcm128, rekey, sftp with a 200-byte upload, forward and forward_refused -- where every chacha case failed before.

### C273 — pole_placement solves a one-state plant: the polynomial scratch was two entries short

Landed. control_loop failed with exit 8, one of six pole_placement assertions; giving each a distinct code showed the 1x1 case, and splitting its call from its gain showed the call itself returning an error (87, not 88). pole_placement reserved scratch[5*nn+3*n .. 6*nn+4*n] for characteristic(), which needs 2*(n+1) entries: for n=1 that tail is nn+n=2 against 4 needed, so characteristic answered TooSmall and a one-state system was refused even though the controllability matrix [1.0] is invertible and the gain is 0.5. The same declared budget, 5*nn+5*n+2, was also below the nn+n tail for n >= 3 and only worked because the caller's scratch happened to be larger. Fixed with a computed requirement: poly_needed is max(nn+n, 2*(n+1)) and the guard is poly_base + poly_needed, so the polynomial is sized by what it actually slices. Verified: control_loop exits 0 and prints control ok, and the 2-pole, 3-pole and uncontrollable cases it already covered still pass. Pre-existing: the untouched Nov 6 compiler fails the same way.

### C274 — e.ml.linear.pls answers Invalid for an impossible component count, whatever the buffer

Landed. ml_chemometric failed with exit 22: pls with n=6, d=3 and components=4 was expected to answer Invalid -- more components than columns -- and answered TooSmall instead, because the storage guard ran first. That guard sizes scratch for c components (80 entries for c=4), while the fixture's scratch is 64, so an invalid request was reported as a buffer problem and the same bad request had two answers depending on the caller's scratch. The request is now validated before the storage for it is sized, so Invalid means invalid. Verified: ml_chemometric exits 0, including the neighbouring cases it already covered -- components=0 Invalid, a 10-entry scratch TooSmall, a flat signal, and the working two-component fit whose coefficients it pins. Pre-existing: the untouched Nov 6 compiler fails the same way.

### C275 — the DOM selector APIs reject pseudo-elements, as the specification says

Landed. fmt_dom failed with exit 53: query_selector, query_selector_all, matches and closest were expected to answer dom.SyntaxError for `p::before` and accepted it. The parser supports pseudo-elements on purpose -- a style rule keeps `p::before` -- and compile_selectors, which all four APIs share, only asked selector_known, which is true of a pseudo-element. The DOM selector APIs reject it instead, because a pseudo-element names something that is not an element of the tree. compile_selectors now checks has_pseudo alongside selector_known, so one guard covers all four. Verified: fmt_dom exits 0, including the neighbouring cases it already covers -- the class-name errors (empty is SyntaxError, a space is InvalidCharacter), the tree-shape assertions, and every selector the fixture expects to find. Pre-existing: the untouched Nov 6 compiler fails the same way.

### C276 — robot_plan pins the planner it now has, after the ellipse and PRM changes

Landed. robot_plan failed with exit 3, which the fixture's own map_checks maps to the informed RRT* signature; splitting each check showed informed and then PRM, and after those a kinodynamic signature on the second map. The cause is c1cba18de ('Fix #129 part: goal-reaching ellipse bound, undirected PRM edges, workspace box for kinodynamic roll-outs'), a deliberate change to the planner that alters the exact paths it samples, while the fixture pins those paths as u64 signatures. Nobody regenerated the pins, so the fixture has failed since that commit. Regenerated from the planner itself, by printing the computed signature beside the pinned one and confirming each moved value is the one the code now produces: informed on both maps, PRM on both maps, and the kinodynamic path on the second. The values that did not move were left alone, which is the check that the regeneration was targeted rather than wholesale. Verified: robot_plan exits 0 and prints robot plan ok, with the intermediate RRT, RRT* and connect signatures still matching their original pins.

### C277 — algo_gaps_a calls bdd.count the way it is declared now, with its memo

Landed. algo_gaps_a would not emit: 'bdd.count takes 3 arguments and this call gives 2'. The memoising commit 4fa5cbcb2 ('Fix #277, #226: memoise BDD counts, refuse cycles and bound SAT pseudo-boolean sums') added the memo buffer and the error to bdd.count and updated tests/selfhost/fixtures/link/algo_bdd, but missed the second caller in tests/selfhost/fixtures/link/algo_gaps_a, which is why the suite stopped at emission rather than at a check. The fixture now passes a 2048-entry memo, names it bdd_counts because the file already binds counts later, and checks the returned error as algo_bdd does. Verified: algo_gaps_a emits and exits 0 printing algo gaps a ok. No other live caller uses the two-argument form -- the remaining hits are in a stale build tree.

### C278 — fmt_gaps_a keeps the last chunk its quoted-printable reader hands back with the end

Landed. fmt_gaps_a failed with exit 27 on the quoted-printable round trip, though encode matched its pinned text. Splitting the assertion showed a mismatch, then a length mismatch, then that qp_total was zero; a probe on the first read showed it had returned all 113 decoded bytes, so the bytes were being thrown away rather than miscoded. e.fmt.quoted_printable's read returns the final chunk together with io.End -- refill records the end from the source read and the pending error is reported as soon as the buffer empties -- and this loop tested for End before adding count, so the one chunk that carried the whole message was dropped. fmt_gzip's drain shows the house shape: add count, then look at the error. The loop now does the same. Verified: fmt_gaps_a exits 0 printing fmt gaps a ok, with the encode comparison against quopri's output and the rest of the fixture unchanged.
