An operating system that is grown on each machine rather than shipped to it: a small trusted core boots the computer and connects it to Claude, which writes everything else — kernel, drivers, applications — as machine code fitted to that exact hardware, and nothing touches the real machine until it has survived a rehearsal on a copy.
The name carries both meanings: the germline it grows from, and the benign germ that settles into a machine, phones a faraway server, and starts mutating.
Everything here follows one rule: nothing that exists for human convenience is allowed to run at runtime. Human convenience belongs in the conversation, at authorship time. Claude is the last interpreter, moved out of the machine and into the cloud, with English as the source language — the interpretation cost is paid once, at authorship, not on every run. The full design is in ai-os-foundation.md, the project's single source of truth. HANDOVER.md is the rolling state.
The project went live on 31 August 2026 with an empty folder. Every stage is a growth ring: small enough to finish, ends with something you can see, and gated by acceptance tests written before the code existed.
| Stage | What grew | Closed | Picture |
|---|---|---|---|
| 0 — First pixel | A 512-byte BIOS boot sector: Spectrum loading stripes and a hello over serial. 211 of 510 bytes used. | 31 Aug 2026 — pixels by teatime | the stripes |
| 1 — Owning the processor | A hand-written PE32+ UEFI application: own GDT and paging, all cores woken with INIT-SIPI-SIPI, each painting its own band at native resolution. The picture is the core count. | 31 Aug 2026 | eight bands, eight cores |
| 2 — Senses | Interrupt-driven PS/2 keyboard and a framebuffer text console. First words typed into the OS: hello world. yay. thank you claude. | 1 Sep 2026, midnight | the first words |
| 3 — Memory of its own | A virtio-blk driver and an append-only notebook filesystem, grown overnight in one unattended run. Typed lines survive a reboot: "It remembers!" | 1 Sep 2026 | it remembers |
| 4 — The umbilical | virtio-net, a minimal TCP/IP stack, and a caged network with one door to a broker that relays to Claude. The booted OS asked Claude its first question and printed the answer. | 1 Sep 2026 | the first conversation |
| 5 — The conversation | The loop closes. A line typed ! ... goes to Claude and comes back as machine code, rehearsed in a twin boot before it may run, then cached in the germline. "Make me a clock" produced a running clock — with the date and an exit line nobody asked for. |
1 Sep 2026 | the first grown clock · the boot log |
| 6a — The glass | The screen gets one owner: a glass core composites four regions from surfaces in RAM at sixty frames a second; an obs strip of live counters the harness reads back against the machine's own obs page; an app is four callbacks stepped beside a live conversation. The grown clock ticked in its panel while a note was typed next to it — with two switches Claude added unasked. | 2 Sep 2026 | the clock in its panel |
| 6b — The store of plans | An app is a plan file: intent in English plus five-verb tests. ! install calculator was grown from plans/calculator.md, rehearsed in the twin against the plan's own tests, kept on a second disk with its SHA-256, and launched after a reboot with the broker gone. |
3 Sep 2026 | the calculator installed · launched offline |
| 6c — The pointer | The PS/2 mouse on the i8042, the first device configured rather than inherited: a one-cell arrow drawn last in every frame by the glass core, pointer input-to-photon on the strip, a click on the choices row doing what its key does, and an optional fifth callback point(row, col, button) for apps that want clicks. |
5 Sep 2026 | hello cursor · the corner and the calculator |
| 7 — Bare metal | The same binary on a real machine: an HP Compaq Elite 8300 from 2012, booted from a stick the owner flashed by hand. An AHCI driver and a GPT the machine writes itself; an e1000e driver on the 82579LM with a relay answering on the home switch, and a serial monitor that found the one bit that kept it from sending; the EDID guard; the i8042 initialised cold; serial first, so every device reports before the next is touched. The binary that passed the owner's test on it is 40,960 bytes. The Ubuntu 26.04.1 image that boots the same machine from the same drive is 6,482,409,472 bytes, 158,262 times larger. From the firmware's handover to a prompt you can type at: 0.63 seconds, timestamped on the serial chart. Shutdown is the power button. | closed 18 Sep 2026 | the HP and its screen · hello metal · pong · the calculator from the disk |
| 7d — The trials | An N-of-1 crossover the OS runs on its own human: the choices row as text (A) against the same items drawn as boxes (B), the machine as the timer and the case-report form, every click a note on its own disk, and the verdict computed in the guest by a rule fixed before the first click. Three sittings on the HP, 240 cues. B's median was lower in 8 of 12 pairs; ten were needed. Misses: 4 on A, none on B. A stays. | 25 Sep 2026 | sitting 3 and the verdict · trial concluded |
| 8t — Trial two | A second N-of-1 trial of the choices row, pre-registered after the first leaned towards the boxes. It asks one question only: does the painted box itself help? Layout G draws the boxes' zones, labels and targets as plain text with | separators, against the boxes (B). There is a ten-cue warm-up, then eight blocks of twenty cues. Each block is scored as a trimmed mean plus 100 ms a miss. The verdict is on the sign of the summed differences over four sittings. Times stay hidden until the verdict, the machine asks which felt easier, and Enter at an offer starts the next sitting. Seed 2, 61,440 bytes. |
green pending the oracle | — |
| 8a — The floor | The first ring of the molt, where the machine starts replacing its own parts. It gets a floor it cannot grow over: a frozen loader, with its own SHA-256 and a read-only .text, checks every part against the disk's record before it runs. The keyboard-and-mouse slot can be handed to a part that first shadows the seed's own driver on real input, counting every disagreement. If a live part hangs, the chipset's hardware watchdog resets the machine, and the next boot demotes the part and runs on the seed. Five hand-written parts meet five fates in the twin: good, wrong, hang, fault and liar. With no part installed, the binary is ring 7d's to the line and to the pixel. 57,344 bytes. |
closed 28 Sep 2026 | hang demoted on the HP |
The pictures in history/ are the machine's own screendumps, taken by each stage's acceptance harness (Stage 4's and Stage 5's are window captures from the oracle runs).
Stage 6 — growth — is closed (5 September 2026): the glass, the store of plans and the pointer, three rings in four days. The owner's first oracle run found a defect the gate had missed — the arrow left fragments along the bottom edge, because a 1080-pixel mode is not a whole number of 16-pixel cells — and the fix made the bottom row a click margin for the choices row, as Fitts's law asks of an edge.
Stage 7 — metal — is closed (18 September 2026; opened 9 September): the patient is an HP Compaq Elite 8300, and every driver the metal needs is rehearsed first in the twin. Ring 7a, the disk (closed 9 September 2026), replaces virtio-blk with an AHCI driver: one SATA disk, a GPT the machine writes itself on a blank drive, the notebook and the home as two partitions with their formats unchanged inside (stage7/DISK.md). The disk is chosen by what it holds — a GermOS table wins, a blank disk is formatted, anything else is refused by name and never written. Ring 7b, the wire (closed 15 September 2026), replaces virtio-net with an e1000e driver beside it — the NIC preferred by kind, the MAC from the device's own registers, the link awaited and its absence a named error — and puts a relay in front of the frozen broker (stage7/WIRE.md): on the home switch the relay is what answers the guest's ARP for 10.0.2.4, and in the twin every question, grow and install of the gate goes through it. Ring 7c, the metal (closed 18 September 2026), is procedure and a guard: the EDID is read from BAR2 only on QEMU's VGA and any other display gets S7: edid none and the highest mode the console can hold; the i8042 is initialised cold — the controller's self-test before its command byte, i8042: self-test ok and i8042: mouse reset ok (or mouse none, a line not an error), every controller failure named; staggered spin-up is honoured on the AHCI ports; stage7/mkstick.py writes a bootable stick image with mtools at the partition's offset and the gate boots a copy of it over USB with no boot image on SATA, re-proving every stage in one run; the storage bodyguard denies CC the flash's own words and every spelling of a device path; and stage7/METAL.md is the owner's day, step by step. Test 5 was the HP itself: the owner ran its eight steps on 18 September 2026, and his word closed the ring and the stage. Ring 7d, the trials (opened 22 September 2026 after the stage closed, closed 25 September 2026 — the trials first, the molt after, the owner's order), makes the DE evidence-based rather than asserted: GermOS runs an N-of-1 crossover on its own human. The choices row as text (layout A, the row as it was) against the same items drawn as boxes (layout B); a cue in the conversation panel names an item, the human clicks it, the machine is the timer — from the frame that painted the cue to the click's interrupt — and the case-report form: every hit, miss and block is a note on the notebook and a line on serial. Ten cues a block from a fixed table, eight blocks a sitting in ABBA BAAB / BAAB ABBA, one sitting a boot, three sittings, and a pre-registered verdict — B becomes the default if its median is lower in ten of twelve pairs and its misses are not worse — computed in the guest, journaled as a trial verdict note, and read back at every boot, so the machine remembers its own evidence with the broker off (stage7/TRIALS.md). The automated gate plays a synthetic human through the monitor, three sittings to a scripted verdict, every number predicted by the document's rules; Test 5 was three sittings on the HP's notebook, pre-registered by the owner before any click, after a rehearsal in the twin that is not trial data. They ran on 24 September 2026, and the guest's verdict was A: B's median was lower in 8 of 12 pairs, ten were needed, and the misses were 4 on A and none on B. At the next boot ! trial answered trial concluded. At the rehearsal the owner had said the boxes felt easier; the rule, fixed before the first click, is what decided. His word on the verdict closed the ring on 25 September 2026.
Stage 8 — the molt — is open (25 September 2026). It is done when the machine reboots into a kernel it grew itself and survives a week. It gets there one slot at a time, in rings 8a to 8g, and only on a floor it cannot grow over. Ring 8a, the floor, is green in the twin: all four automated tests pass on ./stage8/test-8a.sh (about 43 minutes). Ring 8a is closed (28 September 2026): on the HP, good earned its place in shadow on the owner's own typing with no disagreement, ran live on the machine's real keyboard controller, and gave way to Esc; then hang, live, stopped the machine, the chipset's watchdog reset it with nobody touching it, and the next boots demoted hang and ran on the seed's own driver. The HP's day is stage8/HP-8a.md; its chart is in history/.
- The loader. It moved into
stage8/loader.asm, frozen behind the hook: everything from the firmware's handover to the moment a slot is handed to a part, the disk's read path, and SHA-256 with its known answer checked at every boot..textis read-only on every core, and a stray write faults at its own store. - Parts. A part is a 96-byte header and a body, fetched with
! molt i8042and kept in the home store under apart-name. Every state change is amoltnote on the notebook, mirrored on serial, so the HP's chart carries the record (stage8/PARTS.md). - Shadow, then live. A new part first runs beside the seed's own driver on the same bytes, and every key and packet is compared. It is taken live only after 3 boots, 1,000 keyboard bytes and 5,000 mouse packets with no disagreement.
- The watchdog. On a boot with a part, the chipset's TCO watchdog is armed for 30 seconds and petted only while the machine is demonstrably alive. If a live part hangs or faults, the machine resets itself, and the next boot demotes the part and says why.
- The owner's way back. Holding Esc at power-on returns the machine to the seed.
- The seed. Each seed is a line in
stage8/seed-record.md: a commit and the SHA-256 of what it builds, rebuilt from a clean tree bystage8/SEED.md's recipe. Seed 1 is ring 8a's; seed 2 is ring 8t's. - Ring 8t, trial two, sits between rings 8a and 8b. It runs on the seed's own keyboard-and-mouse driver throughout, and refuses to start while a part is in that slot. Its pre-registration is
trials/spec-trial2.md, andtrials/TRIALS2.mdis the frozen document. It is green in the twin (./trials/test-trial2.sh, about 66 minutes, with ring 8a's whole gate inside it). Its four sittings are the owner's, on the HP, bytrials/HP-8t.md.
The metal, 17 and 18 September 2026 — Stage 7 closed 18 September 2026. Every driver was rehearsed in a twin of the HP for eight days before the machine saw the binary. The first watched boot stopped twelve lines in, with no error and a black screen. A live Ubuntu on the same machine proved the NIC healthy, and Intel's own driver source named the cause: on the PCH's integrated LAN, a register read in the instruction after the reset write hangs the processor. One item, nine bytes, a 25 ms wait, and the next boot went all the way. Four cores woken, the 250 GB SATA disk found on port 0 carrying the table a blind boot had left two days earlier, the link up at a gigabit, the glass painted by core 2, hello metal typed and back after the power button: 0.64 seconds from the firmware's handover to S7: keyboard ready, in a binary of 36,864 bytes. Then ? ping stopped at a named error, ERR: nic transmit timed out. Four flashes asked one question each, and every register read as written. Item 20 put a monitor in the guest and a socket on mlrig: after the timeout the machine answers register reads, writes and memory dumps over the serial line instead of halting. In one boot, nineteen resets and some 1,400 questions over the serial line, the transmit engine was shown to fetch a descriptor without EOP and refuse every one with it, and the cause was one bit: TCTL's reset default on the 82579LM carries MULR, and the driver's absolute write cleared it. The fix is three instructions. The twin cannot show it, because QEMU's 82574L sends either way. On 18 September the owner ran test 5 on the HP, eight steps: pong over the home switch, ! install calculator over the same wire, then with the broker off S7: home 1 apps, the arrow under the mouse, and the calculator launched from the disk giving 4096 with w 000 and io 000000/000000 on the strip; 0.63 seconds from the firmware's handover to S7: keyboard ready, in a binary of 40,960 bytes. The fix came from reading drivers/net/ethernet/intel/e1000e in the Linux kernel, ich8lan.c and netdev.c, written and maintained by Intel Corporation's wired Ethernet team and the kernel community on the intel-wired-lan list. The whole of it was written in assembly by Claude, rehearsed in QEMU before any of it ran on the HP, and flashed by the owner's hand, the one step the tools are forbidden to take. The originals of the photographs, straight from the phone, are beside the web copies in history/.
Everything runs inside QEMU — that is a design rule, not a convenience: nothing touches real hardware until Stage 7, on a sacrificial machine. On Ubuntu:
sudo apt install nasm qemu-system-x86 ovmf mtools python3
Each stage keeps a frozen acceptance gate — ./stageN/test.sh from the repo root builds it and proves it still works. To see each one:
Stage 0 — stripes and a serial hello:
./stage0/test.sh
qemu-system-x86_64 -drive format=raw,file=stage0/out/stage0.img -serial stdio
Stage 1 — one band per core (the machine's core count, painted):
./stage1/mkimage.sh
qemu-system-x86_64 -machine q35 -m 256M -smp 8 -bios /usr/share/ovmf/OVMF.fd \
-drive format=raw,file=stage1/out/esp.img -serial stdio
Stage 2 — type at the prompt:
./stage2/mkimage.sh
qemu-system-x86_64 -machine q35 -m 256M -smp 8 -bios /usr/share/ovmf/OVMF.fd \
-drive format=raw,file=stage2/out/esp.img -serial stdio
Stage 3 — type a line, quit, boot again: it remembers.
./stage3/mkimage.sh
truncate -s 16M stage3/out/notes.img
qemu-system-x86_64 -machine q35 -m 256M -smp 8 -bios /usr/share/ovmf/OVMF.fd \
-drive format=raw,file=stage3/out/esp.img \
-drive format=raw,file=stage3/out/notes.img,if=virtio -serial stdio
Stage 4 — ask Claude a question from inside the OS. Two terminals; the broker shells out to the Claude Code CLI (claude), which must be installed and logged in:
python3 broker/broker.py
./stage4/mkimage.sh
truncate -s 16M stage4/out/notes.img
qemu-system-x86_64 -machine q35 -m 256M -smp 8 -bios /usr/share/ovmf/OVMF.fd \
-drive format=raw,file=stage4/out/esp.img \
-drive format=raw,file=stage4/out/notes.img,if=virtio \
-netdev 'user,id=n0,restrict=on,guestfwd=tcp:10.0.2.4:9999-cmd:nc -N 127.0.0.1 9999' \
-device virtio-net-pci,netdev=n0 -serial stdio
Type ? and a question. A line without the marker is a note, and persists — exactly as Stage 3. The guest's network is a cage: restrict=on means it can reach nothing at all except that one forwarded socket to the broker on localhost.
Stage 5 — ask the OS to grow something. The Stage 5 broker answers questions and requests; on a request it asks Claude for a flat binary against the ABI in stage5/GERMLINE.md, rehearses it in a headless boot of the same image (the twin) before it is allowed anywhere near your screen, caches what passed in germline/ (per machine, gitignored), and delivers it. Two terminals:
python3 broker/germline.py
./stage5/mkimage.sh
truncate -s 16M stage5/out/notes.img
qemu-system-x86_64 -machine q35 -m 256M -smp 8 -bios /usr/share/ovmf/OVMF.fd \
-drive format=raw,file=stage5/out/esp.img \
-drive format=raw,file=stage5/out/notes.img,if=virtio \
-netdev 'user,id=n0,restrict=on,guestfwd=tcp:10.0.2.4:9999-cmd:nc -N 127.0.0.1 9999' \
-device virtio-net-pci,netdev=n0 -serial stdio
Type ! make me a clock. The indicator turns while Claude writes and the twin rehearses; a clock ticks; Esc brings the prompt back; ask again and it comes from the germline at once. ? still asks (with or without the space now), and a plain line is still a note. The automated gate (./stage5/test.sh) uses only a mock broker with a canned test component, so it never spends a token.
Stage 6, ring 6a — the glass. The screen gets one owner: a dedicated core composites four regions — an obs strip of live counters on top, a choices row at the bottom, the conversation on the left, the app on the right — from surfaces in RAM, sixty frames a second. An app is four callbacks (init, step, key, exit, per stage6/GLASS.md) stepped by the main loop, so the conversation stays alive beside it. The display's EDID picks the mode, so QEMU is given a display that states one. Two terminals:
python3 broker/glass.py
./stage6/mkimage.sh
truncate -s 16M stage6/out/notes.img
qemu-system-x86_64 -machine q35 -m 256M -smp 8 -bios /usr/share/ovmf/OVMF.fd \
-vga none -device VGA,edid=on,xres=1920,yres=1080 \
-drive format=raw,file=stage6/out/esp.img \
-drive format=raw,file=stage6/out/notes.img,if=virtio \
-netdev 'user,id=n0,restrict=on,guestfwd=tcp:10.0.2.4:9999-cmd:nc -N 127.0.0.1 9999' \
-device virtio-net-pci,netdev=n0 -serial stdio
Type ! make me a clock: the strip says growing while Claude writes and the twin rehearses, then the clock ticks in the app panel with running make me a on the strip. Tab gives the keys to the prompt — type a note beside the running clock — and Tab gives them back; Esc closes the app. The choices row always says what the keys do. The Stage 5 clock in germline/ is an ABI 1 entry: ring 6a keys its germline abi2, so the first request regenerates. The automated gate (./stage6/test.sh) speaks only to the mock and its canned apps, and spends no token.
Stage 6, ring 6b — the store of plans. An app is a file: plans/<name>.md — its name, an Intent in plain English, up to four Choices for the choices row, and Tests in five verbs (press, wait, expect "…", expect not "…", expect changed) that the twin runs against the build before it is delivered (stage6/PLANS.md). ! install <name> grows it from the intent, rehearses it against the plan's own tests on top of the safety criteria, and delivers it with the installed flag; the machine writes it to a second disk, the home image (stage6/HOME.md: a header, a table of apps with each build's SHA-256 and the previous build kept for undo), and runs it. From then on ! <name> launches it from disk with nothing on the wire — the choices row names the installed apps — and ! undo install <name> swaps the previous build back. Windowed runs are 1920x1080; the twin is the same machine. Two terminals:
python3 broker/plans.py
./stage6/mkimage.sh
truncate -s 16M stage6/out/notes.img
truncate -s 16M stage6/out/home.img
qemu-system-x86_64 -machine q35 -m 256M -smp 8 -bios /usr/share/ovmf/OVMF.fd \
-vga none -device VGA,edid=on,xres=1920,yres=1080 \
-drive format=raw,file=stage6/out/esp.img \
-drive format=raw,file=stage6/out/notes.img,if=virtio \
-drive format=raw,file=stage6/out/home.img,if=virtio \
-netdev 'user,id=n0,restrict=on,guestfwd=tcp:10.0.2.4:9999-cmd:nc -N 127.0.0.1 9999' \
-device virtio-net-pci,netdev=n0 -serial stdio
Type ! install calculator: the strip says installing while Claude builds and the twin runs the plan's five tests; installed calculator and the calculator in its panel with = result c clear Esc exit Tab prompt on the row. Do a sum; Esc. Quit QEMU, stop the broker, boot the same command again: S6: home 1 apps, ! calculator on the choices row, and ! calculator runs it from disk. An install may be amended at the door — ! install calculator, but big keys — and a plan whose build fails its own tests is refused naming the test. The automated gate (./stage6/test-6b.sh) speaks only to the mock and its two canned plans, echo and the liar, and spends no token.
Stage 6, ring 6c — the pointer. The PS/2 mouse arrives because the constitution demands it: the choices row has targets on an edge, and Fitts's law is about pointing at them. The i8042 is configured for the first time (the auxiliary port and its interrupt, the mouse reset and told to report — the path Stage 7's metal will have, not a tablet); the glass core draws a one-cell arrow as the last thing in every frame from a position the interrupt handler keeps in the obs page; pointer input-to-photon joins the strip as pt, beside the packet and click counts, the moment the mouse first speaks — until then the machine is ring 6a's to the pixel. A click on a choices-row item does what its key does: ? ask and ! grow type their marker, ! calculator launches from disk (on an empty prompt line), an app's declared choices reach the app, Esc exit and the Tab items move as the keys do. An app may announce a fifth callback in its blob — POINTER2 at byte 16, then the offset of point(row, col, button) — and every earlier app, the calculator included, is clicked on harmlessly (stage6/GLASS.md, "Ring 6c — the pointer"). Two terminals:
python3 broker/pointer.py
./stage6/mkimage.sh
truncate -s 16M stage6/out/notes.img
truncate -s 16M stage6/out/home.img
qemu-system-x86_64 -machine q35 -m 256M -smp 8 -bios /usr/share/ovmf/OVMF.fd \
-vga none -device VGA,edid=on,xres=1920,yres=1080 \
-drive format=raw,file=stage6/out/esp.img \
-drive format=raw,file=stage6/out/notes.img,if=virtio \
-drive format=raw,file=stage6/out/home.img,if=virtio \
-netdev 'user,id=n0,restrict=on,guestfwd=tcp:10.0.2.4:9999-cmd:nc -N 127.0.0.1 9999' \
-device virtio-net-pci,netdev=n0 -serial stdio
Click in the QEMU window to grab the mouse (Ctrl+Alt+G releases it) and move it: the arrow appears, S6: mouse ready goes out on serial, and pt, pk and cl join the strip. Click ! grow and type a request, or ! install calculator and then click ! calculator on the row; click into the calculator's panel (nothing happens — it has no point), then = result, c clear, Tab prompt, Tab app, Esc exit. With the mock broker (python3 broker/pointer.py --mock) the request ! point app serves the one committed app that takes clicks: each button draws its digit where you clicked. The automated gate (./stage6/test-6c.sh) drives QEMU's PS/2 mouse through the monitor, speaks only to the mock, and spends no token.
Stage 7, ring 7a — the disk. The same machine on q35's own SATA controller with the patient's CPU model: one 64 MB raw disk, blank, which the machine partitions on its first boot — a protective MBR, a GPT with GermOS's own type GUIDs, a 16 MB notes partition at LBA 2048 and a 16 MB home partition at 34816, the frozen formats byte for byte inside — and recognises on every boot after. S7: gpt written on the boot that formats, then S7: disk port 1 131072 notes 2048 home 34816. A disk holding anyone else's table, a boot sector or a torn table is refused by name (ERR: no GermOS disk and no blank disk - port 0: other, port 1: gpt) and never written; the twin's own boot image sits on port 0 and is never touched. Everything Stage 6 does runs unchanged on the partitions. Two terminals:
python3 broker/metal.py
./stage7/mkimage.sh
truncate -s 64M stage7/out/disk.img
qemu-system-x86_64 -machine q35 -cpu IvyBridge -m 256M -smp 4 -bios /usr/share/ovmf/OVMF.fd \
-vga none -device VGA,edid=on,xres=1920,yres=1080 \
-drive format=raw,file=stage7/out/esp.img \
-drive if=none,id=d0,format=raw,file=stage7/out/disk.img -device ide-hd,drive=d0,bus=ide.1 \
-netdev 'user,id=n0,restrict=on,guestfwd=tcp:10.0.2.4:9999-cmd:nc -N 127.0.0.1 9999' \
-device virtio-net-pci,netdev=n0 -serial stdio
Type a note; ! install calculator; do a sum; quit, stop the broker, boot the same command again: the note is back, S7: home 1 apps, and ! calculator runs from the home partition. On the host, blkid -p stage7/out/disk.img and partx -s stage7/out/disk.img read the table the machine wrote. The automated gate (./stage7/test.sh) drives five serial boots, the persistence pair and ring 6b's store test on the partitions, speaks only to the mock, and spends no token.
Stage 7, ring 7b — the wire. The same machine on the NIC the metal has: an e1000e — QEMU's 82574L standing in for the HP's 82579LM, the same register family — found by vendor, class and a table of three ids and preferred over a virtio-net whenever both are present, owned, reset with interrupts masked, its MAC read from RAL0/RAH0, its link awaited for ten seconds (S7: nic 6c:3b:e5:3b:86:45 then S7: link up; a link that never comes is ERR: nic link did not come up within 10 s, never a hang), sixteen legacy receive descriptors and eight transmit descriptors, polled (stage7/WIRE.md). The TCP stack above is untouched. On the metal the guest keeps its frozen addressing and ARPs for 10.0.2.4 on the home switch; broker/relay.py is what answers there — it binds exactly 10.0.2.4 or 127.0.0.1 and nothing else, forwards each connection to the frozen broker on 127.0.0.1:9999, and logs one JSON line per connection. In the twin the relay sits on 127.0.0.1:9997 and the cage's guestfwd lands on it, so every question, grow and install of the gate goes through it. Three terminals:
python3 broker/wire.py
python3 broker/relay.py --bind 127.0.0.1 --port 9997
./stage7/mkimage.sh
rm -f stage7/out/disk.img; truncate -s 64M stage7/out/disk.img
qemu-system-x86_64 -machine q35 -cpu IvyBridge -m 256M -smp 4 -bios /usr/share/ovmf/OVMF.fd \
-vga none -device VGA,edid=on,xres=1920,yres=1080 \
-drive format=raw,file=stage7/out/esp.img \
-drive if=none,id=d0,format=raw,file=stage7/out/disk.img -device ide-hd,drive=d0,bus=ide.1 \
-netdev 'user,id=n0,restrict=on,guestfwd=tcp:10.0.2.4:9999-cmd:nc -N 127.0.0.1 9997' \
-device e1000e,netdev=n0,mac=6c:3b:e5:3b:86:45 -serial stdio
The serial log says S7: nic 6c:3b:e5:3b:86:45 then S7: link up. Type ? ping: the relay's terminal logs one connection, pong appears, and the strip says w 001. Type ! make me a clock: Claude writes it, the twin rehearses it on a SATA disk and an e1000e of its own, and the clock ticks in its panel. On the HP's day the relay runs with no flags (10.0.2.4:9999, the switch) beside the broker.
Stage 7, ring 7c — the metal. The twin of the HP: the same binary on a USB stick the firmware reads (stage7/mkstick.py writes stage7/out/stick.img — a protective MBR, a GPT, one 64 MB EFI System Partition holding EFI/BOOT/BOOTX64.EFI, formatted and filled with mtools at the partition's offset, no loop device), booted as a copy over qemu-xhci + usb-storage with no boot image on SATA, the SATA disk and the e1000e as before. The guest reads an EDID only from QEMU's VGA and takes the highest mode the console can hold on any other display (S7: edid none), initialises the i8042 cold (i8042: self-test ok, i8042: mouse reset ok), and honours staggered spin-up on the AHCI ports. The relay closes a guest that never closes; broker/chart.py reads the HP's serial port on the day; stage7/METAL.md is the owner's procedure — the flash by his own hand by the by-id path, the LAN port's second address, the three terminals, the first boot line by line. Three terminals, the same as ring 7b's with the stick in place of the boot image:
python3 broker/wire.py
python3 broker/relay.py --bind 127.0.0.1 --port 9997
./stage7/mkimage.sh && python3 stage7/mkstick.py
rm -f stage7/out/disk.img; truncate -s 64M stage7/out/disk.img
cp stage7/out/stick.img stage7/out/stick.twin.img
qemu-system-x86_64 -machine q35 -cpu IvyBridge -m 256M -smp 4 -bios /usr/share/ovmf/OVMF.fd \
-vga none -device VGA,edid=on,xres=1920,yres=1080 \
-device qemu-xhci -drive if=none,id=stick,format=raw,file=stage7/out/stick.twin.img -device usb-storage,drive=stick \
-drive if=none,id=d0,format=raw,file=stage7/out/disk.img -device ide-hd,drive=d0,bus=ide.1 \
-netdev 'user,id=n0,restrict=on,guestfwd=tcp:10.0.2.4:9999-cmd:nc -N 127.0.0.1 9997' \
-device e1000e,netdev=n0,mac=6c:3b:e5:3b:86:45 -serial stdio
OVMF says it is loading from the USB drive, then the nineteen lines with S7: disk port 1 … (the only disk on SATA now) and the i8042: pair before S7: keyboard ready. Everything the earlier rings did runs unchanged. The automated gate (./stage7/test-7c.sh) parses the stick from the host, boots it three times over USB, re-proves every stage in one scripted run, and checks the bodyguard's table — mock only, no token. The stick is a copy in the twin because QEMU locks what it boots; the file as built is what the owner flashes.
Stage 7, ring 7d — the trials. The same three terminals and the same machine; type ! trial at the prompt and click the cued item eighty times (click: grow names ! grow; ask, app and exit the others); a sitting is eight blocks with a two-second rest between them, about four minutes, and Esc abandons it. The row alternates between its text and its boxes block by block; the strip says trial A 3/8; every hit goes to the notebook and to serial as trial: 1 3 A 7 412. After the sitting the app panel shows its table; after the third completed sitting the verdict, and the row keeps the winning layout from then on. python3 stage7/trials.py --disk stage7/out/disk.img prints the tables and the verdict from the disk, --serial from the chart. The automated gate (./stage7/test-7d.sh, about 21 min, its output in stage7/out/gate-7d.log) parses the document cold, plays the synthetic human through three sittings to a scripted verdict, and runs the three earlier Stage 7 gates on the same binary — mock only, no token; the trial itself sends nothing.
Stage 8, ring 8a — the floor. The same twin of the HP, with ring 8a's binary and a mock broker that answers ! molt i8042 with one of the five committed fixture parts (--part good, wrong, hang, fault or liar). Three terminals:
python3 broker/molt.py --mock --part good
python3 broker/relay.py --bind 127.0.0.1 --port 9997
./stage8/mkimage.sh && python3 stage8/mkstick.py
rm -f stage8/out/disk.img; truncate -s 64M stage8/out/disk.img
cp stage8/out/stick.img stage8/out/stick.twin.img
qemu-system-x86_64 -machine q35 -cpu IvyBridge -m 256M -smp 4 -bios /usr/share/ovmf/OVMF.fd \
-vga none -device VGA,edid=on,xres=1920,yres=1080 \
-device qemu-xhci -drive if=none,id=stick,format=raw,file=stage8/out/stick.twin.img -device usb-storage,drive=stick \
-drive if=none,id=d0,format=raw,file=stage8/out/disk.img -device ide-hd,drive=d0,bus=ide.1 \
-netdev 'user,id=n0,restrict=on,guestfwd=tcp:10.0.2.4:9999-cmd:nc -N 127.0.0.1 9997' \
-device e1000e,netdev=n0,mac=6c:3b:e5:3b:86:45 -display gtk,zoom-to-fit=on -serial stdio
With no part installed it boots as ring 7d, with no S8: line.
- Type
! molt i8042. The console sayspart i8042 shadow 4fe6beefc4bc57d0, and! moltdraws the slot's table in the app panel. - Boot the same command again, three times. Each time
S8: sha256 ok,S8: part i8042 shadow …andS8: watchdog tco 30 scome before the ready line, andhold Esc for the seedshows for three seconds. Type, move the mouse, and wait forS8: healthy <n>a minute after the ready line. - Once the table meets its threshold,
! molt take i8042makes the part live from the next boot, and the part's ownpart:lines replace the seed'si8042:pair. - Serve
--part hangand fetch it the same way. Once it is live, type until the machine stops. About thirty seconds later QEMU resets it, and the next boot saysS8: recovery i8042 watchdog.
python3 stage8/parts.py --disk stage8/out/disk.img prints the same table from the disk, and --serial prints it from a serial log. The automated gate (./stage8/test-8a.sh, its output in stage8/out/gate-8a.log) plays every fate on its own disk, then runs ring 7d's gate with 7c, 7b and 7a inside it on their own binary: mock only, no token. stage8/HP-8a.md is the owner's day on the HP.
Ring 8t — trial two. No human sitting runs in QEMU: the trial is the owner's four sittings on the HP. The twin is the automated gate only. Its synthetic human plays every sitting through the monitor's mouse, on a blank disk and on a disk rebuilt from the HP's own charts. python3 trials/trials2.py --disk <image> prints a disk's sittings and verdict, and --status <chart> prints a chart's procedure facts, with no time or score before the verdict.
GermOS is built by a team of three, and the division of labour is the experiment as much as the OS is:
- Wajira (@IndyWH) — product owner and QA oracle. A UK GP and health-informatician who verifies every stage by eyeball; the medical model runs through the project's verification (the trial protocol precedes the treatment).
- Claude Cowork — design and specs. Writes each stage's one-page spec for approval, reviews every diff, flags the judgement calls.
- Claude Code — implementation. Writes all the assembly, one commit per numbered plan item, tests green before every commit — mechanically held to an approved plan by hooks it cannot edit.
The acceptance tests are written before the code and frozen by a hook; the human's word is the final gate of every stage. Every spec, plan, decision and mistake is in the git history and HANDOVER.md — the project's coordination channel is the audit trail.
Not a Linux replacement. Not a product. Not secure enough to trust with anything that matters — and never, under any circumstances, connected to clinical work or patient data. It is a laboratory for one thesis — that software can be grown rather than shipped — and the most fun available per kilobyte.
MIT.


