Living doc. Single source of truth for "what is currently built." Auto-refreshed as feature work lands (see CLAUDE.md § Post-Change Review Protocol Step 8). Intent lives in CambiOS.md and the design docs; this file is for current state.
"Is X done yet?" — read here. "Should X be done a certain way?" — read the linked design doc.
- Tri-arch first-class: clean release build on
x86_64,aarch64,riscv64gc; all three boot in QEMU to ancambios>shell prompt.make check-allis the permanent regression gate. - 561 host unit tests passing on
x86_64-apple-darwin. Runmake statsfor current counts — numbers live in code, not prose. - Security model live end-to-end: cryptographic identity, signed-ELF verification, capability-gated IPC, content-addressed ObjectStore, audit ring, kernel identity gate, userspace
recv_verified. - GUI stack live on x86_64 + aarch64: scanout-virtio-gpu drives QEMU virtio-gpu-pci; compositor composites; virtio-input forwards HID keyboard/pointer events into the focused window; first-party app
pong(continuous-motion 1-player vs AI) runs as the default GUI boot module on x86_64, andwormrenders on aarch64 viamake run-aarch64-guinow that the kernel has an ECAM-based PCI enumerator.tree(Minesweeper) stays buildable for regression. - Persistent storage live: virtio-blk + disk-backed ObjectStore +
arcobjshell CLI; objects survive reboot. - Bare metal: USB boot tooling complete, untested on hardware.
- Formal verification: Kani proofs live on BuddyAllocator + ELF parser + FrameAllocator + CapabilityManager + UserSlice + DTB parser (1 + 7 + 10 + 12 + 12 + 5 = 47 harnesses across 6 proof crates; proof authoring fixed 6 overflow sites in
src/loader/elf.rs, 2 insrc/memory/frame_allocator.rs, and 2 insrc/boot/riscv.rs). verification/CLAIMS.md tracks the gap between proven and aspirational claims.
Chronological, newest first. ~3 week window — older items rotate out; git log has the full history.
- 2026-05-25 — USB host stack Stream B substage B-vii: CCID class driver split into
user/ccid/boot module on endpoint 33, with a newcambios-ccid-protowire-format crate at the workspace root following thecambios-fde-protoprecedent.user/usb-hostno longer knows anything about CCID semantics — it exposes a BULK_OUT / BULK_IN IPC ABI on endpoint 31 ([opcode:1][slot_id:1][...payload]request,[status:1][...result]reply; STATUS_OK/INVALID_OPCODE/TRUNCATED/PAYLOAD_TOO_BIG/DEVICE_NOT_READY/XHCI_ERROR codes; MAX_BULK_PAYLOAD=192 inline-data cap). The retired inlinerun_ccid_get_slot_status_smoketest in usb-host's main is replaced by the real consumer in user/ccid.cambios-ccid-protocarriesencode_get_slot_status+decode_slot_status+IccPresence/CommandStatusenums +message_typeconstants for the broader CCID 1.1 § 6.1+§6.2 message families that future substages will fill in; 7 host tests cover canonical round-trips, the actual QEMU-observedRDR_to_PC_SlotStatusbyte pattern, and rejection of truncated/mistyped buffers. End state undermake run-quiet-dev-piv: usb-host completes enumeration through Configure Endpoint, registers ep 31, becomes ready; ccid registers ep 33, issuesPC_to_RDR_GetSlotStatusvia usb-host's IPC, and logs the parsed response —bSlot=1, bSeq=0, bStatus=0x02, ICC presence = absent.MAX_BOOT_MODULES+MAX_MODULESbumped 16 → 32 to accommodate the new boot module (current load is 19; the 16 cap was silently dropping shell + audit-tail + worm before B-vii, found via[boot::limine] WARNING: dropped 3 boot modulesdiagnostic). New code uses durable anchors only — noB-viiprefixes in comments, doc-comments describe what the code does. B-vii is the last QEMU-only substage: B-viii (PIV applet APDUs over CCID) needs a real smart card or a chardev-backed CCID emulation. - 2026-05-25 — USB host stack Stream B substage B-vi.c: first bulk transfer end-to-end on the configured CCID endpoints. New
BulkDirenum +XhciController::bulk_transfer(dir, paddr, len) -> Result<u32, _>issues a single Normal TRB (xHCI 1.2 § 6.4.1.1, type 1) on the chosen direction's transfer ring, rings the per-DCI doorbell, polls for the matching Transfer Event, returns actual bytes moved (= requested - residual).wait_for_transfer_eventextended to accept bothSUCCESSandSHORT_PACKET(CCID 1.1 § 6.2.2 bulk IN responses are typically short — the device returns only the bytes it has, not the full requested length). Newcompletion_code::SHORT_PACKET = 13constant. End state undermake run-quiet-dev-piv: PC_to_RDR_GetSlotStatus (10 bytes) goes out on bulk OUT (DCI 6 = ep 3 OUT), RDR_to_PC_SlotStatus (10 bytes) comes back on bulk IN (DCI 5 = ep 2 IN), parsedbMessageType=0x81 bSlot=0 bSeq=0 bStatus=0x02(ICC absent — QEMU usb-ccid has no chardev backend, expected). Bug found + fixed during bring-up:configure_endpoint's EP context offset calculation wasdci * ctx_size, off-by-one — the Input Context layout per xHCI 1.2 § 6.2.5 places EP DCI=N at offset(N+1) * ctx_sizebecause the Input Control Context takes the firstctx_sizeslot. Fix changed the offset to(dci + 1) * ctx_size. Symptom wasusb_xhci_ep_kick slotid 1, epid 6followed by nousb_xhci_fetch_trb— the controller saw the doorbell, looked at the EP context's TR Dequeue Pointer, found 0 (because the IC context for the kicked DCI was untouched — driver had populated the DCI-1 slot instead), and silently stayed idle. Found via diagnostic dumps of the Device Context EP6 ctx (all zeros except EP State = Running) + comparison to the Input Context layout in the spec. The corresponding offset inaddress_devicewas correct from B-iv because EP0/DCI=1 happened to line up under the wrong formula (1*32 == (1+0)*32is coincidentally the same as2*32 // ICC + Slot). Polling-based completion retained; IRQ delivery skipped from B-vi scope per the substage plan agreed before B-vi.a (polling is acceptable for low-rate CCID APDU traffic). New code uses durable anchors only — noB-vi.cprefixes; the closing cleanup sweep of earlier substages'B-iii/B-iv/B-vlabels stays queued for after B-ix. - 2026-05-24 — USB host stack Stream B substage B-vi.b: SET_CONFIGURATION + Configure Endpoint + bulk transfer rings. New
XhciController::control_transfer_no_data(setup)helper carries the 2-TRB Setup/Status sequence for control transfers without a Data Stage (xHCI 1.2 § 6.4.1.2 with TRT=0; Status Stage direction is IN per USB 2.0 § 8.5.3).set_configuration(value)wraps the helper with the standard SET_CONFIGURATION request (USB 2.0 § 9.4.7,bmRequestType=0x00,bRequest=0x09,wValue=config_value). NewXhciController::configure_endpoint(&CcidEndpoints) -> Result<u8, XhciError>allocates per-endpointTransferRings, rebuilds the Input Context (Add Context flags = A0 | A_in | A_out; Slot Context re-populated with Context Entries = max DCI; bulk IN endpoint context with EP Type=6 + speed-correct MPS + TR Dequeue + Avg TRB Length=1024; bulk OUT context with EP Type=2 mirrored), submits the Configure Endpoint Command (TRB Type 12 per xHCI 1.2 § 4.6.6, DC=0), and reads back the Device Context's Slot Context DWord 3 to confirm the Addressed → Configured transition. NewCcidBulkRingsstruct onXhciControllerretains DCIs + MPSes + transfer rings for B-vi.c's first bulk transfer. New fieldsport_idx/port_speedonXhciController(populated byaddress_device) so the Slot Context re-fill in Configure Endpoint preserves current state without needing to read the Device Context back. DCI mapping (xHCI 1.2 § 4.5.1) is2 * ep_num + dir_bit: QEMU usb-ccid's ep 2 IN → DCI 5; ep 3 OUT → DCI 6; Context Entries field = 6. End state undermake run-quiet-dev-piv: B-vi.a sequence still passes;SET_CONFIGURATION OKreaches the device;Configure Endpoint OK; slot state = 3confirms the slot moved to Configured. New code uses durable anchors only — noB-vi.breferences in comments per Convention 10; the closing cleanup sweep over earlier substages'B-iii/B-iv/B-vlabels still queued for after B-ix. - 2026-05-24 — USB host stack Stream B substage B-vi.a: GET_DESCRIPTOR(Configuration) + descriptor parser + Evaluate Context for EP0 MPS reconciliation. EP0 control-transfer code factored — the 3-TRB Setup/Data/Status enqueue + doorbell + wait pattern lifts into a single
control_transfer_in(setup, buf_paddr, length)helper onXhciController;get_descriptor_devicereduces to a thin wrapper, newget_descriptor_configuration(&mut [u8])issues the two-pass USB 2.0 § 9.4.3 read (9 bytes to learnwTotalLength, then full blob) into a caller-owned buffer. NewMAX_CONFIG_DESCRIPTOR_SIZE = 512SCAFFOLDING bound + ASSUMPTIONS row. Newuser/usb-host/src/descriptors.rsmodule — pure functions (no syscalls, no MMIO) walking the variable-length config blob:parse_configurationfor the top-level descriptor + body slice,find_ccid_interfacefor the CCID-class (0x0B) interface together with its bulk IN + bulk OUT endpoint pair. Skips class-specific descriptors (CCID functional type 0x21, etc.) viabLength. NewXhciController::evaluate_ep0_context(new_mps: u16)reuses the Input Context page fromaddress_device, sets Add Context flags = A1 only (EP0), populates the EP0 endpoint context with the device-reported MPS, submits an Evaluate Context Command (TRB Type 13 per xHCI 1.2 § 4.6.7); the controller writes through to the Device Context's EP0 entry so subsequent transfers use the corrected MPS without rebuilding the slot. End state undermake run-quiet-dev-piv: B-v sequence still passes; EP0 MPS reconciled 8 → 64 ("Evaluate Context OK"); GET_DESCRIPTOR(Configuration) returns wTotalLength=93 bytes; CCID interface located:bConfigurationValue=1,bInterfaceNumber=0, bulk IN @ address 0x82 (MPS=64), bulk OUT @ address 0x03 (MPS=64). B-vi.b consumes these to build the Configure Endpoint Input Context. - 2026-05-24 — USB host stack Stream B substage B-v: GET_DESCRIPTOR(Device) via EP0 control transfer.
TransferRinggains anenqueuemethod symmetric withCommandRing::enqueue(two-step write: body without cycle →compiler_fence(Release)→ control DWord with cycle as commit; returns slot paddr for completion matching; same Link-wrap-unimplemented stance with Convention 9 trigger pointed at B-vi runtime-driven transfer issuance). New TRB types inxhci.rs:SETUP_STAGE=2,DATA_STAGE=3,STATUS_STAGE=4,TRANSFER_EVENT=32. NewXhciController::get_descriptor_device() -> Result<[u8; 18], XhciError>walks the standard 3-TRB control-transfer sequence on the slot's EP0 transfer ring (xHCI 1.2 § 4.11.2 + § 6.4.1.2): Setup Stage TRB carries the 8-byte SETUP packet[0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00]via IDT=1 + TRT=3 (IN Data Stage); Data Stage TRB points at a freshly allocated DMA page with DIR=1 + length=18; Status Stage TRB has DIR=0 (OUT, opposite of IN data) + IOC=1, so the controller emits exactly one Transfer Event when the full sequence completes (event's TRB pointer matches the Status TRB paddr). All three TRBs enqueued, device doorbell rung (target=slot_id, value=1=EP0/DCI 1),wait_for_transfer_event(status_paddr)polls the event ring for the matching Transfer Event and returns 18 bytes from the buffer. NewXhciErrorvariants:EpNotReady/TransferRingFull/TransferTimeout/TransferFailed(u8). End state undermake run-quiet-dev-piv: B-iv sequence still passes; B-v then logs the parsed descriptor —bLength=18 bDescriptorType=1 bcdUSB=0x0110 bDeviceClass=0 bMaxPacketSize0=64 idVendor=0x08E6 idProduct=0x4433 bNumConfigurations=1. Notable finding: QEMU's usb-ccid reportsbMaxPacketSize0=64despite running at Full Speed (PORTSC speed=1), while B-iv'saddress_deviceset EP0 MPS=8 (the spec-correct FS default). QEMU's xHCI emulation accepted the transfer regardless; real hardware would require an Evaluate Context command to update the EP0 endpoint context's Max Packet Size before subsequent transfers. The Convention 9 trigger named atlog_device_descriptorinmain.rsfires here — Evaluate Context implementation becomes load-bearing in B-vi alongside Configure Endpoint (same Input-Control-Context shape, with the Add Context flags addressing the relevant endpoint contexts). DMA buffer for the descriptor response is per-transfer alloc (alloc_zeroed_page); Convention 9 trigger at the alloc site points at B-vi for a buffer pool when bulk endpoints land. - 2026-05-23 — USB host stack Stream B substage B-iv: Address Device + Input Context + Device Context + EP0 transfer ring. New
TransferRingtype inring.rs(structurally identical toCommandRing: 1 page, Link TRB at slot 255 toggling cycle, no enqueue path yet — B-v adds it; Convention 9 trigger named at the type: sharedTrbRingrefactor lands when a second transfer ring shows up in B-vi). NewXhciController::address_device(port_idx, speed) -> Result<slot_state, XhciError>allocates a fresh Input Context page (Input Control Context with A0|A1 add-flags, Slot Context carrying Route=0 + Speed + Context Entries=1 + Root Hub Port Number, EP0 Endpoint Context carrying CErr=3 + EP Type=Control + speed-default Max Packet Size + TR Dequeue|DCS=1 + Avg TRB Length=8), allocates a fresh Device Context page (controller-written), allocates the EP0TransferRing, installs Device Context paddr intoDCBAA[slot_id], issues the Address Device Command (TRB Type 11 with BSR=0 — controller drives SET_ADDRESS on the bus), and reads back the Slot Context's Slot State [31:27] from the Device Context for logging. Context layout selects 32B vs 64B per-context spacing fromcap.csz. NewXhciError::SlotNotEnabledcovers the misordering case. New SCAFFOLDING boundTRANSFER_RING_TRBS = 256+ ASSUMPTIONS row.XhciControllergrowsinput_context_paddr/vaddr,device_context_paddr/vaddr,ep0_transfer_ring: Option<TransferRing>fields (single-slot today; Convention 9 trigger: "Revisit when multi-device discovery lands (B-vi) — these belong in a slot-indexed table"). End state undermake run-quiet-dev-piv: B-iii sequence still passes (port 5 detected, reset OK, NoOp OK, Enable Slot OK; slot_id = 1); B-iv then runs Address Device and logsAddress Device OK; slot state = 2(2 = Addressed per xHCI 1.2 § 6.2.2 Slot State enum). No actual EP0 transfers yet — that's B-v's GET_DESCRIPTOR. No IRQ delivery yet — that's B-vi. - 2026-05-22 — USB host stack Stream B substage B-iii: port enumeration + command/event flow + first commands.
XhciControllergrows PORTSC accessors with RW1C-safe writes, port walk + port reset (preserve CCS/PED/PP, set PR=1, wait for PRC, RW1C-clear PRC), doorbell-array MMIO access,submit_command/wait_for_command_completionflow that enqueues a TRB viaCommandRing::enqueue, rings HC doorbell 0, polls the event ring (viaEventRing::poll_next) for a matching Command Completion Event, and updates ERDP on consumption (with EHB RW1C clear).noop_command()andenable_slot()helpers built on top. End state undermake run-quiet-dev-piv: usb-ccid attached to qemu-xhci is detected on port 5 (Full Speed), port reset succeeds with PED=1, NoOp Command returns completion code 1 (Success), Enable Slot Command returns Slot ID = 1.XhciController.slot_id: Option<u8>threads the slot forward to B-iv's Address Device. Two non-obvious bugs found + fixed during bring-up: (1) all 64-bit MMIO writes (CRCR / DCBAAP / ERSTBA / ERDP) must be LO-first / HI-second under QEMU's xhci — the HI-first order silently failed because QEMU latches the dequeue/pointer on the HI write using the captured LO; (2)CommandRing::enqueuewrites the TRB in two steps (body with cycle cleared → compiler_fence(Release) → control dword with cycle bit set) — a single 16-bytewrite_volatile<Trb>may be split by the compiler such that the controller reads a torn TRB with cycle=1 but stale body, asserting USBSTS.HCE. Kernel-side companion change:src/pci/mod.rsscan()now writes the PCI command register (I/O + Memory + Bus Master enable) for every discovered device after BAR decode — defensive against firmwares that don't, though SeaBIOS already does for the device classes shipped today.CommandRing::enqueuereturnsNoneon Link-TRB-slot collision; full Link-wrap (rewrite Link's cycle, toggle producer cycle, reset producer) is deferred — Convention 9 trigger named at the call site: "when port-status-change-event handler auto-issues commands without explicit driver code at the call site." - 2026-05-21 — USB host stack Stream B substage B-ii: operational bring-up.
XhciController::bring_upruns the xHCI 1.2 § 4.2 sequence end-to-end — HCRESET (halt + reset + wait for CNR clear), CONFIG.MaxSlotsEn = 8, DCBAA allocation (1 page, zero-init), command ring (256 TRBs with Link TRB at slot 255 toggling cycle on wrap), event ring (256 TRBs) + ERST (single-segment table), interrupter 0's ERSTSZ / ERSTBA / ERDP installed, USBCMD.RUN, then poll USBSTS.HCH until cleared. End state verified undermake run-quiet-dev-piv: USBSTS post-RUN = 0x00000000 (HCH=0 running, CNR=0 ready, no error bits). Newuser/usb-host/src/ring.rsmodule housesTrb/CommandRing/EventRing/Erst; newXhciControllerstruct inxhci.rsowns the MMIO bases + DMA-backed rings; newXhciErrorenum (HaltTimeout / ResetTimeout / NotReadyTimeout / RunTimeout / DmaAllocFailed) covers the bring-up failure modes. Four new SCAFFOLDING bounds tagged + ASSUMPTIONS rows:COMMAND_RING_TRBS=256,EVENT_RING_TRBS=256,MAX_SLOTS_ENABLED=8,MAX_POLL_ITERATIONS=1000. CRCR / DCBAAP / ERSTBA / ERDP all written high-dword-first then low-dword per xHCI 1.2 § 4.6.1.2. No port enumeration, no command issuance, no IRQ — those land in B-iii / B-iv. Open: the defaultmake runpath (degraded-mode FDE) stalls between fde-mount's exit and virtio-net's module_ready in HEAD; pre-existing regression independent of B-ii —run-quiet-dev-piv(FDE-enabled e2e target) is the verification path that reaches the shell. - 2026-05-20 — YubiKey Stream A substage A-v.e:
tools/format-volume/host tool ships. Sibling totools/sign-elf/andtools/gen-dev-piv-keys/— host-side, workspace-excluded, own.cargo/config.tomltargetingaarch64-apple-darwin. Reads the 168-byte DPIV bundle (slot-9C Ed25519 sign key + slot-9D X25519 public key + bootstrap AID), generates a fresh ephemeral X25519 keypair, computes the X25519 ECDH shared secret, derives a ChaCha20-Poly1305 symmetric key viablake3::derive_key(WRAP_KDF_CONTEXT, &shared), AEAD-encrypts a 32-byte AES-256 master key (random by default;--master-key-hexoverride for reproducible runs), builds a 1-slot YubiKey-live volume header per ADR-032 § 4 (432 bytes total: 112 fixed prefix + 256 slot + 64 signature), signs the [0..header_length-64] prefix with the slot-9C Ed25519 key, zero-pads to 16 KiB to match the LBA 0..3 reserved extent, writes to the target raw disk image file. After writing, the tool self-verifies by round-tripping the bytes through the samecambios_fde_proto::parse+parse_slot_table+find_first_live_yubikeycallsfde-mountuses at boot — catches format-drift bugs at format time rather than first-boot. Stream A's unlock side is now structurally complete: the runtimemake runflow under--features dev-pivcanmake gen-dev-piv-keys+make format-volume+tools/format-volume/.../format-volume disk.img+ boot, and fde-mount should walk health probe → PIN → read_volume_header → verify_volume_header → parse_slot_table → piv_decrypt → blake3 derive_key → ChaCha20-Poly1305 decrypt → stub install successfully. Out of scope for A-v.e: real YubiKey-backed format (uses the DPIV bundle for now; the production format mode talks to a real YubiKey via PC/SC, comes alongside stream B), Argon2id recovery slot provisioning (deferred to a future recovery-design ADR), multi-slot enrollment UX. Three new host-side deps forformat-volume:chacha20poly1305,ed25519-compact(withx25519feature),blake3. All match what fde-mount + gen-dev-piv-keys already use. - 2026-05-19 — YubiKey Stream A substage A-v.a:
fde-mountboot module ships. Newuser/fde-mount/userspace orchestrator walks the full FDE unlock flow per ADR-032 § Architecture lines 154-167: registers reply endpoint 32, probespiv_health(bails to "NoPiv" in default builds), verifies the dev PIN123456, calls the newSYS_READ_VOLUME_HEADERto copy LBA 0..=3 (16 KiB) into a local buffer, callsSYS_VERIFY_VOLUME_HEADER(A-iv), walks the slot table viacambios_fde_proto::parse_slot_table+find_first_live_yubikey(A-v.b), extracts the 80-byte envelope per ADR-032 § 4 (locked at the prior ADR-032 commit), callspiv_decrypt(KeyManagement, ephemeral_pk)for the X25519 ECDH shared secret, derives the ChaCha20-Poly1305 symmetric key viablake3::derive_key(WRAP_KDF_CONTEXT, &shared), decrypts the envelope ciphertext in-place to recover the 32-byte AES-256 FDE master key, and stub-installs (A-v.d will replace the stub withSYS_INSTALL_MASTER_KEY). All key material (shared / symm_key / plaintext) zeroized via thezeroizecrate before_startexits. NewSyscallNumber::ReadVolumeHeader = 74incambios-abi(all seven syscall-workflow touchpoints updated); kernel handler uses the existingVirtioBlkDevicekernel-cmd path to read 4 × 4 KiB blocks; bootstrap-Principal-only authority (same gating asClaimBootstrapKey/BindPrincipal); 16 KiB kernel-side stack buffer. Newcambios_libsys::read_volume_header(&mut buf) -> i64thin wrapper. NewWRAP_ENV_*envelope constants incambios-fde-proto(offsets, length,WRAP_KDF_CONTEXT,WRAP_NONCE,FDE_MASTER_KEY_LEN); 5 new tests verify offset contiguity, fit inSLOT_WRAPPED_KEY_MAX, AEAD overhead math, KDF context non-empty, nonce shape.limine.conf+limine-aarch64.confaddfde-mount.elfafter virtio-blk. Makefile getsfde-mount/fde-mount-aarch64/fde-mount-riscv64targets + iso recipe inclusion + ELF signing. Three new userspace deps forfde-mount:chacha20poly1305 = "0.10" (no_std),blake3 = "1.8" (pure)already kernel-side,zeroize = "1.7" (no_std). Out of scope for A-v.a:SYS_INSTALL_MASTER_KEY(A-v.d),EncryptedBlockDevice<B>XTS-AES wrapper (A-v.c),tools/format-volumehost tool (A-v.e), recovery boot path. All three arches build clean (make check-all). Defaultmake isosucceeds with fde-mount included; runtime behavior in default builds = "NoPiv" log + clean exit. - 2026-05-18 — YubiKey Stream A substage A-v.b.1: shared-crate extraction. New
cambios-fde-protocrate at workspace root (MPL-2.0, no_std, no dependencies — mirrors thecambios-abiprecedent for shared-format crates). All volume-header byte layout, fixed-prefix parser, slot table parser, slot enums, andSlotEntrystruct migrate fromsrc/fs/crypto/header.rsinto the shared crate; 21 parse-only tests move with them. Kernelsrc/fs/crypto/header.rsbecomes a thin shim that re-exports the proto types and keeps onlyverify_header(which depends oncrate::crypto::verify— kernel-only). Userspace shellfde-testswitches from duplicatedFDE_OFF_*constants to the proto crate's named imports. Setup for A-v.a'sfde-mountboot module + A-v.e'sformat-volumehost tool: both will consumecambios_fde_proto::{parse, parse_slot_table, find_first_live_yubikey}directly without duplicating byte layout. 853 kernel host tests pass (was 874; -21 moved to proto crate where they pass standalone). All lints clean; baseline regenerated to drop the stalesrc/fs/crypto/header.rs:47-58entries now living in the proto crate (which is outsidesrc/and not scanned). - 2026-05-18 — YubiKey Stream A substage A-v.b: multi-slot volume header parser. Extends
src/fs/crypto/header.rswithSlotTypeenum (Empty/YubiKey/Argon2idPassphrase per ADR-032 § 4 slot table),SlotClassenum (Live/Recovery per § 5), andSlotEntry { slot_type, slot_class, wrapped_key_len, slot_principal, wrapped_key }carrying the parsed slot at full 256-byte fidelity. Newparse_slot_table(bytes, slot_count) -> [Option<SlotEntry>; MAX_VOLUME_SLOTS]walks the slot region afterverify_headersucceeds — pure function, validatesslot_type/slot_classbyte ranges +wrapped_key_len <= SLOT_WRAPPED_KEY_MAX=220, returns three newHeaderErrorvariants for the structural failures. Helperfind_first_live_yubikey(&slots)returns the firstSlotEntrymatching(slot_type=YubiKey, slot_class=Live)— the unlock target A-v.a'sfde-mountwill walk to. 15 new host tests cover all-None zero-slot, single live-YubiKey round-trip, 3-slot mixed (live YK + recovery Argon2id + empty), slot-count overflow / truncated bytes / bad slot_type / bad slot_class / oversize wrapped_key_len rejection, max wrapped_key_len acceptance, find-helper's recovery+Argon2id-skip behavior + first-of-multiple selection + empty-table handling, plus enum byte round-trips. Dispatcher'shandle_verify_volume_headerupdated to map the three newHeaderErrorvariants toInvalidArg(structural failures). 874/874 kernel host tests pass (was 859; +15). Out of scope for A-v.b: A-v.afde-mountorchestrator that consumes this (next), A-v.c EncryptedBlockDevice (XTS-AES wrapper), A-v.d SYS_INSTALL_MASTER_KEY, A-v.e format-volume tool. - 2026-05-18 — YubiKey Stream A substage A-v.0: zero-on-free in
FrameAllocator. Newzero_frame_range(start_idx, count)helper writes zeros through the HHDM map for each freed frame; wired into bothfreeandfree_contiguousafter the bitmap-clear succeeds. Closes a class of "freed-frame remnant" attacks system-wide; load-bearing for A-v.a'sfde-mountorchestrator which will briefly hold an AES-256 FDE master key in a stack buffer betweenpiv_decryptandSYS_INSTALL_MASTER_KEY. Helper is cfg-split (real write under#[cfg(not(test))], no-op in host tests since the simulated phys addresses have no backing memory). Singleunsafeblock with SAFETY comment per Convention 1. Early-boot guard short-circuits whencrate::hhdm_offset() == 0. +2 wiring tests; 859/859 host tests pass. - 2026-05-18 — YubiKey Stream A substage A-iv: first consumer round-trip. New
src/fs/crypto/{mod.rs,header.rs}(kernel) carriesVolumeHeader::parse+verify_headerper ADR-032 § 4 — pure functions that check magic /header_lengthbounds /slot_count ≤ MAX_VOLUME_SLOTS=16/volume_uuid == bootstrap_pubkey(AID-equals-pubkey per ADR-025) / ed25519 signature overbytes[0..header_length-64]. Wires throughcrate::crypto::verifyso no direct ed25519-compact use in fs/. NewSyscallNumber::VerifyVolumeHeader = 73incambios-abi(identity-required;requires_identity()+ identity test arrays updated;from_u64mapped;all_syscall_numbers_coveredrange extended to 0..=73). Kernel dispatcher arm +handle_verify_volume_headercopy the user buffer throughUserReadSlice(HEADER_MAX_LEN = 4 KiB stack-allocated), load the baked bootstrap pubkey viaBOOTSTRAP_PRINCIPAL.load().current_key_bytes(), route throughverify_header, and mapHeaderErrorvariants toInvalidArg(structural) orPermissionDenied(AID / signature mismatch). Newcambios_libsys::verify_volume_header(&[u8]) -> i64thin wrapper. Shell gains anfde-testcommand that probespiv_health, verifies the dev PIN123456, reads the slot-9C pubkey, builds a HEADER_MIN_LEN=176 byte 0-slot header withvolume_uuid= pubkey, signs the prefix viapiv_sign(slot=Signature), and hands the result tosys::verify_volume_header. Under--features dev-pivon both kernel and key-store-service, this round-trips end-to-end (SwPivBackend slot-9C key matches kernel-baked bootstrap pubkey by construction); default builds exit early at theNotPresenthealth probe. Host test coverage: 14 new tests infs::crypto::header(minimal-header round-trip, tampered content / signature / pubkey rejection, AID-vs-signing-key mismatch, length-bound violations, padded-1-slot header round-trip); 857/857 kernel host tests pass (was 843). Out of scope for A-iv: kernel-as-IPC-client architecture (kernel still readsBOOTSTRAP_PRINCIPAL.load()for verify, doesn't yet IPC to key-store-service — that lands at A-v with the FDE mount path +EncryptedBlockDevice+piv_decrypt-driven master-key unwrap), real volume-on-disk format/mount, multi-slot table parsing. No new lock, no new capability, no new unsafe.SYS_VERIFY_VOLUME_HEADERsurvives A-v as the diagnostic / recovery-shell primitive (does not get torn down). - 2026-05-18 — YubiKey Stream A substage A-iii: IPC dispatch wires
cambios-key-store-servicefor the seven newCMD_PIV_*commands (3-9). Newuser/key-store-service/src/piv/dispatch.rscarries the puredispatch_piv_command<B: PivBackend>(backend, request, response) -> usizefunction — decodes per the libsys codec from A-i, calls into the backend, encodes the matching response, maps backendPivErrorto wirePivStatusbytes.src/piv/inert.rsadds the always-NotPresentstand-in selected in default builds;src/piv/mod.rsintroduces apub type ActiveBackendcfg-alias (Sw underdev-piv, Inert otherwise) somain.rspicks one at compile time withoutBox<dyn>.src/main.rsinstantiatesActiveBackendonce at startup and adds a single arm in the service loop that routes any CMD_PIV_* opcode through dispatch; legacyCMD_SIGN/CMD_GET_PUBKEYpaths unchanged.user/libsys/src/keystore.rsgains seven IPC wrappers —piv_health,piv_verify_pin,piv_list_slots,piv_get_pubkey,piv_sign,piv_decrypt,piv_attest— each taking areply_endpoint: u32the caller must have pre-registered viaSYS_REGISTER_ENDPOINT; they compose the codec, callsys::writeto KS endpoint 17, block onsys::recv_msg, strip the 36-byte IPC envelope, and return the typed result. Audit-emit on key-use is deferred per Convention 9 withRevisit when: userspace audit-emit syscall lands OR audit-tail subscribes to key-store eventsat both server (dispatch sign/decrypt arms) and client (libsys keystore module) sites — ADR-007's audit-emit primitives are kernel-side today, so the userspace-emit story is its own design problem. Identity gating relies onrecv_verifiedper ADR-026 (anonymous senders dropped before reaching dispatch; no Principal-value branching inside the kernel ring). Test coverage: 10 InertPivBackend dispatch tests in default builds, +6 SwPivBackend-through-dispatch tests under--features dev-piv(sign+verify, decrypt ECDH round-trip, PIN lockout surfacing health=NotReady, sign-before-PIN→AuthRequired); 39/39 pass with dev-piv, 10/10 default. Out of scope for A-iii: the first consumer (A-iv FDE volume header sign+verify), CcidPivBackend (stream B). No new syscall, no new capability, no new lock, no new unsafe. - 2026-05-18 — YubiKey Stream A substage A-ii: software-emulated PIV backend lands behind a new
dev-pivcfg flag spanning the kernel andcambios-key-store-service. New host tooltools/gen-dev-piv-keys/derives slot-9C (Ed25519, signing) + slot-9D (X25519, key management) keypairs from a persistent per-developer seed attools/gen-dev-piv-keys/.dev-seed.bin(gitignored), writesdev_bootstrap_pubkey.bin(40-byte CKEY v1, format-compatible withsign-elf --export-pubkey) at the workspace root anduser/key-store-service/dev_piv_secret.bin(168-byte DPIV v1 bundle) inside the service crate, both gitignored. The kernel'sbootstrap_identity_initbaked-in pubkey switches between the committed real-YubiKeybootstrap_pubkey.bin(default) and the dev pubkey (under--features dev-piv) viacfg-gatedinclude_bytes!.user/key-store-servicegainssrc/lib.rs+src/piv/{mod.rs,sw.rs}exposing thePivBackendtrait andSwPivBackendimplementation that answersPivBackend::{health,verify_pin,list_slots,get_pubkey,sign,decrypt,attest}against the DPIV bundle's keys;decryptperforms X25519 ECDH and returns the 32-byte shared secret per real PIV slot-9D semantics. PIN policy mirrors PIV defaults (PIN =123456, 3-failure lockout, verified state persists for backend lifetime). 23 host tests cover bundle parsing, PIN lockout transitions, sign-verifies-under-advertised-pubkey, and decrypt-roundtrip-against-independent-ECDH-sender; all pass oncargo test --features dev-piv --target x86_64-apple-darwin. Out of scope for A-ii: IPC dispatch arms for the new CMD_PIV_* codec (substage A-iii), kernel-side consumer integration (A-iv FDE volume header sign+verify). Default no-feature builds untouched; production path continues using the real YubiKey bootstrap pubkey.make gen-dev-piv-keysis the explicit prereq before any--features dev-pivbuild. - 2026-05-18 — USB host stack Stream B substage B-i:
user/usb-host/userspace driver lands as a boot module on endpoint 31. Discovers an xHCI controller via theSYS_DEVICE_INFOdescriptor (filters class=0x0C, subclass=0x03, prog_if=0x30 — last byte newly exposed in the existing 108-byte descriptor's reserved pad slot at offset 9, not an ABI break), maps the controller's MMIO BAR viaSYS_MAP_MMIO, parses the xHCI 1.2 § 5.3 capability register block (CAPLENGTH, HCIVERSION, HCSPARAMS1, HCCPARAMS1, DBOFF, RTSOFF), and logs the dump. Idles cleanly on hosts with no xHCI (aarch64/riscv64 without-device qemu-xhci). No port enumeration, no transfers, no IRQ — those land in B-ii / B-iv.make run/run-aarch64/run-riscv64now attach-device qemu-xhci,id=xhci0 -device usb-ccid,bus=xhci0.0so the real CCID transport path is wired from B-i forward (CCID chardev backend wires in at B-v). All three arches build clean (make check-all). Foundation for stream A'sPivBackend::CcidPivbackend swap at B-vii. - 2026-05-16 — ADR-029 step 6 backend half (3-commit
6-i/ii/iiichain). Per-processFdTableonProcessDescriptorwithMAX_FDS_PER_PROCESS = 64SCAFFOLDING + monotonic generation counter for stale-fd detection;FileMetadatastruct added tocambios-abifor SYS_STAT return shape.PosixFsBackend<B>gainscreate_inode/open_inode/stat_inode/acl_grant/acl_revoke/acl_listmethods, all owner-or-ACL-row authorization per ADR-029 § Decision 3, all journal-flush-before-header-write per § Decision 5 (idempotent on replay). Tier3-at-1-TiB binding tests updated for the ~3.6 KiBSLOT_OVERHEADgrowth from FdTable per ADR-008 § Post-Change Review (binding flipped MaxSlots → BudgetCeiling). Step-6 scope is backend-only: dispatcher arms still route SYS_FILE_OPEN..SYS_ACL_LIST throughhandle_posix_stub→ Enosys; the runtime POSIX_STORE singleton is deferred to step 7 because the 16 MiB journal exceeds the 4 MiB kernel heap, and step 6 has no userspace consumer to motivate routing it through the frame allocator or amending the ADR. Step 6 handler logic is exercised by host tests withMemBlockDevice; 833 host tests pass. - 2026-05-16 — ADR-010 § Divergence 3 landed: CambiObject v2 records adopt the shared bitmap + journal (4-commit
5Dchain).FORMAT_VERSIONbumps to 2; the superblock gainsbitmap_region_lba/journal_region_lba/data_region_lba/journal_capacity_bytes/last_checkpoint_offsetdeclaring the v2 disk regions. NewARCOREC_MAGIC_V2 = "ARCOREC2"distinguishes v2 records from v1; the 192-byte header-resident extent array at offset 568..760 carries up to 16(start_lba, block_count)extents pointing into the shared data region (single-extent allocation in v1; multi-extent fallback documented asRevisit when:).DiskObjectStoregains in-memorybitmap: BlockBitmap+journal: Journalstruct fields; mount runs journal-replay over a fresh all-free bitmap and cross-checks against the on-disk bitmap region (defense-in-depth, mirroringPosixFsBackend5C-ii).putwrites v2 records (journalBitmapMutation::Set→ content blocks → header → write-through bitmap region);getmagic-dispatches onARCOREC1vsARCOREC2so v1 records remain readable forever;deletejournalsBitmapMutation::Clearfor v2 records before zeroing the slot header. v1 disks (FORMAT_VERSION=1superblock) are rejected at mount viaSuperblockState::UnknownVersion. Crash-safety gap (out of scope): the current write order leaves a window where a crash between header write and journal record could orphan data blocks; full atomicity per Divergence 3's "atomic with the CambiObject record's header commit" wording requires mount-side slot-scan augmenting the bitmap reconstruction OR a journal record carrying enough info to commit the header on replay —Revisit when:production crash testing surfaces it. - 2026-05-15 — ADR-029 § Divergence 2 landed:
JOURNAL_LOCK(13)promoted to top-level lock-hierarchy position alongsideBLOCK_BITMAP_LOCK(12)(4-commit5Cchain).PosixFsBackendgains in-memorybitmapandjournalstruct fields;mountreorders to journal-replay → defense-in-depth bitmap cross-check → inode scan; newallocate_block/free_blockprimitives journal anExtentUpdaterecord per ADR-029 § Decision 5 withBitmapMutation::Set/Clear.src/fs/journal.rsadds theJournalstruct with single-wrap-around circular-log semantics (KIND_PAD = 0xFFrecords fill the tail when records won't fit; wrap-stop atlast_checkpoint_offsetprevents re-applying pre-checkpoint stale records).POSIX_STORE(11)reserved in the hierarchy doc; concreteSpinlock<Option<PosixFsBackend<...>>>static declaration deferred to ADR-029 step 6+ when the kernel-singleton wire-up picks a concreteBlockDevice. Cross-backend acquisition pattern documented: POSIX-only / CambiObject-only / CAMBIO-cross-backend each follow strictly-downward chains rooted at their top-level lock. The shared journal record format makes the two backends' allocation transactions compatible from the momentJOURNAL_LOCKis reachable from both sides. - 2026-05-13 — ADR-028 → ADR-029 → ADR-030 ABI surface reserved in
cambios-abi.SYS_CAMBIO=50,SYS_REGALO=51,SYS_STREAM=52,SYS_FILE_OPEN..SYS_ACL_LIST=53..72. New type surface:ObjectHandle/FileDescriptor/StreamEndpoint/Rights/PosixInode/Extent/AclEntry/FrozenInodeView/InodeId/StreamCapShape.ChannelRecordgainsstream_cap_shape+stream_statefields per ADR-030. - 2026-05-07 — ADR-027 rendering-limb cluster wiring landed end-to-end (Option A — minimum viable migration). user/compositor calls
sys::cluster_createat startup with a 2-member manifest (compositor + scanout, both bootstrap Principal); cluster_id is threaded through an extendedRegisterCompositorwire format ([tag:4][cluster_id:8]= 12 bytes); both scanout drivers (scanout-virtio-gpu and scanout-limine) callsys::cluster_joinon receipt. New libsys wrappers (cluster_create/_join/_revoke/_info) +ClusterMemberwire-format struct +CLUSTER_POLICY_*/CLUSTER_ROLE_*constants. Boots end-to-end on x86_64 (make run-quietreachescambios>shell). Out of scope (substrate-deferred): virtio-input membership (no inbound endpoint),cluster_policy::caps_for_rolepopulation,SYS_CHANNEL_CREATEcluster_id arg + auto-attach, stripping the pairwise handshake's cap-token-passing role. Triggers for each named in code (Convention 9) and in the original ADR-027 § Migration Path. Cluster value-add today is structural (membership tracking + exit-path auto-revoke fan-out); functional cap-promotion lands when the substrate does. - 2026-05-07 — ADR-027 cluster syscall handlers landed end-to-end.
SYS_CLUSTER_CREATE/_JOIN/_REVOKE/_INFO(44–47) wire to the ClusterManager skeleton at lock position 5 (per ADR-027 § Architecture);CapabilityKind::CreateCluster/ClusterRevokeadded. Authority: cluster-create needsCreateClustercap or bootstrap Principal; cluster-revoke needs creator ORClusterRevokecap OR bootstrap. Newcluster_policy.rsmodule:caps_for_roleis a v1 stub returning empty (real cap shapes land with the rendering-limb migration that walks the existing pairwise handshakes);on_member_departis populated — RenderingLimb's policy is "any departure tears down the limb", per ADR-027 § Migration Path step 7.handle_exitextended with cluster-departure cleanup driving the same teardown sequence asSYS_CLUSTER_REVOKE. Path A (advisory quiesce) per ADR-027 Divergence 2 — cluster revoke wraps N atomic per-channel revokes inheriting tombstone-on-revoke from ADR-007 Divergence 7. BootstrapCreateClustergrant toinit+ rendering-limb migration pending. - 2026-05-06 — ADR-027
ClusterManagerskeleton at src/ipc/cluster.rs: pure bookkeeping + state machine (Forming → Active → Revoking → Revoked; memberExpected → Joined → Departed), slot+generation table, 34 host tests covering create/join/auto-promote/depart/attach-channel/begin-revoke/complete-revoke/slot-reuse. Three SCAFFOLDING bounds (MAX_CLUSTERS/MAX_CLUSTER_MEMBERS/MAX_CLUSTER_CHANNELS= 32 each per ADR-027 § Architecture v1-endgame math) tagged + rowed in docs/ASSUMPTIONS.md. No syscalls, no scheduler hooks, no integration — cluster ABI reservation, lock-hierarchy renumber, handlers, and rendering-limb migration follow per ADR-027 § Migration Path steps 4–7. - 2026-05-04 — verification/CLAIMS.md: the honest gap-map between "what runs" (this file) and "what's proven." 14 rows spanning all four Status values (Proven / Tested / Asserted / Aspirational) and all three Layers (1=behavior, 2=guarantee, 3=meaning). Strict schema requires
Bound:andGap:on every row; vacuous rows fail review. Layer-3 meaning-claims (Zero-trust, AI-watches-not-decides) are explicitly Aspirational by their nature and the doc says so. C-11 (IPC identity transcription invariant) and C-12 (ObjectStore ownership) carry the planned Kani→Verus pivot triggers. - 2026-05-04 —
verification/dtb-proofs/: 5 Kani harnesses on the DTB parser atsrc/boot/riscv.rs(header validation, byte-extraction safety, wire-format contracts, bounded callbacks). Slice-shim refactor extracts purewalk_dtb_slice(&[u8])andFdtHeader::read_slice(&[u8])as the verifier entry points; the unsafewalk_dtb(dtb_phys)becomes a 4-line pointer-to-slice bridge. Real Kani finding fixed:be_u32_at/be_u64_atclaimed "return 0 on overrun" but actually panicked with arithmetic overflow when the symbolic offset reachedusize::MAX - 8; both helpers now usechecked_add. ADR-013 Decision 2's "no panics" claim now has provable backing for the byte-extraction layer. End-to-end walker proof (P-DTB-6) deliberately deferred — its CBMC budget at the natural bound exceeds one CPU-hour; needs walker restructuring or the planned Kani→Verus pivot, not unwind-tuning. - 2026-05-03 — Multi-Principal vault Phase 1C: new userspace service extending key-store (endpoint 17) with kernel consultation at process spawn. Plurality lives in userspace; kernel keeps Principal singular and atomic. AI sandbox is per-Principal. Implements the design from the identity.md Phase 1C rewrite + ADR-026.
- 2026-05-03 — ADR-027: service clusters as identity-bound channel meshes. Designed only — kernel-ABI cluster handle (
cluster_create/cluster_join/cluster_revoke) and lock-hierarchy placement spelled out, no implementation yet. First cluster target: rendering limb (compositor + scanout + virtio-input + libgui clients). Closes the compositor-#PF-on-clean-client-exit class (cluster-shaped revoke vs per-channel teardown). - 2026-05-02 — ADR-026: "transcribe-not-interpret" identity invariant. Codifies the rule the kernel was already implicitly following: read a Principal AID from
ProcessCapabilities.principal, copy it onto outgoing IPCsender_principal/ authored CambiObjectcreator/ audit events; never branch on the AID value to make a policy decision. Capability-shape duality (kernel(endpoint, rights)table entry vs rich external envelope) made explicit. AI-watches-flags-sandboxes-but-does-not-write-policy added as load-bearing principle. ADR-007 gains a divergence appendix tying the audit-cap migration to this framing. identity.md rewritten around the multi-Principal vault model at the same time. - 2026-05-01 — ADR-025: Principal-as-AID + crypto-agility plumbing. Principal is now a 32-byte AID (Authentication Identifier) — currently
algo=Ed25519, hash=blake3(pubkey)but the algo/hash fields are first-class so post-quantum migration is a code-only change, not a wire-format change. 256-byte IPC envelopes include 32-byte AID + algo + hash byte; PQ audit shows the format is forward-compatible to Dilithium without growth. - 2026-05-01 —
user/networkpolish: virtio-net registers reply-endpoint per ADR-027 framing precursor + wall-clock deadlines on retry/timeout + virtio-net modern PCI header parsing. - 2026-04-27 — ADR-022 wall-clock landed:
SyscallNumber::SetWallclock/GetWallclock(39 / 40),SetWallclockcapability gate,src/time/wallclock.rs(4 unit tests). Identity-aware shell prompt (did:key:z6Mk…@user>); GUIcmd_playflow;terminal-windowapp's manualclockcommand for offline demos. The ADR-022 implementation reservation memory pin from 2026-04-22 is resolved. - 2026-04-27 —
user/terminal-window/(new first-party app): boot splash matching coherentforge.com palette → recede-to-watermark transition → identity-aware shell with ANSI SGR per-cell color in the GUI Grid renderer. Compositor gains z-stack semantics: layered windows + per-pixel alpha; alpha-preservingSurface::blend_pixel+scale_brightness. Compositor forwards Pointer events to the focused window (was keyboard-only). - 2026-04-26 — Syscall ABI surface factored out to a new top-level
cambios-abi/crate (ADR-024;no_std, MPL-2.0, zero deps beyondcore). Owns the canonicalSyscallNumber/SyscallError/SyscallArgsdefinitions. Kernel re-exports them viapub use cambios_abi::*so existinguse crate::syscalls::SyscallNumbercall sites compile unchanged. libsys drops its 37 privateconst SYS_*: u64; policy-service drops 38 privateconst SYS_*: u32plus the 9 dead-code warnings they were emitting on everymake iso. policy-service's profile arrays move from&[u32]to&[SyscallNumber]— type-safe at every call site. Single source of truth across kernel + userspace; the "must matchsrc/syscalls/mod.rs" comment that flagged the old hand-mirror is gone. 4-commit chain onsyscall-abi-cratebranch (crate creation → kernel re-export → libsys migration → policy-service migration); each independently passesmake check-all. - 2026-04-26 — Audit consumer capability (ADR-023).
CapabilityKind::AuditConsumerreplaces the bootstrap-Principal-only check onSYS_AUDIT_ATTACH(ADR-007 § "Audit channel boot sequence");SYS_GET_PROCESS_PRINCIPAL = 42resolves asubject_pidto its bound 32-byte Principal so audit consumers can renderdid:key:z6Mk…without widening the 64-byte event format. Recent-exits ring onProcessTable(SCAFFOLDING, 64 entries) handles principal-after-exit lookups. New signeduser/audit-tail/boot module holds the cap, attaches to the ring, resolves principals via the new syscall, and prints one-line summaries to serial. Tri-arch built; 554 host tests pass. - 2026-04-21 — Kani proofs for FrameAllocator (
verification/frame-proofs/): 9 harnesses onsrc/memory/frame_allocator.rscoveringallocate,free,allocate_contiguous,free_contiguous, andadd_regionoverflow. Proof authoring found 2 integer-overflow sites that panic in debug / wrap in release on malformed bootloader memory-map entries (add_regionline 138,reserve_regionline 158); both fixed withsaturating_add.reserve_region's fully-symbolic overflow proof blows CBMC's memory budget; covered instead by a mechanical-copy of theadd_regionfix + a unit-test regression gate (test_reserve_region_wrap_boundary_no_panic). - 2026-04-21 — Kani proofs for CapabilityManager (
verification/capability-proofs/): 12 harnesses onsrc/ipc/capability.rs. Tier A (7) coversProcessCapabilities— empty-table denial, grant/verify composition, revoke effectiveness, absent-endpoint rejection, rights upgrade, count bound ≤ 32, capacity-full rejection. Tier B (5) coversCapabilityManageron a 3-slotBox::leak'd manager — stale-generation rejection (ADR-008 slot-reuse defence), delegate-without-delegate-right denied, no-rights-escalation,revoke_all_for_processclears every endpoint cap + all 5 system-cap flags, non-bootstrap revoke returnsAccessDeniedwith no state change. Kernel source unchanged; proof crate includessrc/ipc/capability.rsverbatim via#[path]and stubscrate::ipc::{ProcessId, EndpointId, CapabilityRights, Principal}locally, drops the audit emit via the existing#[cfg(not(any(test, fuzzing)))]gate flipped bybuild.rs--cfg fuzzing. ADR-000 § Divergence now cites these proofs as the formal backing for the capability-soundness claim. - 2026-04-21 —
did:keyencoder for Principals (identity.md Phase 4 pull-forward): 32-byte Ed25519 pubkey ↔did:key:z6Mk…via multicodec0xed+ base58btc, implemented inuser/libsys/(no new deps, no_std). Shell gains adid-keycommand (self / encode-hex / decode-did:key). Cross-verified against the RFC 8032 Test 1 vector. x/a/r. - 2026-04-22 — Kernel ECAM PCI enumerator → aarch64 GUI parity.
src/pci/mod.rsgrew amod ecam+mod configshim: x86_64 continues to use mechanism-1 port I/O (CF8/CFC), aarch64 + riscv64 route through ECAM MMIO atECAM_VIRT + (bus << 20) + (dev << 15) + (func << 12) + off.scan,decode_bars, andwalk_virtio_modern_capsare now arch-agnostic.pci::init_ecam(phys_base, size)maps the window into TTBR1 viamemory::paging::map_rangeon aarch64 (kernel frame allocator; bus 0 only, 1 MiB = 2 intermediate tables) and is a sanity check + VA publish on riscv64 (boot-HHDM gigapages already cover[0, 4 GiB)).handle_device_infois no longer x86-gated. Undermake run-aarch64-gui(new target) the kernel discovers virtio-gpu-pci + virtio-keyboard-pci over ECAM, scanout-virtio-gpu + virtio-input bind, the compositor handshake completes, andwormrenders frames — the verified failure mode before this landed was scanout-virtio-gpu hittingSYS_DEVICE_INFO=Enosysand falling into passive idle, which stalled the compositor's blockingrecv_verified(WelcomeCompositor). - 2026-04-22 — Pong v0 (first-party app):
user/pong/— third game in the HN-launch playable arc. Continuous-motion physics (8-bit subpixel integer fixed-point, AABB collision, classic-Pong spin, speed-capped AI), Tree-world palette (logs + acorn + grass). Replaces worm as default GUI boot module; worm + tree stay buildable for regression viamake worm/make tree(and each-aarch64/-riscv64variant). Second consumer oflibgui::FrameClock(extracted in the prior commit). - 2026-04-22 —
libgui::FrameClock: fixed-interval tick gate for self-driven apps. Pure-logic, host-testable; 7 unit tests covering boundary, refire, large-gap-no-catchup, backward-time, seed reset, zero-interval, step_ticks getter. Extraction trigger per Development Convention 9 (second consumer = pong). - 2026-04-22 — Worm v0 (first-party app):
user/worm/— classic snake on a 20×15 dirt grid with Tree-palette continuity (shared biosphere narrative). 200 ms tick, ring-buffer body + collision bitmap, bounded iteration. Replacestreeas default GUI boot module;treeretained for regression. - 2026-04-21 — Tree v0 (first-party app):
user/tree/— 9×9 Minesweeper homage on libgui + virtio-input, replaceshello-windowas default GUI boot module;hello-windowretained as protocol regression test. - 2026-04-21 — Input-1 (ADR-012):
user/libinput-proto96-byte wire format;user/virtio-inputdriver (modern virtio-pci, device class probed viaVIRTIO_INPUT_CFG_EV_BITS, evdev→HID translation); compositor forwards events to focused window onCOMPOSITOR_INPUT_ENDPOINT = 30; libguiClient::poll_eventdrains on a tagged libgui-proto message.make run-guicaptures Cocoa keyboard/mouse → serial log end-to-end. x86_64 only. - 2026-04-21 —
user/libguiv0:Client::open,Surfaceprimitives (fill_rect,draw_lineBresenham,draw_text_builtin8×8 ASCII font,blit_bitmapwith optional chroma-key),TileGrid. hello-window ported to the library; Tree v0 consumes it. - 2026-04-21 — Licensing: AGPLv3-or-later on kernel + services + apps, MPL-2.0 on
user/libsys/. SPDX headers across every source + config file. LICENSE files at both scope levels. Repo now public at github.com/coherentforge/CambiOS. - 2026-04-21 — Docs pivot: ADR-016 rewritten as "Windows Compatibility via Bounded Static Shims" (AI translator pipeline withdrawn); ADR-017 slot reused for "User-Directed Cloud Inference" (generative-not-extractive principle operationalized).
- 2026-04-20 — Phase Scanout-4.b: scanout-virtio-gpu is the default scanout driver. Modern virtio-pci transport via kernel-parsed
VirtioModernCaps+SYS_VIRTIO_MODERN_CAPS = 38. Five 2D ops (CREATE_2D / ATTACH_BACKING / SET_SCANOUT / TRANSFER_TO_HOST_2D / RESOURCE_FLUSH).make run-guishows a visible green window. - 2026-04-19 → 04-21 — ADR-020 Phase A → B.1-B.5 → C landed: typed
UserReadSlice/UserWriteSliceat the syscall boundary; every handler migrated; rawu64user pointers are type-system unreachable in production code. Phase D marked deferred with revisit triggers. - 2026-04-19 → 04-20 — ADR-021 Phase A → B.3 landed:
BootErrorpropagation from Limine adapter → APIC → timer / PLIC init. Phase C lint (make check-boot-panics) enforces no new panic sites in the curated boot-path file set. - 2026-04-19 — RISC-V Phase R-6: riscv64 boots to
cambios>shell prompt with 5 signed boot modules via-initrd(CAMBINIT archive). Third architecture at service-level parity.
Archs column: x = x86_64, a = AArch64, r = riscv64. x/a/r means first-class parity. Subsystems still gapped on one or two arches show what runs today; see known issues for what's missing.
| Subsystem | Status | Archs | Code | Design |
|---|---|---|---|---|
| Microkernel core | Done | x/a/r | src/microkernel/, src/memory/ |
CambiOS.md |
| Per-CPU SMP scheduler | Done | x/a/r | src/scheduler/ |
SCHEDULER.md, ADR-001 |
| Voluntary + preemptive context switch | Done | x/a/r | src/arch/*/mod.rs |
ADR-001 |
| IPC control path (256-byte messages) | Done | x/a/r | src/ipc/ |
ADR-000, ADR-002, ADR-005 |
| IPC bulk path (shared-memory channels) | Done (Phase 3.2d) | x/a/r | src/ipc/channel.rs |
ADR-005 |
| Capability revocation | Done (Phase 3.1, bootstrap-authority only; grantor + revoke-right paths deferred to post-v1) | x/a/r | src/ipc/capability.rs |
ADR-007 |
| Boot-time-sized kernel object tables | Done (Phase 3.2a-d) | x/a/r | src/config/tier.rs, src/memory/object_table.rs, src/process.rs, build.rs |
ADR-008 |
| Deployment tiers | Designed, policy-only (single binary; tier selects TableSizingPolicy at install) |
— | — | ADR-009, GOVERNANCE.md |
| Audit infrastructure | Done (Phase 3.3) | x/a/r | src/audit/ |
ADR-007 |
Audit consumer capability + audit-tail |
Done (bootstrap-only check replaced) | x/a/r | user/audit-tail/, src/ipc/capability.rs (AuditConsumer), src/syscalls/dispatcher.rs (handle_get_process_principal), src/process.rs (RecentExitsRing) |
ADR-023 |
| Policy service (syscall allowlisting) | Done (Phase 3.4b, per-process allowlists) | x/a/r | user/policy-service/ |
ADR-006 |
| Cryptographic identity | Done (Phase 1C, hardware-backed + load-bearing; Principal as 32-byte AID with algo/hash agility per ADR-025; transcribe-not-interpret invariant per ADR-026) | x/a/r | src/ipc/, src/syscalls/, user/libsys/, bootstrap_pubkey.bin |
identity.md, ADR-003, ADR-025, ADR-026 |
| Multi-Principal vault service | Done (Phase 1C; userspace plurality, kernel-side Principal stays singular/atomic; AI sandbox is per-Principal) | x/a/r | user/key-store-service/ (vault extends ep 17) |
identity.md Phase 1C, ADR-026 |
did:key encoding (Principal ↔ did:key:z6Mk…) |
Done (encoder + decoder; not full DID resolution) | x/a/r | user/libsys/src/lib.rs (did_key_encode/did_key_decode), user/shell/src/main.rs (did-key cmd) |
identity.md Phase 4 |
| Signed ELF loading | Done (ARCSIG trailer, Ed25519) | x/a/r | src/loader/ |
ADR-004 |
| Content-addressed ObjectStore (RAM) | Done (Phase 1C, fallback) | x/a/r | src/fs/ram.rs |
ADR-003 |
| Persistent ObjectStore (disk) | Done (Phase 4b) | x (via virtio-blk) | src/fs/disk.rs, src/fs/block.rs, src/fs/lazy_disk.rs, src/fs/virtio_blk_device.rs |
ADR-010 |
| BlockDevice abstraction | Done (Phase 4a.i) | x/a/r | src/fs/block.rs |
ADR-010 |
| POSIX file storage backend | Substrate done (5A–5D) + step-6 handler half done (create_inode / open_inode / stat_inode / acl_grant / acl_revoke / acl_list); runtime POSIX_STORE singleton + dispatcher wire-up + libsys shim deferred to step 7. Per-process FdTable lives on ProcessDescriptor. SYS_FILE_OPEN..SYS_ACL_LIST still return Enosys until step 7. |
x/a/r (host-testable; no userspace consumer yet) | src/fs/posix/mod.rs, src/fs/bitmap.rs, src/fs/journal.rs, src/process.rs (FdTable), cambios-abi/src/lib.rs (FileMetadata) |
ADR-029 |
| FS service | Done (endpoint 16, ObjectStore gateway) | x/a/r | user/fs-service/ |
— |
| Key-store service | Done (endpoint 17; CMD_PIV_* live via dispatch_piv_command; default builds answer NotPresent via InertPivBackend; SwPivBackend selected under --features dev-piv; first consumer = shell fde-test round-trip through SYS_VERIFY_VOLUME_HEADER) |
x/a/r | user/key-store-service/ |
ADR-032 |
| Virtio-blk driver | Done (Phase 4b, dual-endpoint user/kernel) | x/a/r | user/virtio-blk/ |
ADR-010 |
| Virtio-net driver | Done (Phase 4c, modern virtio-pci on x86_64; legacy MMIO on aarch64+riscv64; live in boot, drives udp-stack NTP demo) | x/a/r | user/virtio-net/ |
— |
| Intel I219-LM driver | Scaffolded, untested on hardware | x | user/i219-net/ |
— |
| UDP/IP stack (ARP/IPv4/UDP + NTP demo) | Done | x/a | user/udp-stack/ |
— |
Shell (arcobj CLI incl.) |
Done | x/a/r | user/shell/ |
— |
| Spawn / WaitTask syscalls | Done | x/a/r | src/syscalls/dispatcher.rs |
— |
Wall-clock subsystem (SetWallclock / GetWallclock syscalls + SetWallclock cap) |
Done (Phase 4d) | x/a/r | src/time/wallclock.rs, src/syscalls/dispatcher.rs (handle_set_wallclock / handle_get_wallclock) |
ADR-022 |
| Service clusters | End-to-end wiring live: kernel ABI (SYS_CLUSTER_* 44–47), cluster_policy (caps stub + RenderingLimb→revoke departure), exit-path auto-revoke, CreateCluster boot grant, libsys cluster_* wrappers, compositor calls cluster_create at startup, scanout drivers (virtio-gpu + limine) call cluster_join on RegisterCompositor receipt. Cluster_id threaded through extended RegisterCompositor wire format. Cap-table population + virtio-input membership + handshake-strip pending substrate (SYS_CHANNEL_CREATE cluster_id arg + virtio-input inbound endpoint). |
x/a | src/ipc/cluster*.rs, src/syscalls/dispatcher.rs, user/libsys/, user/libscanout/, user/compositor/, user/scanout-virtio-gpu/, user/scanout-limine/ |
ADR-027 |
| PCI bus discovery | Done (x86_64 = port I/O mechanism 1; aarch64 + riscv64 = ECAM via init_ecam; riscv64 also synthesizes virtio-mmio via register_virtio_mmio) |
x/a/r | src/pci/ |
— |
| Device syscalls (MapMmio/AllocDma/DeviceInfo/PortIo/VirtioModernCaps) | Done | x/a/r | src/syscalls/dispatcher.rs |
— |
Bootloader abstraction (BootInfo + src/boot/) |
Done (Phase GUI-0) | x/a/r | src/boot/ |
ADR-011 |
SYS_MAP_FRAMEBUFFER + graphics capabilities |
Done (Phase GUI-0) | x/a | src/syscalls/dispatcher.rs, src/ipc/capability.rs |
ADR-011 |
| Compositor (incl. Input-1 event routing) | Done (Scanout-2/3 + Input-1) | x/a | user/compositor/ |
ADR-014 |
| scanout-virtio-gpu driver (default) | Done (Scanout-4.b; aarch64 enabled by kernel ECAM 2026-04-22) | x/a | user/scanout-virtio-gpu/ |
ADR-014 |
| scanout-limine driver (fallback, not in default boot) | Done | x/a | user/scanout-limine/ |
ADR-014 |
| pong v0 (first-party app, default GUI boot module) | Done | x | user/pong/ |
ADR-011, ADR-012, ADR-014 |
| terminal-window v0 (boot splash → recede-to-watermark → identity-aware shell with ANSI SGR per-cell color) | Done | x | user/terminal-window/ |
ADR-011, ADR-022 |
worm v0 (first-party app, buildable; default GUI on aarch64 run-aarch64-gui + regression on x86_64) |
Done | x/a | user/worm/ |
ADR-011, ADR-012 |
| tree v0 (first-party app, buildable; retained for regression) | Done | x | user/tree/ |
ADR-011, ADR-012, ADR-014 |
| hello-window | Done, buildable; retained as protocol regression (replaced by tree → worm → pong as default GUI boot module) |
x | user/hello-window/ |
ADR-011, ADR-014 |
| libgui::FrameClock | Done | x/a/r (host-testable) | user/libgui/src/frame_clock.rs |
ADR-011 |
| libgui v0 (GUI client library) | Done | x/a/r (buildable; GUI only runs where scanout driver exists) | user/libgui/ |
ADR-011 |
| libinput-proto (wire format) | Done (Input-0) | x/a/r | user/libinput-proto/ |
ADR-012 |
| virtio-input driver | Done (Input-1) | x/a | user/virtio-input/ |
ADR-012 |
| USB host stack (xHCI) | In progress (Stream B B-vii) — CCID layer split out. usb-host now stays controller-only (enumeration, addressing, control + bulk transfers) and exposes a BULK_OUT / BULK_IN IPC ABI on endpoint 31. New user/ccid/ boot module on endpoint 33 frames PC_to_RDR_* / RDR_to_PC_* messages via the new cambios-ccid-proto wire-format crate. Boot smoke: ccid drives PC_to_RDR_GetSlotStatus → RDR_to_PC_SlotStatus through usb-host's IPC; QEMU usb-ccid reports ICC absent (no chardev backend). Next: B-viii PIV applet APDUs (needs a real smart card or chardev-backed CCID emulation; QEMU-only validation ends at B-vii). |
x/a/r (buildable; runtime detection requires -device qemu-xhci) |
user/usb-host/, user/ccid/, cambios-ccid-proto/, src/pci/mod.rs (prog_if + post-scan device enable) |
— |
| APIC + I/O APIC + SMP IPI | Done | x | src/arch/x86_64/ |
— |
| GIC v3 + ARM Generic Timer | Done | a | src/arch/aarch64/ |
— |
| PLIC + SBI timer + SBI IPI | Done | r | src/arch/riscv64/ |
ADR-013 |
| TLB shootdown | Done (x86 vector-IPI / ARM TLBI broadcast / RISC-V SBI IPI) | x/a/r | src/arch/*/tlb.rs |
— |
| Process lifecycle cleanup | Done (Phase 3.2d.ii; kernel stack free deferred) | x/a/r | src/syscalls/dispatcher.rs, src/process.rs |
— |
| USB boot tooling | Done (make img-usb + make usb DEVICE=...) |
x | Makefile |
— |
| Formal verification (Kani) | Started 2026-04-16. Live across 6 proof crates, 47 passing harnesses: BuddyAllocator::free reserved-prefix (1); ELF header parser (7; fixed 6 integer-overflow sites); FrameAllocator (10; fixed 2 overflow sites with saturating_add; reserve_region overflow covered by unit tests where CBMC's budget blew); CapabilityManager (12; Tier A ProcessCapabilities invariants + Tier B cross-process on a 3-slot manager); UserSlice validators (12; ADR-020 UserReadSlice/UserWriteSlice exhaustive over (addr, len) × CR3 state); DTB parser (5; fixed 2 attempt to add with overflow sites in be_u32_at/be_u64_at with checked_add). Walker proof (P-DTB-6) and ELF verify_binary cross-cutting proof both deferred — CBMC budget intractable; targeted by the planned Kani→Verus pivot. Compositor protocol parser deferred until scanout settles past Scanout-4.c. The gap-map between proven and aspirational claims is verification/CLAIMS.md. |
— | verification/{buddy,elf,frame,capability,userslice,dtb}-proofs/ |
ADR-000 § Divergence, verification/CLAIMS.md |
| AArch64 SMP timer on AP | Gap: PPI 30 not firing on second CPU under QEMU virt. Single-CPU works. |
a | — | — |
| DHCP client | Paused (pre-work in udp-stack; waiting on channel architecture consumer) |
— | partial in user/udp-stack/ |
— |
| DNS / TCP / Yggdrasil mesh / TLS / VFS / USB HID / DID resolution / identity revocation | Planned | — | — | identity.md, various ADRs |
| AI pre-exec analysis / behavioral anomaly detection / Win32 compat | Planned (post-v1) | — | — | CambiOS.md, ADR-016, ADR-017 |
Source: identity.md, FS-and-ID-design-plan.md.
| Phase | Goal | Status |
|---|---|---|
| 0 | Identity primitives in kernel + RAM ObjectStore (stamps identity on every IPC; every object has author + owner) | Done |
| 1 | Real cryptography: Blake3, Ed25519, signed ELF, key-store service | Done |
| 1B | YubiKey-derived bootstrap pubkey compiled into kernel | Done |
| 1C | Key-store degraded mode + signed ObjectStore puts + identity gate (no unsigned fallback) | Done |
| 2A | First user-space hardware driver (virtio-net) | Done |
| 2B | First user-space network service (UDP/IP + NTP demo) | Done |
| 3 | Architecture substrate: revocation (3.1), CreateProcess cap (3.2b), ProcessId generation counters (3.2c), channels (3.2d), audit (3.3), policy service (3.4b) | Done |
| 4 | Persistent storage: virtio-blk + disk ObjectStore + arcobj CLI |
Done |
| 5 | Identity-routed Yggdrasil networking | Planned |
| 6 | Biometric commitment + key recovery | Planned (post-v1) |
| 7 | SSB bridge | Planned (post-v1) |
Interactive, network-capable, identity-rooted OS running on real hardware with persistent storage. Items are dependency-ordered. Blocker = bare-metal hardware bring-up.
| # | Item | Status |
|---|---|---|
| 1 | Shell | Done |
| 2 | USB boot tooling | Done (untested on target hardware) |
| 3 | Intel I219-LM NIC driver | Scaffolded (untested on target hardware) |
| 4 | DHCP client | Paused |
| 5 | DNS resolver | Planned |
| 6 | TCP stack | Planned |
| 7 | Virtio-blk driver | Done |
| 8 | Persistent ObjectStore | Done |
| 9 | arcobj CLI |
Done |
| 10 | Yggdrasil peer service | Planned |
Parity-target with x86_64 / AArch64. All phases landed as of 2026-04-19. Source: ADR-013.
| Phase | Goal | Status |
|---|---|---|
| R-0 | Build infra + tri-arch gate | Done (2026-04-15) |
| R-1 | First serial output, kmain_riscv64 banner |
Done (2026-04-16) |
| R-2 | Sv48 higher-half, DTB parser, frame allocator + heap | Done (2026-04-16) |
| R-3 | Trap vector, SBI timer, PLIC, context switch, 100 Hz preemption | Done (2026-04-18) |
| R-4 | U-mode transition via sscratch/tp swap, ELF EM_RISCV |
Done (2026-04-18) |
| R-5 | SMP (SBI HSM), cross-hart TLB shootdown (SBI IPI) | Done (2026-04-18/19) |
| R-6 | Service parity: virtio-mmio transport, -initrd signed modules, 5 boot services |
Done (2026-04-19) |
Total: 561 on x86_64-apple-darwin. Run RUST_MIN_STACK=8388608 cargo test --lib --target x86_64-apple-darwin, or make stats for the current number.
Major categories (approximate; breakdown drifts faster than the total):
| Area | Tests |
|---|---|
| Scheduler | 35 |
| Capability manager | 40 |
| IPC (interceptor, sender_principal, sync channel) | 17 |
| Channel manager | 29 |
| Process lifecycle cleanup | 3 |
| ELF verifier (incl. signed binary) | 14 |
| ObjectStore types + crypto | 21 |
| RamObjectStore | 12 |
| BlockDevice abstraction | 11 |
| DiskObjectStore (incl. reboot preservation) | 30 |
| Memory subsystem (buddy, frame, heap, paging, contiguous) | ~37 |
| Tier configuration | 16 |
| Kernel object table region | 5 |
| Audit (staging + events + ring/drain) | 44 |
| Syscall dispatcher (Cuts 1/2/3a) | 40 |
| Syscalls user_slice (ADR-020 Phase A) | 26 |
| Boot adapter (BootInfo + initrd parser) | 8 |
| PCI virtio-modern caps | 11 |
| AArch64 portable logic | 12 |
| Timer, ProcessTable, VMA tracker, syscall args, other | ~127 |
User-space crates have their own host tests: libgui v0 ships 26 (drawing primitives + TileGrid + font coverage); libinput-proto ships 8 (wire format, round-trips, signature preservation); libgui-proto ships 13 (including input_event_roundtrip). Run cargo test --lib --target x86_64-apple-darwin from each crate directory.
- AArch64 SMP timer on AP: PPI 30 not firing on second CPU under QEMU
virt. Single-CPU works fully. Likely QEMU config or missing GIC redistributor step on the AP path. Investigation pending. - AArch64 device IRQ routing: GIC
enable_spi/set_spi_triggerexist but are not called from the boot path orhandle_wait_irq. No device IRQs on aarch64 today. Revisit when: first aarch64 path needs device IRQs (likely a polling→IRQ-driven transition in virtio-blk, or resolution of the AP-timer gap enabling PL011 RX to drive a consumer). - ELF loader overlapping-segment permissions: If two PT_LOAD segments share a page with different permissions, the first segment's permissions win. Worked around in user-space linker scripts via
ALIGN(4096)before.data. - Kernel stack not freed on process exit:
handle_exitnow performs full lifecycle cleanup (Phase 3.2d.ii), but the 32 KiB kernel stack per task remains a bounded leak — can't free the stack you're running on. Requires scheduler-level deferred-dealloc. Bounded bynum_slots × 32 KiB(~6.4 MiB worst case). - Clippy warnings (~125): ~67
multiple_unsafe_ops_per_blockin arch code, ~25 missing// SAFETY:, ~12static_mut_refs(Rust 2024 migration — IDT/GDT/TSS patterns needUnsafeCelloraddr_of!), ~20new_without_default. Dedicated pass scheduled beforestatic_mutdeprecation becomes a hard error. - Pre-existing driver warnings in
user/i219-net/:dead_code/unused_importsfrom scaffolded state. Not correctness issues; clean up on next real-hardware bring-up. - Virtio-net TX on QEMU TCG: QEMU defers virtio TX to its event loop, which runs during guest
hlt. The UDP stack's ARP retry/timeout logic doesn't yet exploit this fully.
- CambiOS.md — source-of-truth architecture document
- identity.md — identity architecture (Phases 0-7 defined here)
- FS-and-ID-design-plan.md — storage + identity decisions
- SECURITY.md — enforcement status (security subset)
- GOVERNANCE.md — governance, deployment tiers, scope
- ASSUMPTIONS.md — catalog of numeric bounds (SCAFFOLDING / ARCHITECTURAL / HARDWARE / TUNING)
- README.md — public-facing summary
- SCHEDULER.md — scheduler implementation reference
- docs/adr/INDEX.md — architecture decision records (000-027, auto-generated)
- verification/CLAIMS.md — gap-map of proven vs aspirational verification claims
- CLAUDE.md — kernel technical reference + required-reading map