ctos — Functional & Non-Functional Requirements
Learning/research AArch64 (arm64) Rust bare-metal kernel (not a general-purpose desktop OS).
ISA revision: ADR-003 (2026-09-08) replaced x86_64 / VGA / bootimage wording with AArch64 / UART / QEMU virt. IDs are unchanged. Sponsor authorized the text revision; do not mint new FR/NFR IDs here. The sponsor brief called this “ADR-002”; that number was already the identity-split ADR on the harness tip.
FR-06 stage note (2026-09-09): Stage moved Next → Now when M3 landed VBAR_EL1 + resumable BRK (ADR-004). ID unchanged.
FR-07 stage note (2026-09-09): Stage moved Next → Now when M4 landed the dedicated exception / fatal stacks (ADR-005). ID unchanged.
FR-08 stage note (2026-09-09): Stage moved Next → Now when M5 landed GICv2 + the EL1 physical timer (ADR-006). ID unchanged. FR-08 “later input” is M6 / ADR-007 (PL011 RX on virt). No new FR ID.
FR-09 stage note (2026-09-09): Stage moved Next → Now when M7 landed the EL1 identity map + bump frame allocator (ADR-008). ID unchanged. DTB parse remains staged (Unknown). Heap is M8 / FR-10.
FR-10 stage note (2026-09-09): Stage moved Next → Now when M8 landed GlobalAlloc on a first-fit heap backed by identity-mapped frames (ADR-009). ID unchanged. Growing / slab heaps remain later.
FR-11 stage note (2026-09-09): Stage moved Later → Now when M9 landed cooperative round-robin yield on EL1 (ADR-010). ID unchanged. Preemption / SMP remain later. A documented EL0 SVC ABI is ADR-021 / Track A A1 — not a new FR and not app hosting.
NFR-10 note (2026-09-17, ADR-078): EL0 net_tcp_echo quiet-path CNTPCT (perf: tcp-echo ticks=<n>, ADR-078). Threat-model v1.53. Measure-first only — not a latency SLA. Not BSD sockets. Not listen/accept. Keep net: tcp-ok / libctos: tcp-ok. IDs unchanged.
NFR-10 note (2026-09-17, ADR-077): FAT16 one-level nested mkdir + empty rmdir behind the thin VFS (fat: nested / fat: rmdir, ADR-077). Threat-model v1.52. Not POSIX mkdir/rmdir. Not arbitrary-depth trees. No new SVC. Not TCP CNTPCT. Keep fat: mkdir. IDs unchanged.
NFR-10 note (2026-09-17, ADR-075): EL0 fs_mkdir (SVC 27) + freestanding /mkdemo (libctos: mkdir-ok / mkdemo: ok, ADR-075). Threat-model v1.50. Not POSIX mkdir. Not a directory tree. Not EL0 TCP. Keep fat: mkdir. IDs unchanged.
NFR-10 note (2026-09-16, ADR-073): FAT16 root mkdir behind the thin VFS (fat: mkdir, ADR-073). Threat-model v1.48. Not POSIX mkdir. Not a directory tree. No new SVC this mile. Track N / TCP untouched. IDs unchanged.
NFR-10 note (2026-09-16, ADR-064): FAT16 multi-cluster grow behind the thin VFS (fat: grow / libctos: fat-grow, ADR-064). Threat-model v1.39. Not POSIX write API. Not exFAT. Track N untouched. IDs unchanged.
NFR pillars note (2026-09-09): ADR-011 revises NFR-05, NFR-07, and NFR-10 text in place (antifragility, performance, security as first-class pillars). IDs unchanged. Do not mint NFR-15+.
NFR-10 W^X note (2026-09-10): ADR-012 revises NFR-10 text in place for the heap / coop-stack NX cut. ADR-013 records EL0 direction; the first mile is enter/return + UXN fetch, not isolation. ADR-014 adds unmapped linker-stack guards. IDs unchanged.
NFR-10 / NFR-08 note (2026-09-11): ADR-015 revises NFR-10 text in place for the RO+NX text/data cut (SCTLR.WXN on). ADR-013 adds a user-TTBR0 read mile, an ASID-tagged TLB mile, and a standing EL0 context; ADR-016 adds a TTBR1 private-page first cut; ADR-017 adds EL1 fetch from the TTBR1 RAM alias; ADR-018 adds the first identity-tear cut (split tables + one torn text page); ADR-019 jumps the post-MMU continuation to high VA and unmaps a 16 KiB dedicated identity text range; ADR-020 rewrites rustc vtables to high aliases and unmaps live identity .text after the boot stub (.rodata/.data/heap stay). ADR-021 adds a documented EL0 SVC ABI (exit / uart_write / yield). ADR-022 adds a freestanding libctos CRT that wraps those numbers. ADR-023 adds a guest ELF64 PT_LOAD loader into user TTBR0. ADR-024 promotes standing EL0 so a loaded image runs until exit with fail-closed restore. Those are ABI + CRT + loader + standing-task miles, not app hosting. ADR-025 unmaps identity .rodata after a pointer rewrite (.data/heap stay). ADR-026 reads ID_AA64MMFR1_EL1.PAN on -cpu cortex-a57 (enable stays Planned). ADR-027 adds a thin VFS + in-RAM memfs (create / open / read / write / close; public SVC 19–23). ADR-028 adds virtio-mmio block + FAT16 behind that same VFS (/probe read). ADR-050 deepens FAT16 with guest write + small create. Those are memfs / block-FS miles, not POSIX and not app hosting. The umbrella isolation row stays Planned/non-claim (ADR-047). NFR-08 boot-to-ready CNTPCT is a measurement, not a budget. IDs unchanged.
Status legend: Now = hello-UART / QEMU virt / smoke sensors · Next = near roadmap · Later = aspirational.
Tracker is GitHub (gh). New IDs go through a GitHub issue plus an ADR/docs change — not chat.
Scope
In: freestanding no_std Rust, QEMU -kernel → _start, UART/earlycon output, exceptions/interrupts, paging, heap, basic multitasking, reproducible build/QEMU probes, docs-first harness (honesty, three pillars — antifragility / security / performance — second brain, thin multi-agent).
Out (for now): userspace processes, POSIX, networking stack, GPU, SMP, real-hardware certification, secure-boot productization, Raspberry Pi or other board bring-up (unprobed), x86_64 as a primary path.
IDs below are frozen. Do not invent new FR/NFR IDs in chat; add via issue + ADR/docs change.
Functional requirements
| ID | Requirement | Priority | Stage |
|---|---|---|---|
| FR-01 | Kernel builds as a freestanding no_std / no_main binary for a custom aarch64-*-none target. | Must | Now |
| FR-02 | QEMU (-kernel on virt) loads the kernel ELF and transfers control to a stable _start entry. | Must | Now |
| FR-03 | Kernel can write text to the virt PL011 UART (MMIO, or later earlycon) via print! / println!. Not VGA 0xb8000. | Must | Now |
| FR-04 | Panic handler prints a message (best-effort) and halts without unwinding. | Must | Now |
| FR-05 | Developer can produce a runnable AArch64 kernel ELF and boot it under qemu-system-aarch64 (-machine virt). | Must | Now |
| FR-06 | Synchronous exceptions are handled via VBAR_EL1 vectors (at least a breakpoint / fault path). | Must | Now |
| FR-07 | A fatal exception uses a dedicated stack so overflow does not silently lock the VM. | Must | Now |
| FR-08 | Hardware interrupts: timer via the virt GIC (M5). Input on QEMU virt is PL011 UART RX (M6). The x86-era keyboard wording is this UART path; virtio-keyboard remains later. | Should | Now |
| FR-09 | Kernel reads the firmware/QEMU memory map (DTB when probed) and establishes paging / virtual memory. M7: virt RAM convention + linker __kernel_end + EL1 identity map (ADR-008). DTB walk is staged. | Must | Now |
| FR-10 | GlobalAlloc heap so alloc types (Box, Vec) work in kernel. M8: first-fit list on a 64 KiB identity-mapped frame run (ADR-009). | Should | Now |
| FR-11 | Cooperative or simple round-robin task switching (threads or async tasks). M9: EL1 yield of AAPCS64 callee-saved GPRs; two heap-backed workers (ADR-010). | Should | Now |
| FR-12 | Serial remains usable for headless/CI logs (PL011 or extra earlycon), including later test-exit telemetry. | Should | Next |
| FR-13 | Integration tests that boot in QEMU virt and exit with a deterministic success/fail code (ARM semihosting SYS_EXIT, not x86 isa-debug-exit). | Must | Now |
| FR-14 | Documented milestone path (vision → architecture → ADR → roadmap) stays ahead of code for each stage. | Must | Now |
| FR-15 | Honesty ledger records each major capability as claim + probe + status (Verified / Unknown / Planned). | Must | Now |
NFR-10 note (2026-09-12): ADR-039 revises NFR-10 text in place for the EL0 trampoline without TLBI VMALLE1 cut (after ADR-037/038). Threat-model v1.19. IDs unchanged.
NFR-10 note (2026-09-13): ADR-040 revises NFR-10 text in place for taken lower-EL IRQ while standing. Threat-model v1.20. FIQ/SError lower-EL still park. IDs unchanged.
NFR-10 note (2026-09-13, ADR-041): ADR-041 revises NFR-10 text in place for IRQ-unmasked default standing/task ERET. Threat-model v1.21. Short non-standing trampoline probes stay masked. FIQ/SError lower-EL still park. IDs unchanged.
NFR-10 note (2026-09-13, ADR-049): ADR-049 revises NFR-10 text in place for leftover identity RAM tear (ident: ram / ident: ram-fault / ident: ram-high; ident: ram-stay superseded). Threat-model v1.27. Umbrella isolation / PAN enable / taken SError / yank _start stay decided as in ADR-047. IDs unchanged.
NFR-10 note (2026-09-13, ADR-042): ADR-042 revises NFR-10 text in place for the isolation leftover honesty wrap (ident: start-stay / ident: ram-stay). Threat-model v1.22. Umbrella isolation / PAN enable / FIQ-SError / full _start teardown stay Planned. IDs unchanged.
NFR-10 note (2026-09-13, ADR-043): ADR-043 revises NFR-10 text in place for taken lower-EL FIQ while standing (el0: fiq) and SError park honesty (el0: serror-park). Threat-model v1.23. Taken SError / PAN enable / umbrella isolation stay Planned. IDs unchanged.
NFR-10 note (2026-09-13, ADR-047 / ADR-048): ADR-047 decides isolation leftovers (taken SError deferred/non-goal on this smoke machine; PAN enable non-goal on default cortex-a57; never yank _start; leftover RAM optional Planned; umbrella Planned/non-claim). ADR-048 writes product app-hosting claim criteria (still Planned at that note). Threat-model v1.26. IDs unchanged.
NFR-10 note (2026-09-13, ADR-048 / ADR-052): Product app-hosting claim is Verified under ADR-048 criteria Met×5; sponsor accept recorded in ADR-052. Threat-model v1.29. Still not Linux/POSIX/containers/“EL0 isolated.” IDs unchanged.
NFR-10 note (2026-09-14, ADR-053 / ADR-054 / ADR-055): Isolation-gap locks — taken SError hard-stopped (ADR-053); PAN enable locked non-goal on default cortex-a57 (ADR-054); umbrella “EL0 isolated” non-claim until checklist (ADR-055). Threat-model v1.30. IDs unchanged.
NFR-10 note (2026-09-14, ADR-056): FAT16 root listing behind the thin VFS (fat: readdir / fat: entries, ADR-056). Threat-model v1.31. Not POSIX getdents. IDs unchanged.
NFR-10 note (2026-09-14, ADR-057): FAT16 root delete behind the thin VFS (fat: delete, ADR-057). Threat-model v1.32. Not POSIX unlink. IDs unchanged.
NFR-10 note (2026-09-14, ADR-058): Thin VFS prefix mounts (vfs: mount / vfs: mounts, ADR-058). Threat-model v1.33. Not POSIX mount(2). IDs unchanged.
NFR-10 note (2026-09-28, ADR-091 / M6): the sponsor accepted the ADR-091 revision-3 sentence and scope in writing (B3, 2026-09-28 16:41 CEST). Umbrella “EL0 isolated” (P-SEC-3l) is Verified, only as that sentence: one core, the TCG default smoke machine; not a speculative-execution or side-channel claim, not a real-hardware claim, not a certification; EL0 can read its own code bytes; no multi-core race story. Checklist ADR-055 all Met. Threat-model v1.70. Earlier notes that say the umbrella is Planned / non-claim are as of their dates. IDs unchanged.
NFR-10 note (2026-10-02, ADR-091 revision 4): the sponsor accepted ADR-091 revision 4 in writing (“I accept ADR-091 rev 4”). Only the PAN clause and the code-bytes limit changed: the limit is now “app text is EL0 execute-only; EL1 can still read it (no FEAT_EPAN)” (was “EL0 can read its own code bytes”). The umbrella “EL0 isolated” (P-SEC-3l) stays Verified, only as the revision-4 sentence in ADR-091. Threat-model v1.74. The 2026-09-28 note above records revision 3 as of its date. IDs unchanged.
Non-functional requirements
| ID | Requirement | Priority | Stage |
|---|---|---|---|
| NFR-01 Safety | Prefer safe Rust; unsafe only at hardware/FFI boundaries, minimized and justified. | Must | Now |
| NFR-02 Reproducibility | Toolchain pinned (rust-toolchain.toml); target JSON + .cargo/config.toml checked in. | Must | Now |
| NFR-03 Portability (dev) | Build+QEMU path works on Windows/macOS/Linux (host tools); kernel target remains freestanding AArch64. | Must | Now |
| NFR-04 CI / sensors | PR gate runs scripts/qemu-smoke.sh (build + UART hello string + cargo test exit codes). GitHub Actions + optional Docker. | Should | Now |
| NFR-05 Antifragility | First-class pillar (ADR-011). Repeated failures become ratchets (#[test_case], scripts/qemu-smoke.sh grep, Dockerfile pin, GHA) — not README-only fixes. Fail-closed sensors stay on the strongest layer. | Must | Now |
| NFR-06 Honesty | Status words in docs/PRs need a probe; unprobed stays Unknown; no self-merge as “verified.” | Must | Now |
| NFR-07 Performance | First-class pillar (ADR-011). Performance claims need a measurable probe (CNTPCT delta around a known path; IRQ-to-handler CNTPCT−CVAL min/max/spread). No fake benches and no “faster than X.” Optimize only after a probe shows a cost. Not a hard latency budget. | Should | Now |
| NFR-08 Footprint | Debug image size and boot time tracked once measurable; no premature optimization. | Could | Later |
| NFR-09 Maintainability | Clear module layout; ADRs for boot-path, console, or allocator choices. | Must | Now |
| NFR-10 Security | First-class pillar (ADR-011). No secrets in repo. Do not claim “secure OS” / “hardened” / “the kernel is W^X” without a written threat model and a probe. Prefer minimize unsafe (NFR-01). Heap and heap-backed cooperative stacks are PXN (ADR-012). Linker-stack downward overflow hits an unmapped 4 KiB guard (ADR-014). .text/.rodata are RO+X and .data/.bss/live linker stacks are RW+NX; SCTLR.WXN is on (ADR-015). That scoped image cut is not a “secure OS” sentence. Device MMIO XN. Least privilege on IRQ paths. EL0 first mile (enter/return + cannot execute kernel data), the user-TTBR0 read mile, the ASID-tagged TLB mile, and the standing EL0 context are probes (ADR-013). TTBR1 private-page first cut is a probe (ADR-016). EL1 fetch from the TTBR1 RAM alias (plus high VBAR_EL1) is a probe (ADR-017). The first identity-tear cut (split TTBR1 RAM tables + one unmapped identity text page) is a probe (ADR-018). A 16 KiB dedicated identity text range plus a high-VA continuation is a probe (ADR-019). A high-VA vtable / fn-pointer rewrite plus live identity .text tear after the boot stub is a probe (ADR-020); identity -kernel stub stays. An identity .rodata tear after a pointer rewrite is a probe (ADR-025); .data/heap stay; full identity teardown stays Planned. A PAN ID-field read on -cpu cortex-a57 is a probe (ADR-026); PAN enable stays Planned. A documented EL0 SVC ABI (exit / uart_write / yield) is a probe (ADR-021). A freestanding libctos CRT wrapping those numbers is a probe (ADR-022). A guest ELF64 PT_LOAD loader into user TTBR0 is a probe (ADR-023); not a Linux ABI. Standing EL0 as normal mode for a loaded image until exit (fail-closed restore) is a probe (ADR-024). A thin VFS + in-RAM memfs (create / open / read / write / close; SVC 19–23) is a probe (ADR-027); not POSIX (product freestanding hosting is Verified under ADR-048/052 separately). virtio-mmio block + FAT16 behind that same VFS (/probe read) is a probe (ADR-028); FAT16 write + small create is a probe (ADR-050); FAT16 root listing is a probe (ADR-056); FAT16 root delete is a probe (ADR-057); thin VFS prefix mounts are a probe (ADR-058); host -drive without guest code is not that probe. An OS-image vs app-payload slot first cut (published hello-libctos.elf + FAT /hello + A3 map) is a probe (ADR-030). A2–A4 load that FAT file (no hello include_bytes!); the same published ELF on this OS and prior ba6541c is a probe (ADR-032). Identity .data/stacks and heap are torn (ident: data / ident: heap, ADR-037 / ADR-038); standing/EL0 trampoline switches without TLBI VMALLE1 (el0: no-vmalle1, ADR-039); taken lower-EL IRQ while standing returns to EL0 (el0: irq, ADR-040); default standing/task ERET clears IRQ mask (el0: irq-default, ADR-041); taken lower-EL FIQ while standing (el0: fiq, ADR-043); SError park honesty (el0: serror-park, ADR-045 A-clear + QMP attempt); short non-standing trampoline probes stay masked; _start stays (ident: start-stay); leftover identity frames after the heap are torn (ident: ram*, ADR-049); taken SError is hard-stopped/deferred (ADR-053); PAN enable is locked non-goal on default cortex-a57 (ADR-054); never yank _start; umbrella “EL0 isolated” is Verified only as the accepted ADR-091 sentence since M6 (2026-09-28; checklist ADR-055 / ADR-047); product “app hosting is done” is Verified under ADR-048 / ADR-052 (freestanding slots; not Linux/POSIX/containers). Do not claim PAN on -cpu cortex-a57. | Must | Now |
| NFR-11 Observability | QEMU UART + explicit test exit codes are first telemetry; host Grafana out of scope. | Should | Next |
| NFR-12 Multi-agent | Thin roles (engineer / knowledge / coherence / MRC); implementer ≠ merge approver. | Should | Now |
| NFR-13 Document-first | Written milestone acceptance criteria match what code/CI actually prove. | Must | Now |
| NFR-14 Second brain | Session memory + daily briefs in git so agents inherit state without chat archaeology. | Should | Now |
Acceptance sketch (Now)
cargo buildsucceeds with pinned nightly foraarch64-ctos.json.qemu-system-aarch64 -machine virtshows the hello line on serial or honesty ledger says Unknown until probed.scripts/qemu-smoke.shfails closed if the hello string is missing orcargo testdoes not exit 0.cargo testuses ARM semihosting so QEMU exits 0 on pass and 1 on panic (force-fail).- Current-EL
BRKis handled viaVBAR_EL1(serial string and/or#[test_case]) or the honesty ledger says Unknown until probed. - Nested / fatal exception prints a serial marker from a dedicated stack (FR-07) or the honesty ledger says Unknown until probed.
- A timer tick is observable on serial and/or
#[test_case]via the virt GIC (FR-08 / M5) or the honesty ledger says Unknown until probed. - A received PL011 byte is observable on serial (FR-08 input / M6) or the honesty ledger says Unknown until probed.
- MMU-on + allocate-frame / map-unmap is observable on serial and/or
#[test_case](FR-09 / M7) or the honesty ledger says Unknown until probed. Box/Vecon the kernel heap is observable on serial and/or#[test_case](FR-10 / M8) or the honesty ledger says Unknown until probed.- Two cooperative tasks are observable on serial and/or
#[test_case](FR-11 / M9) or the honesty ledger says Unknown until probed. - A CNTPCT baseline delta is observable on serial and/or
#[test_case](NFR-07) or the honesty ledger says Unknown / Planned until probed. - An IRQ-to-handler CNTPCT delta (min/max/spread) is observable on serial and/or
#[test_case](NFR-07) or the honesty ledger says Unknown until probed. - Threat-model v1.1 exists under
docs/framework/security.md; “secure OS” stays unclaimed (NFR-10). - Heap NX / execute-from-heap caught is observable on serial and/or
#[test_case](NFR-10 / ADR-012) or the honesty ledger says Unknown until probed. - Linker-stack guard store faults observably (NFR-10 / ADR-014) or the honesty ledger says Unknown until probed.
- EL0 first mile (SVC return and/or UXN IABORT) is observable on serial and/or
#[test_case](NFR-10 / ADR-013) or the honesty ledger says Unknown / Planned until probed. - Host debug ELF size is printed by
scripts/qemu-smoke.sh(NFR-08) or the honesty ledger says Unknown until probed. - Boot-to-ready CNTPCT (
perf: boot-delta) is observable on serial and/or#[test_case](NFR-08) or the honesty ledger says Unknown until probed. - RO+NX text/data (execute-from-
.dataand write-to-RO-text) is observable on serial and/or#[test_case](NFR-10 / ADR-015) or the honesty ledger says Unknown until probed. - EL0 cannot-read-kernel-data (user TTBR0) is observable on serial and/or
#[test_case](NFR-10 / ADR-013) or the honesty ledger says Unknown / Planned until probed. - ASID isolation (dual ASID without
TLBI VMALLE1+ conflict/stale-entry probe) is observable on serial and/or#[test_case](NFR-10 / ADR-013) or the honesty ledger says Unknown / Planned until probed. - Standing EL0 (
el0: standing/el0: restored,is_active()flips) is observable on serial and/or#[test_case](NFR-10 / ADR-013) or the honesty ledger says Unknown / Planned until probed. - TTBR1 private page (
ttbr1: el1/ttbr1: no el0/ttbr1: ok) is observable on serial and/or#[test_case](NFR-10 / ADR-016) or the honesty ledger says Unknown / Planned until probed. - EL1 fetch from the TTBR1 RAM alias (
ttbr1: el1 exec/ttbr1: vbar) is observable on serial and/or#[test_case](NFR-10 / ADR-017) or the honesty ledger says Unknown / Planned until probed. Identity-kernelstub at0x40080000stays. - Identity-tear first cut (
ident: split/ident: fault/ident: high/ident: no el0/ident: ok) is observable on serial and/or#[test_case](NFR-10 / ADR-018) or the honesty ledger says Unknown / Planned until probed. High-VA continuation plus a 16 KiB dedicated identity text range (ident: jump/ident: range/ident: text) is observable on serial and/or#[test_case](NFR-10 / ADR-019) or the honesty ledger says Unknown / Planned until probed. High-VA vtable rewrite plus live identity.texttear (ident: reloc/ident: live) is observable on serial and/or#[test_case](NFR-10 / ADR-020) or the honesty ledger says Unknown / Planned until probed. Identity.rodatatear (ident: rodata/ident: rodata-fault/ident: rodata-high) is observable on serial and/or#[test_case](NFR-10 / ADR-025) or the honesty ledger says Unknown / Planned until probed. PAN ID field (pan: id=/pan: absent) is observable on serial and/or#[test_case](NFR-10 / ADR-026) or the honesty ledger says Unknown / Planned until probed. Identity.data/stacks tear (ident: data/ident: data-fault/ident: data-high) is observable (NFR-10 / ADR-037) or the honesty ledger says Unknown / Planned until probed. Identity heap tear (ident: heap-reloc/ident: heap/ident: heap-fault/ident: heap-high) is observable (NFR-10 / ADR-038) or the honesty ledger says Unknown / Planned until probed. EL0 entry withoutTLBI VMALLE1(el0: no-vmalle1) is observable (NFR-10 / ADR-039) or the honesty ledger says Unknown / Planned until probed. Lower-EL IRQ while standing (el0: irq) is observable (NFR-10 / ADR-040) or the honesty ledger says Unknown / Planned until probed. Lower-EL FIQ while standing (el0: fiq) and SError park honesty (el0: serror-park) are observable (NFR-10 / ADR-043 / ADR-045) or the honesty ledger says Unknown / Planned until probed. Yank_startdecided never; leftover identity RAM after the heap is torn (ADR-049). Taken lower-EL SError is deferred/non-goal on this smoke machine. PAN is enabled on default cortex-a76 (ADR-080; was a non-goal on the historical cortex-a57). Umbrella “EL0 isolated”: see the M6 note above (ADR-091 sentence only). Do not claim PAN. - EL0 SVC ABI (
svc: yield/svc: user-hi/svc: uart/svc: exit/svc: ok) is observable on serial and/or#[test_case](NFR-10 / ADR-021 / Track A A1) or the honesty ledger says Unknown / Planned until probed. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052). Not a Linux ABI. libctosCRT (libctos: hi/libctos: ok/libctos: linked) is observable on serial and/or#[test_case](NFR-10 / ADR-022 / Track A A2) or the honesty ledger says Unknown / Planned until probed. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052).- Guest ELF PT_LOAD loader (
loader: mapped/loader: ok) is observable on serial and/or#[test_case](NFR-10 / ADR-023 / Track A A3) or the honesty ledger says Unknown / Planned until probed. Not a Linux ABI. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052). - Standing EL0 as normal mode (
el0: task-enter/el0: task-active/el0: task-exit/el0: task-restored/el0: restore-fail/el0: task-ok) is observable on serial and/or#[test_case](NFR-10 / ADR-024 / Track A A4) or the honesty ledger says Unknown / Planned until probed. Not isolation. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052). - Thin VFS + memfs (
fs: create/fs: write/fs: read/fs: el0/fs: ok) is observable on serial and/or#[test_case](NFR-10 / ADR-027 / Track A A6) or the honesty ledger says Unknown / Planned until probed. Not POSIX. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052). - virtio-blk + FAT16 (
blk: virtio/blk: cap/blk: rw/blk: ok/fat: mount/fat: read/fat: ok) is observable on serial and/or#[test_case](NFR-10 / ADR-028 / Track A A7) or the honesty ledger says Unknown / Planned until probed. Same VFSopen. Not POSIX. Not FAT32. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052). - FAT16 write depth (
fat: write/fat: rewrite/fat: create/ host--check-write) is observable on serial and/or#[test_case](NFR-10 / ADR-050) or the honesty ledger says Unknown / Planned until probed. Same VFSwrite. Not POSIX. Not FAT32. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052). - FAT16 root readdir (
fat: readdir/fat: entries) is observable on serial and/or#[test_case](NFR-10 / ADR-056) or the honesty ledger says Unknown / Planned until probed. Same thin VFS. Not POSIXgetdents. Not FAT32. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052). - FAT16 root delete (
fat: delete) is observable on serial and/or#[test_case](NFR-10 / ADR-057) or the honesty ledger says Unknown / Planned until probed. Same thin VFS. Not POSIXunlink. Not FAT32. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052). - Thin VFS prefix mounts (
vfs: mount/vfs: mounts) are observable on serial and/or#[test_case](NFR-10 / ADR-058) or the honesty ledger says Unknown / Planned until probed. Same thin VFS. Not POSIXmount(2). Not a new disk FS. This mile alone ≠ the ADR-048 product claim (Verified separately under ADR-048/052). - Panic path compiles and is reachable in principle.
- This FR/NFR file + honesty ledger live under
docs/.
Traceability
Map roadmap milestones and PRs to FR/NFR IDs in PR descriptions when touching behavior.
Taken lower-EL SError on this smoke machine is deferred / non-goal (hard-stopped) (ADR-053 / ADR-047); research ADR-044; attempt ADR-045. Park honesty stays ADR-043. Product app hosting claim gate: ADR-048.