Every milestone has an exit criterion
Each step ends with a sentence a machine can check, not a feeling or a demo. The state of the ladder is the state of the project.
A ladder of exit criteria
Every milestone ends with a sentence a machine can check. No hand-waving, no “almost done”.
Kernel core
M0BootDone
Xen PVH handover, serial output, physical memory map.
Exit: Serial log contains "Rabbit: boot OK" and QEMU exits 33.
Verification: Headless QEMU with a serial assertion.
M1Exceptions and timersDone
GDT, TSS with an IST stack, IDT, recoverable exceptions, 8259 PIC, PIT.
Exit: Divide by zero prints "DIV0 RIP=..." and continues; 100 PIT ticks print "TICKS 100".
Verification: Golden serial log.
M2MemoryDone
Buddy allocator, size class heap, higher half kernel, direct map.
Exit: 10,000 allocate/free cycles without leaks or double frees; usable RAM matches -m.
Verification: Host unit tests plus an on target self test.
M2bDirect map onlyDone
The kernel reaches physical memory only through the direct map.
Exit: The same byte read before and after the switch.
Verification: On target self test.
M2cMetadata in its own memoryDone
Frame metadata carved out of the memory it describes, guests of 32 GiB.
Exit: A guest of 4 GiB boots, manages its memory and runs the workload.
Verification: QEMU with -m 4G.
M3ThreadsDone
Kernel threads, preemptive round robin scheduler, interrupt safe locks.
Exit: 10 threads make progress under preemption with fair scheduling.
Verification: On target self test.
Userspace
M4UserspaceDone
Ring 3, SYSCALL/SYSRET, ELF64 loader, 59 Linux system calls.
Exit: A statically linked hello prints and exits 0; the system calls return the same values as Linux.
Verification: Golden log plus a diff against mainline.
M4bA real userlandDone
A standard library program running unmodified.
Exit: A standard library program runs unmodified, prints and exits 0.
Verification: Golden log.
M4cDemand pagingDone
Demand paging for anonymous mappings.
Exit: An anonymous mapping faults its pages in on demand, and the per page tail measures a real fault.
Verification: The weights workload against mainline.
E1InitramfsDone
The initramfs as a read only file system.
Exit: A user program reads a file from it.
Verification: openat, read, lseek, fstat.
E2File mapping and large pagesDone
A file backed mapping and large pages.
Exit: The weights are mapped with 2 MiB pages.
Verification: The weights workload, before and after.
E2bResident weightsDone
Large pages for file mappings and mlock residency of the weights.
Exit: The weights are resident: mlock keeps them in memory and the pages are large.
Verification: The "locked pages" line of the boot log.
E3aPrioritiesDone
A scheduler with priorities and wakeup preemption.
Exit: A scheduler with priorities and wakeup preemption.
Verification: The threads workload and the wakeup test.
E3bA short tailDone
The tail of the scheduler measured, and the policy that shortens it.
Exit: The tail of a runnable thread stays inside a budget.
Verification: The threads workload, published with its p99.
SMP
M9SMPDone
ACPI MADT, INIT-SIPI-SIPI, LAPIC and IOAPIC, IPIs, four processors.
Exit: Boots with 4 vCPUs; every processor runs its own threads and reports a heartbeat.
Verification: Boot gate with four processors in CI.
Network
M10The networkDone
The PCI bus, a virtio device, IPv4 and UDP, the sockets of the ABI.
Exit: The kernel reaches the network: an agent calls an API and reads the answer.
Verification: The networking gate in CI.
M12TCPDone
TCP in the kernel, so the agent can speak HTTP.
Exit: A request and a reply over TCP.
Verification: The networking gate in CI, with a request and a reply over TCP.
Inference runtime
E4The inference runtimeDone
A real model, token for token against the reference.
Exit: A Rust inference runtime generates the same tokens as the reference implementation.
Verification: Token for token diff against the reference.
E5The runtime measuredDone
Tokens per second and time to first token, both kernels, same machine.
Exit: Tokens per second and time to first token, both kernels, same machine.
Verification: The rig, with the raw data published.
Agent
E6The agentDone
Model, tool call, tool result and model, with a grammar that forces the call.
Exit: The agent asks the model for a tool call, runs the tool and goes on, and the call is always well formed.
Verification: The agent gate in CI, and the grammar tests.
E7The agent measuredDone
The latency of a step and the tokens of a step, on both kernels.
Exit: The agent is measured on both kernels: the latency of a step and the tokens of a step.
Verification: The rig, with the raw data published.
E8The tools of an agentNext
The agent writes a file and lists a directory: the tools need a file system the kernel serves.
Exit: The tools need a file system the kernel serves.
Verification: The tools against the same program on both kernels.
Measurement rig
M8The benchmark rigDone
Seventeen measurements, the comparison published with its raw data.
Exit: Published benchmark report: raw CSV, median, p99, sigma, N >= 30.
Verification: The bench scripts.
Next
M11A quantized checkpointNext
A quantized model fits in the memory of the machine and keeps its answer.
Exit: A quantized model fits in the memory of the machine and keeps its answer.
Verification: The runtime against the reference, with the digest of the checkpoint.
M13TLSNext
TLS in the kernel, so the agent can read the certificate of an API.
Exit: Against a server with a certificate.
Verification: The networking gate in CI.
Deferred
M5A shellDeferred
A /init busybox shell runs "ls | wc -l" with the same output as Linux.
Exit: The same output as Linux.
Verification: Diff suite.
M6Dynamic linkingDeferred
A musl dynamic binary runs from a read-only ext2 rootfs.
Exit: A musl dynamic binary runs from a read-only ext2 rootfs.
Verification: Golden log.
M7Signals and pipelinesDeferred
A signal and pipeline test suite produces identical output to Linux.
Exit: Identical output to Linux.
Verification: Diff suite in CI.
Not abandoned, just later
These items are out of the current path. They will be picked up once the core kernel, the agent loop and the network are done.
- Processes and a real file system
- Dynamic linking
- Signals
- A shell test suite
What can go wrong, and what gets cut
The stop rules are the promise: if the schedule slips, the scope shrinks, but the kernel that remains still ships.
Risks
Scope creep towards a small Linux
The cut list is frozen: no kernel modules, no namespaces, no cgroups.
The dynamic loader is the hardest single item
Static musl binaries first, dynamic musl later.
ABI divergence in errno values or structure layouts
Diff the same binary behaviour on Linux and Rabbit from M4 onwards.
Concurrency bugs once SMP arrives
Lockdep-lite from M3, one CPU until the rig lands.
Burnout
Visible weekly exit criteria and explicit stop rules.
QEMU is not hardware
Bare metal is an explicit non-goal; all results are labelled as QEMU results.
Stop rules
If a milestone slips, these items are the first to leave. They are not abandoned; they are deferred until the core kernel is done.
- Network stack, not started.
- SMP: publish single CPU benchmarks instead.
- Dynamic linking: static musl only.
- Signals: keep kill, exit and SIGCHLD only.
- Benchmark suite: keep only the getpid and context switch benchmarks.
Estimate
About 34 weeks in total for a solo developer with steady spare time, roughly 12 hours per week.
Read the design
The architecture document explains why the milestones are ordered this way and how each crate fits in.