Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Roadmap

Each row is one loop unit: one milestone, one branch, one GitHub PR. Do not stack a later stage onto an unclosed earlier PR. Cite frozen FR/NFR IDs in the PR when touching behavior; do not invent new IDs in chat.

Primary ISA is AArch64 (ADR-003). M0/M1 probes are UART + qemu-system-aarch64, not VGA 0xb8000.

IDMilestoneProbe that closes itStatus
M0Kernel tree + harness scaffold on GitHubFiles on the default-target PR; ledger startedIn harness PRs #2/#3 (source). Merge is a human/MRC job.
M1QEMU virt boots UART “Hello World!”qemu-system-aarch64 serial shows the string; see honesty ledgerVerified in the 2026-09-08 cloud probe (not CI). x86 VGA probe is historical only.
M2Integration test harnessQEMU virt ARM semihosting exit + #[test_case]; scripts/qemu-smoke.sh fail-closedVerified in the 2026-09-08 cloud probe (not CI). Sponsor stacked this on the ISA PR.
M3Exception vectors + breakpointTest or QEMU serial proof the handler runsVerified: 2026-09-09 cloud qemu-smoke + GHA smoke.yml on the M3 PR (see honesty ledger).
M4Fatal exception stackFatal path does not silently lock the VMVerified: 2026-09-09 cloud qemu-smoke (see honesty ledger). GHA on the M4 PR branch still Unknown.
M5Hardware interrupts (GIC + timer)Timer tick observable (serial or test)Verified: 2026-09-09 cloud qemu-smoke + GHA smoke.yml on the M5 PR (see honesty ledger).
M6InputInjected PL011 RX byte observable on serial (or test)Verified: 2026-09-09 cloud qemu-smoke (see honesty ledger). GHA on the M6 PR branch still Unknown.
M7Paging + frame allocatorMap/unmap or allocator testVerified: 2026-09-09 cloud qemu-smoke (see honesty ledger). GHA on the M7 PR branch still Unknown.
M8Heap (alloc)Box/vec smoke on the heapVerified: 2026-09-09 cloud qemu-smoke + GHA smoke.yml on the M8 PR (see honesty ledger).
M9Cooperative schedulerTwo tasks observed to runVerified: 2026-09-09 cloud qemu-smoke + GHA smoke.yml (see honesty ledger).

M0–M9 are on main (M9 = merge of PR #15 / FR-11). Pillar work through ADR-020 (#17–#28) plus docs #30/#51/#29, A1–A6 (ADR-021–ADR-027) are on main. This PR is Track A / A7 (issue #38, parent issue #31): ADR-028 virtio-blk + FAT16. Merge is still a human/MRC job (ADR-002).

Pillars (post-M9)

Bring-up M0–M9 stays one loop unit each. After M9, work is grouped under the three pillars.

IDWorkProbe that closes itStatus
P-SEC-1Threat-model v1.1 slice (NFR-10)Read security.md; no “secure OS” claimVerified (file + review). v1.1 adds linker stacks, guards, EL0 first mile, remaining W^X gaps.
P-SEC-2W^X / NX heap + coop stacksPage-table PXN on heap + caught execute-from-heap IABORT (wx: ok)Verified: 2026-09-10 cloud qemu-smoke (see honesty ledger). Map: ADR-012. Linker stack pages still X.
P-SEC-2bLinker-stack guard pagesUnmapped 4 KiB holes; store faults (guard: ok)Verified: 2026-09-10 cloud qemu-smoke (see honesty ledger). ADR-014. Not kernel W^X.
P-PERF-1Baseline CNTPCT probe (NFR-07)Serial perf: cntpct and/or #[test_case]; not a published benchVerified: 2026-09-09 cloud qemu-smoke + GHA (see honesty ledger).
P-PERF-2IRQ-to-handler CNTPCT deltaSerial perf: irq-delta + samples max >= min; not a latency budgetVerified: 2026-09-10 cloud qemu-smoke (see honesty ledger).
P-PERF-3Host debug ELF size (NFR-08)Host marker perf: elf-size bytes=<n>; not a budgetVerified: 2026-09-10 cloud qemu-smoke host print (see honesty ledger).
P-SEC-3EL0 first mileel0: svc + el0: nx kernel + el0: okFirst mile Verified: 2026-09-10 cloud qemu-smoke (see honesty ledger).
P-SEC-2cRO+NX text/data (ADR-015)ro: nx data + ro: write fault + ro: okVerified: 2026-09-11 cloud qemu-smoke (see honesty ledger). Identity image W^X on virt; not “secure OS.”
P-PERF-4Boot-to-ready CNTPCT (NFR-08)perf: boot-delta ticks=<n>; not a budgetVerified: 2026-09-11 cloud qemu-smoke (see honesty ledger).
P-PERF-5A9 slot-disconnect CNTPCT pair (ADR-046)perf: app-load + perf: embed-load + perf: slot-delta app=<a> embed=<b>; not a percentVerified when this tip’s qemu-smoke prints the pair (see honesty ledger). QEMU TCG lab. Production slot stays FAT-only.
P-PERF-6FAT16 vs memfs write CNTPCT pair (ADR-051)perf: fat-write + perf: memfs-write + perf: fs-write-delta fat=<a> memfs=<b>; not a percentVerified when this tip’s qemu-smoke prints the pair (see honesty ledger). QEMU TCG lab. Keep fat: write / fat: ok.
P-PERF-7FAT16 vs memfs read CNTPCT pair (ADR-065)perf: fat-read + perf: memfs-read + perf: fs-read-delta fat=<a> memfs=<b>; not a percentVerified when this tip’s qemu-smoke prints the pair (see honesty ledger). QEMU TCG lab. Keep fat: read / fat: ok / ADR-051 write pair.
P-PERF-8Net-ping path CNTPCT (ADR-069)perf: net-ping ticks=<n>; smoke greps prefix only; not a percentVerified when this tip’s qemu-smoke prints the prefix (see honesty ledger). QEMU TCG lab. Keep N1/N2/N4.
P-PERF-9UDP DNS path CNTPCT (ADR-072)perf: udp-dns ticks=<n>; smoke greps prefix only; not a percentVerified when this tip’s qemu-smoke prints the prefix (see honesty ledger). QEMU TCG lab. Keep N1/N2/N3/N3.x/N4 + ADR-069.
P-PERF-10Thin TCP echo path CNTPCT (ADR-078)perf: tcp-echo ticks=<n>; smoke greps prefix only; not a percentVerified when this tip’s qemu-smoke prints the prefix (see honesty ledger). QEMU TCG lab. Keep N1–N5 / N5.x + ADR-069/072.
P-SEC-3bUser TTBR0 + EL0 cannot read kernel .datael0: no kernel read; user table omits .dataVerified: 2026-09-11 cloud qemu-smoke (see honesty ledger). Isolation / PAN stay Planned.
P-SEC-3cASID-tagged TLB isolationasid: dual + asid: conflict + asid: ok; no TLBI VMALLE1 on the switchVerified: 2026-09-11 cloud qemu-smoke (see honesty ledger). Umbrella isolation / PAN stay Planned.
P-SEC-3dStanding EL0 contextel0: standing + el0: restored; is_active() true only while standingVerified: 2026-09-11 cloud qemu-smoke (see honesty ledger). Not POSIX. Default ERET clears IRQ mask (ADR-041).
P-SEC-3eTTBR1 kernel-private page (ADR-016 first cut)ttbr1: el1 + ttbr1: no el0 + ttbr1: okVerified: 2026-09-11 cloud qemu-smoke (see honesty ledger).
P-SEC-3fEL1 fetch from TTBR1 high VA (ADR-017)ttbr1: el1 exec + ttbr1: vbar + existing ttbr1: okVerified: 2026-09-11 cloud qemu-smoke (see honesty ledger). Identity boot stub stays.
P-SEC-3gIdentity-tear first cut (ADR-018)ident: split + ident: fault + ident: high + ident: no el0 + ident: okVerified: 2026-09-11 cloud qemu-smoke (see honesty ledger). Full identity teardown / PAN / umbrella isolation were Planned at this mile (umbrella: P-SEC-3l). Do not claim “the kernel moved.”
P-SEC-3hHigh-VA jump + 16 KiB identity text range (ADR-019)ident: jump + ident: range + ident: text + existing ident: okVerified: 2026-09-11 cloud qemu-smoke + arm64 workstation Docker on 24d94e6 (see honesty ledger). Do not claim “the kernel moved.”
P-SEC-3iHigh-VA vtable rewrite + live identity .text tear (ADR-020)ident: reloc + ident: live + existing ident: ok; println! after the tearVerified: 2026-09-11 cloud qemu-smoke + arm64 workstation Docker on e80dc93 + GHA merge-commit 34651404108 (see honesty ledger). .rodata / .data / heap stay. Do not claim “the kernel moved.”
P-SEC-3jIdentity .rodata / .data / heap tear.rodata + .data/stacks + heap unmapped + high-only access..rodata Verified (ADR-025). .data/stacks Verified (ADR-037). Heap Verified (ADR-038) on this branch qemu-smoke (ident: heap-reloc / ident: heap / ident: heap-fault / ident: heap-high; heap-stay gone). Do not claim “the kernel moved.”
P-SEC-3kPAN enable on virtID_AA64MMFR1_EL1.PAN != 0 and an EL1-vs-EL0 access faultVerified (ADR-080 / #125 mile 2): default -cpu cortex-a76, pan: present + pan: enabled + pan: el1-fault. Historical a57 pan: absent (ADR-026 / ADR-054 / ADR-079). One mile; alone it is not the ADR-091 umbrella claim.
P-SEC-3mEL0 entry without TLBI VMALLE1 (ADR-039)el0: no-vmalle1; src/exception.rs has no tlbi vmalle1Verified: 2026-09-12 agent-box qemu-smoke (see honesty ledger). One mile; alone it is not the ADR-091 umbrella claim. PAN enable was a non-goal on the then-default a57 (enabled on a76 since ADR-080); umbrella: P-SEC-3l.
P-SEC-3nLower-EL IRQ while standing (ADR-040)el0: irq; #[test_case] lower_el_irq_while_standingVerified when this tip’s qemu-smoke prints el0: irq (see honesty ledger). FIQ/SError still park. One mile; alone it is not the ADR-091 umbrella claim.
P-SEC-3oIRQ-unmasked default standing/task ERET (ADR-041)el0: irq-default; #[test_case] lower_el_irq_default_eretVerified when this tip’s qemu-smoke prints el0: irq-default (see honesty ledger). Short non-standing probes stay masked. FIQ/SError still park. One mile; alone it is not the ADR-091 umbrella claim.
P-SEC-3pIdentity _start stay honesty (ADR-042 / ADR-047)ident: start-stay; #[test_case] identity_boot_stub_stays_while_live_tornVerified honesty. Never yank _start. One mile; alone it is not the ADR-091 umbrella claim.
P-SEC-3sLeftover identity RAM tear (ADR-049)ident: ram / ident: ram-fault / ident: ram-high; reject ident: ram-stayVerified on this branch when smoke passes. Optional mile from ADR-047. One mile; alone it is not the ADR-091 umbrella claim. Not “kernel moved.”
P-SEC-3qLower-EL FIQ while standing + SError park (ADR-043)el0: fiq + el0: serror-park; #[test_case] lower_el_fiq_while_standingVerified (FIQ taken + park honesty). Taken SError = deferred/non-goal (ADR-047). One mile; alone it is not the ADR-091 umbrella claim.
P-SEC-3rTaken lower-EL SError QMP attempt (ADR-045) / hard-stop (ADR-053) / reopen (ADR-081) / B1 pin (ADR-083) / B2 spike (ADR-084) / B2-P KVM (ADR-085)Guest A-clear path + el0: serror-arm + QMP inject-nmi log; el0: serror-park if not taken; bare el0: serror under opt-in pinStock virt TCG: deferred / non-goal (hard-stopped) (ADR-053 / ADR-081 / ADR-047); park Verified; do not require el0: serror on default smoke. B1: Verified (opt-in pin only) — ADR-083 pinned QEMU TYPE_NMI→SError, GHA job qemu-nmi-pin (CTOS_BUILD_QEMU_NMI=1). B2 (different runner/accelerator): Planned / blocked — ADR-084 2026-09-25 free-runner spike: no arm64 KVM/HVF/WHPX on any free GitHub-hosted runner (runs 36193423604 / 36193613972); needs sponsor choice (self-hosted arm64 KVM, paid bare metal, or wait). B2-P: Verified (opt-in, one-off paid run) — ADR-085 2026-09-26: AWS Graviton3 c7g.metal, QEMU -accel kvm + 0002 KVM_SET_VCPU_EVENTS serror_pending → bare el0: serror + b2: taken (fail-closed smoke PASS, run 4). Not a CI gate. Also fixed TCR_EL1.TG1 (reserved → 4K). Evidence class (D1): ADR-090 2026-09-26: B1 pin job made unconditional (every push/PR; a skipped job would pass a required check) + B2-P run 4 = the umbrella’s taken-SError evidence. Stock TCG hard-stop unchanged. One mile; alone it is not the ADR-091 umbrella claim.
P-SEC-3lUmbrella EL0 isolationStanding + PAN + full TTBR1 / identity teardownVerified (scoped: the accepted ADR-091 sentence only; M6, 2026-09-28). History: was Planned / non-claim until checklist (ADR-055 / ADR-047 / sponsor closure ADR-060). Constraints: PAN enable Verified separately (ADR-080) but not the umbrella; _start stays; taken SError hard-stopped (ADR-081). Specific miles are not this row. 2026-09-26 audit ADR-086: all ADR-055 §A miles Verified this session; §B not Met (taken SError only opt-in B1/B2-P; five identity ranges remain in kernel TTBR0 incl. the _start stub; no umbrella accept). Milestones M1 (inventory ratchet + RAM-side tears) → M2 (MMIO high alias) → M3 (stub policy, D2) → M4 (SError evidence class, D1) → M5 (accept, D4) → M6 (flip). M1 done (ADR-087): I2/I4/I5 torn from kernel + user TTBR0; fail-closed ident: inv walk allows only {MMIO block, _start stub}; planted identity page caught (ident: inv-neg, inv-leak-probe). Sponsor D1–D5 answered 2026-09-26 ~14:35 CEST (D4 accept still pending the sponsor reading the draft). M2 done (ADR-088): GIC/PL011/virtio via TTBR1 Device blocks; identity MMIO block torn; inventory k=1 u=1 a=1 = _start stub only (ident: inv-ok allow=stub). M3 (ADR-089): sponsor D2: _start stub page = the one documented identity exception; checklist identity row reworded and Met (ADR-087/088 evidence). M4 (ADR-090): sponsor D1: taken-SError evidence class = B1 qemu-nmi-pin (now unconditional) + B2-P run 4; checklist row 1 reworded and Met on that class. M5 (ADR-091, Draft): proposed umbrella sentence + scope, pending the sponsor’s written accept (B3 not Met); M6 flip not started. ADR-092 (2026-09-27, sponsor option (b)): G1 EL0-reachability walk (k/u/ASID-B TTBR0 + TTBR1, allowlist = five user slots, fail-closed + leak build) and G2 EL0 write permission fault closed; new gap G4 (syscall copy helpers skip the EL0 permission check); ADR-091 revision 2 sentence back with the sponsor (B3 not Met). ADR-094 (2026-09-27): G4 closed; ADR-091 revision 3. ADR-095 (2026-09-28): G3 KVM re-check PASS. M6 (2026-09-28): sponsor’s written accept (B3, 16:41 CEST); ADR-091 Accepted; row flipped. Say “EL0 isolated” only as the ADR-091 sentence, with its limits (one core, the TCG default smoke machine; not a speculative-execution or side-channel claim, not a real-hardware claim, not a certification; app text is EL0 execute-only; EL1 can still read it (no FEAT_EPAN); no multi-core race story).

Hub: pillars.md. ABI contract: syscall.md.

Track A — freestanding app hosting (#31)

A1 is the SVC ABI mile. A2 is the CRT / libctos mile. A3 is the guest ELF PT_LOAD loader mile. A4 is standing EL0 as normal mode for a loaded image. A5 is isolation completion (identity .rodata / .data / heap tears + EL0 entry without VMALLE1 + PAN ID-field; PAN enable was a non-goal on the then-default a57 per ADR-047, enabled on a76 since ADR-080). A6 is thin VFS + in-RAM memfs. A7 is virtio-blk + FAT16. A8 is documented sample rebuild recipes (no new runtime). A9 is the OS/app slot first cut plus leftover cross-update / embed-off (ADR-032). Track A children A1–A9 have a first cut; sample catalog deepened with fs-libctos (ADR-059), fat-libctos (ADR-061), and yield-libctos (ADR-062); product “app hosting is done” is Verified under ADR-048 criteria Met×5 (ADR-052). Not Linux containers. Not glibc. One child issue → one PR. Do not round A1–A9 miles alone into Linux/POSIX claims.

IDWorkProbe that closes itStatus
A1Stable SVC ABI + docs (#32, ADR-021)svc: yield + svc: user-hi + svc: uart + svc: exit + svc: ok; #[test_case]ABI mile Verified: 2026-09-11 cloud qemu-smoke on 8846bc5 (onto aa46219 / #29). App hosting stays Planned.
A2Freestanding CRT / libctos (#33, ADR-022)libctos: hi + libctos: ok + libctos: linked; #[test_case]CRT mile Verified: 2026-09-12 cloud qemu-smoke on c9b292b. App hosting stays Planned.
A3ELF (or raw image) loader into user TTBR0 (#34, ADR-023)loader: mapped + loader: ok; payload libctos: hi / libctos: ok; #[test_case]Loader mile Verified: 2026-09-12 cloud qemu-smoke (see honesty ledger). Not a Linux ABI. App hosting stays Planned.
A4Standing EL0 as normal mode (#35, ADR-024)el0: task-enter + el0: task-active + el0: task-exit + el0: task-restored + el0: restore-fail + el0: task-ok; #[test_case]Standing-task mile Verified: 2026-09-12 cloud qemu-smoke (see honesty ledger). Not isolation. App hosting stays Planned.
A5Isolation completion (#36, ADR-025 / ADR-026 / ADR-032 / ADR-037 / ADR-038 / ADR-039 / ADR-040 / ADR-041 / ADR-042 / ADR-043 / ADR-044 / ADR-045 / ADR-047 / ADR-049 / ADR-053 / ADR-054 / ADR-055 / ADR-060 / ADR-079 / ADR-080 / ADR-081 / #125)ident: rodata + ident: data + ident: heap + ident: ram; el0: no-vmalle1; el0: irq + el0: irq-default + el0: fiq + el0: serror-park; pan: id= + pan: present + pan: enabled + pan: el1-fault (cortex-a76)Prior A5 + PAN enable (ADR-079/080). Locks: taken SError still hard-stopped after ADR-081 re-probe (ADR-053 / ADR-081 / ADR-082); umbrella: P-SEC-3l (ADR-055); never yank _start. One mile; alone it is not the ADR-091 umbrella claim.
A6Thin VFS + memfs (#37, ADR-027)fs: create + fs: write + fs: read + fs: el0 + fs: ok; #[test_case]memfs mile Verified (see honesty ledger). Not POSIX. App hosting stays Planned.
A7virtio-blk + FAT16 (#38, ADR-028)blk: virtio + blk: cap + blk: rw + blk: ok; fat: mount + fat: read + fat: ok; #[test_case]block + FAT mile Verified when this tip’s qemu-smoke passes (see honesty ledger). Same VFS open. Not POSIX. Not FAT32. App hosting stays Planned.
—FAT16 write depth (Future slice 3, ADR-050)fat: write + fat: rewrite + fat: create + host --check-write; keep fat: ok / slot: okVerified when this tip’s qemu-smoke passes (see honesty ledger). Not POSIX. Not FAT32. App hosting stays Planned.
—FAT vs memfs write CNTPCT (Future slice 4, ADR-051 / P-PERF-6)perf: fat-write + perf: memfs-write + perf: fs-write-delta; keep fat: ok / slot: okVerified when this tip’s qemu-smoke prints the pair (see honesty ledger). Not a bench. Not a percent. App hosting stays Planned.
—FAT vs memfs read CNTPCT (perf slice 3, ADR-065 / P-PERF-7)perf: fat-read + perf: memfs-read + perf: fs-read-delta; keep fat: ok / write pair / slot: okVerified when this tip’s qemu-smoke prints the pair (see honesty ledger). Not a bench. Not a percent. App hosting stays Planned.
—Net-ping CNTPCT (perf slice, ADR-069 / P-PERF-8)perf: net-ping ticks=<n>; prefix grep; keep N1/N2/N4Verified when this tip’s qemu-smoke prints the prefix (see honesty ledger). Not a bench. Not a percent. N3 UDP unlocked by ADR-070 (not BSD sockets).
—UDP DNS CNTPCT (perf slice, ADR-072 / P-PERF-9)perf: udp-dns ticks=<n>; prefix grep; keep N1/N2/N3/N3.x/N4 + ADR-069Verified when this tip’s qemu-smoke prints the prefix (see honesty ledger). Not a bench. Not a percent. Not TCP.
—Thin TCP echo CNTPCT (perf slice, ADR-078 / P-PERF-10)perf: tcp-echo ticks=<n>; prefix grep; keep N1–N5 / N5.x + ADR-069/072Verified when this tip’s qemu-smoke prints the prefix (see honesty ledger). Not a bench. Not a percent. Not sockets. EL0 surface (not kernel N5 timer).
—FAT16 mkdir depth (ADR-073 / sponsor mile 2)fat: mkdir; keep fat: ok / write / readdir / delete / grow / slot: okVerified when this tip’s qemu-smoke passes (see honesty ledger). Not POSIX mkdir. Not a directory tree. Not TCP (mile 3).
—Thin TCP (ADR-074 / N5 / sponsor mile 3)net: tcp-ok (+ tcp-syn/tcp-est/tcp-tx/tcp-rx); guestfwd 10.0.2.4:7; keep N1–N3 + blk/FATVerified when this tip’s qemu-smoke prints net: tcp-ok (see honesty ledger). Not BSD sockets. Not listen/accept. Not TLS/HTTP.
—FAT16 readdir depth (ADR-056)fat: readdir + fat: entries; keep fat: ok / write / slot: okVerified when this tip’s qemu-smoke passes (see honesty ledger). Not POSIX getdents. Not FAT32. Not Linux/containers.
—FAT16 delete depth (ADR-057)fat: delete; keep fat: ok / write / readdir / slot: okVerified when this tip’s qemu-smoke passes (see honesty ledger). Not POSIX unlink. Not FAT32. Not Linux/containers.
—VFS prefix mounts (ADR-058)vfs: mount + vfs: mounts; keep fs: ok / fat: ok / slot: okVerified when this tip’s qemu-smoke passes (see honesty ledger). Not Linux mount(2). Not a new disk FS.
A8Documented sample apps (#39)recipes cite only existing serial markers; docs-buildRecipes Verified (docs; smoke markers unchanged). Hub: what-can-run.md. No new ADR. Not app hosting.
A9OS–app slots (#48, ADR-030 / ADR-032)host OS ELF + hello-libctos.elf; FAT /hello; slot: ok; same ELF on this OS and ba6541cFirst cut + leftover when this tip’s qemu-smoke prints cross-update lines (see honesty ledger). A2–A4 load FAT (no embed). Product claim Verified under ADR-048/052 (this mile alone ≠ Linux hosting).
—Freestanding fs-libctos catalog (ADR-059)libctos: fs-ok + fsdemo: ok; keep slot: ok / /helloVerified when this tip’s qemu-smoke passes (see honesty ledger). Memfs via ADR-058 /mem. Not POSIX. Not a reopen of ADR-048/052.
—Freestanding fat-libctos catalog (ADR-061)libctos: fat-ok + fatdemo: ok; keep /hello / /fsdemoVerified when this tip’s qemu-smoke passes (see honesty ledger). FAT /probe via thin VFS. Not POSIX. Not a reopen of ADR-048/052.
—Freestanding yield-libctos catalog (ADR-062)libctos: yld-ok + ≥3× libctos: beat + yldemo: ok; keep prior threeVerified when this tip’s qemu-smoke passes (see honesty ledger). Cooperative yield rounds. Not preemption. Not a reopen of ADR-048/052.
—FAT16 nested mkdir + empty rmdir (ADR-077)fat: nested + fat: rmdir; keep fat: mkdir / grow / delete / net / samplesVerified when this tip’s qemu-smoke passes (see honesty ledger). Not POSIX. One nest level only. No new SVC. Not TCP CNTPCT.
—Freestanding mkdir-libctos catalog (ADR-075)libctos: mkdir-ok + mkdemo: ok; keep fat: mkdir / prior sixVerified when this tip’s qemu-smoke passes (see honesty ledger). EL0 fs_mkdir (27). Not POSIX. Not nested trees. Not EL0 TCP.
—Freestanding tcp-libctos catalog (ADR-076)libctos: tcp-ok + tcpdemo: ok; keep net: tcp-ok / prior sevenVerified when this tip’s qemu-smoke passes (see honesty ledger). EL0 net_tcp_echo (28). Not BSD sockets. Not listen/accept.

On-disk filesystem work started as A7 (FAT16 read, not xv6-like). FAT16 write depth is ADR-050. FAT16 root listing is ADR-056. FAT16 root delete is ADR-057. FAT16 root mkdir is ADR-073. Nested mkdir + empty rmdir is ADR-077. EL0 fs_mkdir is ADR-075. EL0 net_tcp_echo is ADR-076. Thin VFS prefix mounts are ADR-058. Freestanding catalog samples on the same volume: ADR-059 / ADR-061 / ADR-062 / ADR-068 / ADR-071 / ADR-075 / ADR-076. See Filesystem: new vs extend.

Tracks (subordinate to principles)

Track A (freestanding apps, #31), Track B (Linux-compat research, #40), and Track N (network foundation, ADR-063) do not override principles.md. A9 is after Track A ABI/loader. Track B B1: Linux-compat subset research frame (ADR-031) — not claiming Linux userspace yet. Track B B2: Linux AArch64 vs ctos SVC gap map (linux-aarch64-syscall-gap.md) — inspection only; no Linux numbers in src/. Track B B3: standing EL0 stays the ctos process model (ADR-035) — Linux clone/execve/wait4 is a gap; do not add those syscalls. Track B B4: Linux ELF / auxv / PT_INTERP vs the freestanding loader (ADR-033) — gap ADR; Track A loader stays reusable; not claiming dynamic Linux ELF. Track B B5: Linux VFS vs thin ctos VFS (ADR-034) — concept compare only; no POSIX flags / dentries. Track B B6: never Linux-compat implementation from this ladder (ADR-036). Track B B7: guest OCI/Docker is a non-goal (ADR-029).

Track N — network foundation (ADR-063)

Separate track from A/B. Hub: track-n.md. N0 scope: ADR-063. N1 first frame: ADR-066. N2 ICMP ping: ADR-067. N3 UDP transport: ADR-070. N3.x EL0 UDP SVC: ADR-071. N4 EL0 net sample: ADR-068. N5 thin TCP: ADR-074. Reuse virtio-mmio patterns from blk; do not break FAT/blk smoke. Still not product: BSD sockets, TCP stack as product / listen-accept, DHCP/DNS as product, Wi‑Fi, Linux net stack, “has networking / sockets OS” marketing.

IDWorkProbe that closes itStatus
N0Scope ADR + docs wiring (ADR-063)Docs-build; ledger Planned; no Verified inventAccepted (docs) — this PR
N1Link bring-up / first frame (virtio-net mmio, ADR-066)Discover + TX ARP + RX SLIRP gateway ARP reply; -netdev user,id=net0 -device virtio-net-device,netdev=net0; net: ok; keep blk/FAT greenVerified when this tip’s qemu-smoke prints net: ok
N2ARP + ICMP ping (kernel-path, ADR-067)After ARP: ICMP echo vs 10.0.2.2; net: icmp-tx / net: icmp-rx / net: ping-ok; QEMU args unchangedVerified when this tip’s qemu-smoke prints net: ping-ok
N3Minimal UDP transport (ADR-070)UDP DNS query/reply vs SLIRP 10.0.2.3:53; net: udp-tx / net: udp-rx / net: udp-ok; keep N1/N2Verified when this tip’s qemu-smoke prints net: udp-ok
N4Freestanding sample using net SVCs (ADR-068)libctos: net-ok / netdemo: ok; keep N1/N2/N3/samplesVerified when tip prints those markers
N3.xEL0 UDP DNS SVC + udpdemo (ADR-071)libctos: udp-ok / udpdemo: ok; keep N1/N2/N3/N4/samplesVerified when tip prints those markers
N5Thin TCP active-open + one payload (ADR-074)net: tcp-ok (+ syn/est/tx/rx); guestfwd 10.0.2.4:7; keep N1–N3Verified when tip prints net: tcp-ok

Docs website

mdBook + GitHub Pages (not a kernel milestone, not a new FR/NFR ID). https://ctos.artof.link HTTPS is Verified after #30 (deploy 34653046584 + HTTPS 200). Route 53 CNAME remains in place (zone <route53-zone-id>). Overview: what can run today. Publish notes: website.md.

Isolation leftovers (decided — ADR-047 / sponsor closure ADR-060)

  • Taken SError: deferred / non-goal (hard-stopped) on virt TCG (ADR-053 / ADR-081 / ADR-082). Re-probed 2026-09-19 on cortex-a76 — still machine does not provide NMIs. Unlock = ADR-081 B1/B2/B3; B1 research ADR-082, then B1 opt-in pin Verified (ADR-083, qemu-nmi-pin). B2 free-runner spike blocked (ADR-084, 2026-09-25: no arm64 KVM/HVF/WHPX on free hosted runners) — sponsor then chose B2-P: Verified (opt-in, one-off) on AWS Graviton3 under KVM (ADR-085, 2026-09-26). Park Verified; A-clear = dormant prep (ADR-045).
  • PAN: CPU reopen + enable Verified (ADR-079 / ADR-080; default -cpu cortex-a76). Historical a57 pan: absent.
  • Yank _start: never while QEMU -kernel needs 0x4008_0000. ident: start-stay Verified honesty. Leftover identity RAM after heap: Verified optional mile (ADR-049; not umbrella-required).
  • Umbrella “EL0 isolated”: Verified only as the accepted ADR-091 sentence (M6, 2026-09-28; revision 4 accepted 2026-10-02; checklist ADR-055 all Met). Limits: one core, the TCG default smoke machine; not a speculative-execution or side-channel claim, not a real-hardware claim, not a certification; app text is EL0 execute-only; EL1 can still read it (no FEAT_EPAN); no multi-core race story. Sponsor one-pager: ADR-060.
  • Product app hosting “done”: Verified under ADR-048 / ADR-052 (freestanding slots; not Linux/POSIX/containers).