The plug-and-play stick (#92 Tasks 1-3) and a BAM flush that moves only the volume (#155) #159

Merged
rajames merged 58 commits from StarForth-v4.0.0 into master 2026-11-08 17:51:56 +00:00
236 changed files with 51182 additions and 174 deletions
+15 -11
View File
@@ -291,8 +291,9 @@ The vendored hosted `make` build (above) is NEVER used to validate kernel change
make -f kernel/Makefile ARCH=amd64 clean qemu
make -f kernel/Makefile ARCH=aarch64 clean qemu
make -f kernel/Makefile ARCH=riscv64 clean qemu
# ...the PC stick loaded above 2 GiB, as a PC's firmware loads it (pc machine, 3 GiB; with
# Zuse's pair in the stick: scripts/qemu_session.py stick_zuse amd64 --target qemu-stick-high):
# ...the PC stick loaded above 2 GiB, as a PC's firmware loads it (pc machine, 3 GiB; the stick as
# built, its first boot minting its own Zuse: scripts/qemu_session.py stick_genesis amd64
# --target qemu-stick-high):
make -f kernel/Makefile ARCH=amd64 clean qemu-stick-high
# ...and the 32-bit build -- v4 with 32-bit cells, the F18/Zynq (FPGA) case: its nucleus
# image and every v4 test at that width (no QEMU; not a substitute for the boots above):
@@ -326,14 +327,17 @@ audit artifacts — they are committed to the repo. Do not delete them. There is
timestamped convention (self-documented via its own README); not a contradiction, just a
second, less-structured log location.
**The disks (Captain Bob, 2026-10-26, the identity gate):** with no identity thumbdrive the system
is headless -- no prompt -- so every boot needs Zuse. `kernel/Makefile`'s `ARTDISK` and `ZUSEDISK`
default to the minted Zuse pair, `disk/zuse-scratch/artemis.img` and `zuse-thumb-ident.img` (a
pair: her genesis marker is on that Artemis disk; `disk/README.md`). Since 2026-10-28 `ZUSEDISK`
is that pair laid out as a stick (`make ... zusestick`, `build/<arch>/kernel/zusestick.img`, made
fresh for every boot: identity and Artemis partitions on one USB disk, STICK.md §4); `ARTDISK`
stays the pair's Artemis file. v3 reads identity drives raw, never through a GPT, so a `system=v3`
boot needs `ZUSEDISK=disk/zuse-scratch/zuse-thumb-ident.img` (a copy) to log Zuse in. Put both back as committed (`git checkout -- disk/zuse-scratch`)
**The disks (plan 2026-10-29-stick-5, Task 3, 2026-11-08):** with no identity the system is
headless -- no prompt -- so every boot needs Zuse. A v4 `qemu` boot attaches a **fresh data stick**
(`DATASTICK`, `make ... datastick`, `build/<arch>/kernel/datastick.img`: identity and Artemis
partitions, made fresh for every boot) and nothing else: its first boot mints the stick's proxy
Zuse (STICK.md §6), so **every acceptance run is a first boot** -- plug and play. `DATASTICK=`
boots v4 with no drive (headless). The minted Zuse pair (`disk/zuse-scratch/`, `disk/README.md`)
is for the tests that ask for it by name (`scripts/qemu_session.py`: `stick_zuse`, `two_sticks`,
`stick_artemis`, `raw_ident`, `v3_keys`, the hot-plug and GPT modes) and for `system=v3`, whose
defaults are unchanged: `ARTDISK` the pair's Artemis, `ZUSEDISK` the pair as a stick (v3 reads
identity drives raw, so a `system=v3` boot needs `ZUSEDISK=disk/zuse-scratch/zuse-thumb-ident.img`,
a copy, to log Zuse in). Put the pair back as committed (`git checkout -- disk/zuse-scratch`)
before each architecture. The prompt is `[zuse@Hera] ok> `.
Do not claim a change is accepted until all three architectures have booted, and their logs are
@@ -343,7 +347,7 @@ present in `logs/`:
the three;
- **the PC stick loaded high** (Captain Bob, 2026-10-29, after the SER5 page-faulted in the
loader -- q35 always loads the image below 2 GiB, a PC's firmware does not; `FABRIC-3.md`
§XLIV): `qemu-stick-high` to `[zuse@Hera] ok> ` with the same `PARITY:V4_POST ... fail=0` and
§XLIV): `qemu-stick-high` -- the stick as built, a first boot -- to `[zuse@Hera] ok> ` with the same `PARITY:V4_POST ... fail=0` and
`POST: PASSED`. The amd64 link also refuses any 32-bit absolute or GOT relocation in the image;
don't work around that check, fix the code it names;
- **the 32-bit build** (Captain Bob, 2026-10-14: "the 32 bit build needs to go into the
+32 -6
View File
@@ -1,10 +1,15 @@
# LithosAnanke v2.1.0
# LithosAnanke v4.0.0-alpha.3
**UEFI-bootable FORTH microkernel.** Boots from firmware, initialises memory and interrupts, then
runs StarForth as its sole userspace runtime. No libc. No OS. Just stone and necessity.
*Lithos* (foundation) + *Ananke* (necessity) — the kernel under StarshipOS.
**Try it in your browser:** [starshipos-f18.com](https://starshipos-f18.com/) — a StarshipOS
machine of your own, booted to `[zuse@Hera] ok>`, thrown away when you leave. **Releases:**
[v4.0.0-alpha.3](https://gitea.starshipos-f18.org/rajames/LithosAnanke/releases) (pre-release),
the kernel `4.0.0-alpha.3` with the StarForth engine `3.2.0`.
---
## Products
@@ -22,7 +27,8 @@ FORTH-79 is recomposed on the F18 engine and stored as a capsule; the StarshipOS
vocabulary gets the same treatment. v3 remains the reference system until v4 meets its
acceptance criteria (`docs/v4.0.0/JUSTIFICATION.md` §16). **Both run on bare metal now:** every
board image carries v4 and v3, boots v4 as built, and one word in its boot configuration
chooses (see below).
chooses (see below) — except the PC stick, which is v4 only. **v3 is being retired** (its own
milestone, #156): what v4 needs of it, the block layer, moves into v4 and the rest is removed.
---
@@ -34,14 +40,22 @@ chooses (see below).
| M7 | StarForth VM integration + parity validation | ✅ Complete |
| M7.1 | Capsule birth · Mama FORTH vocabulary · the Tripod fleet · kernel-Hermes · word-level ACL | ✅ Live |
| M8 | Keyboard input to the REPL — PS/2, virtio and **USB** keyboards (a full keyboard: Caps/Num Lock, keypad) | ✅ In QEMU, all three ISAs |
| M9 | Block storage — Artemis's disk on virtio-blk; identity thumbdrives on USB mass storage | ✅ In QEMU · real disks: no driver yet (`boards/BRINGUP.md` A4) |
| M9 | Block storage — on v4, Artemis and Zuse's identity on the StarshipOS stick (GPT partitions, over USB mass storage); v3's Artemis on virtio-blk | ✅ In QEMU · real disks: no driver yet (`boards/BRINGUP.md` A4) |
| The stick | One USB stick is the whole OS: plug it in, boot, `[zuse@Hera] ok>` — its first boot mints its own Zuse and grows Artemis to fill it (`docs/v4.0.0/STICK.md`, #92) | ✅ Tasks 1–3 of 5 in QEMU · the real Zuse on a second stick next |
| Bare metal | a generic PC (amd64; first on the bench: a Beelink SER5), Raspberry Pi 5 (aarch64), Milk-V Mars (riscv64); Zynq-7020 (ARMv7) not yet ported | Images build; first boots on the bench — `boards/BRINGUP.md` |
**v4 is the default build, and v3 is being retired**: every kernel boots v4 unless its boot
arguments say `system=v3`. POST at boot, on all three ISAs: v4 — **538 tests**,
`PARITY:V4_SYSTEM word_count=317 dict_hash=0xe5a57f3eb72ff94a`; v3 — **1052 tests**,
`PARITY:V4_SYSTEM word_count=317 dict_hash=0xfec8c47cfc6f437f`; v3 — **1052 tests**,
`PARITY:M7.1a word_count=526 hash=0x82f4ae7cb2e2d424`.
**How a change gets in** (the Captain Bob method): `master` is reached only through a pull request
that passed **acceptance** — amd64, aarch64 and riscv64 booted in QEMU to `[zuse@Hera] ok>`, POST
538/538 and one `dict_hash` on all three; the PC stick booted loaded above 2 GiB, as a PC's firmware
loads it; and the 32-bit build's tests. Every acceptance boot starts from a fresh stick, so every
run is a first boot. The same stages run nightly and for every release (`scripts/nightly.sh`); the
serial logs are committed.
### What's live
- **The Tripod** — a named multi-VM fleet: **Hera** (the Mama VM, the governor), **Artemis**
@@ -50,9 +64,14 @@ arguments say `system=v3`. POST at boot, on all three ISAs: v4 — **538 tests**
- **kernel-Hermes** — messaging moved into the kernel (the Hermes VM is gone,
`docs/fabric/FABRIC-3.5.md`): every VM takes its own messages on its own turn, under a
cooperative switcher that every VM takes part in.
- **The plug-and-play stick** (v4) — `make boot_image TARGET=PC` and `make write_stick
DEVICE=/dev/sdX`, plug it in, boot: the stick's first boot mints its own Zuse (no two sticks share
one) and grows its Artemis partition to fill the stick, up to 256 GiB, writing metadata only.
- **Identities on thumbdrives** — Zuse, the superuser, and every user is a minted USB
thumbdrive (Ed25519, Zuse-signed); plugging one in births that user's VMs, pulling it out
ends them. There is only the drive: no password, no PIN.
- **Signed capsules** — the capsules the kernel boots from are signed under the StarshipOS Root CA
(`ci/pki/starshipos-root-ca.pem`, published with every release) and checked at boot.
- **Word-level ACL** — every dictionary entry carries a TTL/allow/mode/pin access-control
record; strict, TTL and pinned modes; two console layers (emergency `ok>` and superuser
`zuse)ok>`). Measured overhead of the live ACL-TTL mechanism: **+0.0603%**, CV 0.000%,
@@ -84,10 +103,16 @@ make # every board with a kernel port + hosted v3 +
make docs # build/docs/LithosAnanke.pdf (LaTeX master: docs/book/main.tex)
make clean TARGET=RASPI # that board's outputs and build/aarch64/kernel
# The kernel in QEMU (OVMF / AAVMF / EDK2), one architecture at a time -- boots v4
# The PC stick, written to a real USB stick (checks the device, asks you to type its name back,
# verifies the write); then boot it from the PC's firmware boot menu
make write_stick DEVICE=/dev/sdX
# The kernel in QEMU (OVMF / AAVMF / EDK2), one architecture at a time -- boots v4 from a fresh
# data stick, so every boot is a stick's first boot
make -f kernel/Makefile ARCH=amd64 clean qemu
make -f kernel/Makefile ARCH=aarch64 clean qemu
make -f kernel/Makefile ARCH=riscv64 clean qemu
make -f kernel/Makefile ARCH=amd64 clean qemu-stick-high # the PC stick itself, loaded high
make -f kernel/Makefile ARCH=amd64 KERNEL_ARGS=system=v3 clean qemu # v3, while it remains
# The Pi 5's native boot path, rehearsed on QEMU's virt machine at EL2
@@ -123,7 +148,8 @@ which to believe. Among them:
| | |
|---|---|
| [The FABRIC record](docs/fabric/) | Every design decision and the work as it happened (`FABRIC-3.md` is the living one) |
| [The FABRIC record](docs/fabric/) | Every design decision and the work as it happened (`FABRIC-3.md` is the living one) — published as *The Book of Fabric* from alpha.4 |
| [The stick](docs/v4.0.0/STICK.md) | The x86-64 StarshipOS stick: plug and play, the proxy Zuse, growth |
| [StarForth v4](docs/v4.0.0/) | The F18-derived engine |
| [Board bring-up](boards/BRINGUP.md) | Getting onto a PC, the Pi 5 and the Mars |
| [Roadmap and versioning](docs/reference/ROADMAP.md) | Milestone plan and release-versioning policy |
+8 -1
View File
@@ -168,7 +168,14 @@ carrying timestamp noise in git history.
image's bytes, each exactly its file's size), fresh before every boot, and
that is `ZUSEDISK`'s default; `make boot_image TARGET=PC
STICK_PAIR=disk/zuse-scratch` puts the pair in the PC stick the same way.
The files here are unchanged. Increment 5 retires the pair.
The files here are unchanged.
**For tests and v3 only (2026-11-08, plan 2026-10-29-stick-5, Task 3):** a
v4 `qemu` boot no longer attaches the pair; it attaches a fresh data stick,
whose first boot mints its own Zuse. The pair stays for the tests that ask
for a known Zuse by name (`scripts/qemu_session.py`'s `stick_zuse`,
`two_sticks`, `stick_artemis`, `raw_ident`, `v3_keys`, the hot-plug and GPT
modes) and as the defaults of a `system=v3` boot.
- **The StarshipOS stick and data stick are not here** (2026-10-27,
`docs/v4.0.0/STICK.md` §4, §9): they are build output, made fresh by
+142
View File
@@ -6303,3 +6303,145 @@ failed was right to: it refuses a line that is not what was printed. The capture
stays headless"; minting Zuse on a stick's first boot (`docs/v4.0.0/STICK.md` section 6) is #92.
**Ruled:** #92 into alpha.4, so the PC stick downloaded from alpha.4 on boots to
`[zuse@Hera] ok>` at its first boot.
### 8. #92, Task 1: the proxy Zuse -- a stick's first boot mints its own (2026-11-08)
Plan `docs/v4.0.0/plans/2026-10-29-stick-5-proxy-zuse-and-real-zuse.md`, Task 1; `STICK.md` section 6.
- **Built:** the genesis marker's version 2 (`zuse_genesis_marker_v2_t`: the proxy's key and the
real Zuse's, zero until she is minted), read and written by the v4 boot alone
(`kernel/src/v4/sk_v4_marker.c`; a version 1 marker -- the minted pair's -- reads as a proxy with
no real Zuse). The identity check and the genesis mint are split out of v3's
`capsule_zuse_boot.c` (`capsule_zuse_boot_check_key`, `capsule_zuse_boot_genesis_mint`) as D1
split the check from the VM; v3's callers are unchanged in behaviour. On v4
(`sk_v4_identity.c`), a stick with no marker and a blank identity partition mints the proxy Zuse,
reads her back, and only then writes the marker that names her; she is logged in. A marker with a
real key gives the proxy no session (the fixed screen is Task 5).
- **Tested first, seen to fail:** `genesis` (a fresh data stick, booted twice) failed on amd64 with
"Zuse: no genesis on this disk -- the system stays headless", both boots. After: `genesis` passes
on all three ISAs (first boot minted, second recognised, not minted again); `stick_genesis` -- the
PC stick as built, no `STICK_PAIR` -- reaches `[zuse@Hera] ok>` with nothing set up: plug and play.
Regressions pass: `zuse`, `stick_boot`, `stick_zuse`, `stick_artemis`, `two_sticks`,
`artemis_unsigned`, `raw_ident`, `hotplug`, `midpull`, `waitpull`, `typeahead`, the seven GPT
modes, `v3_keys`.
- **My slip, written down:** `stick_boot` and `stick_artemis` were first run without
`KERNEL_ARGS=--log-level=info`, which their disk-size checks read; they failed on that check alone,
and passed when rerun at the info level. Both runs' logs are in the tree.
- **Left as it is (the plan's order):** a genesis whose marker write fails leaves Zuse on the
identity partition with no marker naming her; that stick then logs no one in until it is
rewritten. Said once, "Zuse: genesis marker write failed -- headless".
- **Accepted** (`scripts/nightly.sh accept` amd64, aarch64, riscv64, stick-high; `make -C v4
test-32`): `PARITY:V4_POST tests=538 pass=538 fail=0` and `POST: PASSED` on all three and the
stick loaded high; `dict_hash 0xfec8c47cfc6f437f` on the three, unchanged (Task 1 adds no word);
test-32: 39 programs, 0 failures.
### 9. #92, Task 2: Artemis grows to fill the stick (2026-11-08)
Plan `2026-10-29-stick-5`, Task 2; `STICK.md` 5a (its 2 TiB cap amended to 256 GiB, R1).
- **Built:** a GPT writer (`gpt_grow_last`, `kernel/src/gpt.c`): the backup entry array and header
moved to the disk's end, the last partition grown to the last usable sector (whole MiB, capped),
both headers' CRCs, the backup written before the primary, the protective MBR's size. The volume
grown to its partition (`kernel/src/v4/sk_v4_grow.c`): its fence -- the Artemis signature and
Zuse's genesis marker -- moved to the new top, the header written last. Metadata only. The image
builder formats the stick's and the data stick's Artemis with a BAM sized for 256 GiB
(`mkartemis --bam-for`, 6144 devblocks), so the grown blocks are tracked already.
- **Found while building, and followed:** the block subsystem places a volume's fence by its
device's size, not by its header (`blk_format_or_load_disk`), so a volume must always fill its
partition. The partition is therefore grown no further than the volume's BAM tracks, and the
volume grown before Artemis's signature is checked or the disk attached.
- **Tested first, seen to fail:** `stick_grow` (a 16 GiB copy) -- no growth, 1137649 user blocks,
`sfdisk`: the backup GPT not at the end; `stick_small` (4 GiB) -- no line; `check_images.sh` --
the two BAM checks. After: `stick_grow` grows Artemis to 12129370 user blocks and reaches the
prompt 8 s after POST; the second boot of the same copy is not grown again and recognises Zuse;
`sfdisk --verify`: no errors. `stick_small`: "under 8 GB -- not grown". Regressions pass:
`genesis` (three ISAs), `stick_genesis`, `stick_boot`, `stick_zuse`, `two_sticks`,
`artemis_unsigned`, `midpull`.
- **Accepted:** 538/538 and `POST: PASSED` on the three and the stick loaded high; `dict_hash
0xfec8c47cfc6f437f` on the three; test-32: 39 programs, 0 failures.
- **For a ruling (not changed):** `blk_flush` rewrites the whole on-disk BAM -- it reads and writes
every BAM page (`bam_flush_to_disk`) on each flush of a dirty block -- and attach reads the whole
BAM. With the BAM sized for 256 GiB, that is 24 MiB each way per flush, where the 2 GiB Artemis's
own BAM was about 140 KiB. Nothing in acceptance flushes a disk block, so it does not show there.
Recommended: flush and read only the BAM pages that hold a volume's user blocks (the same bytes
on disk, v3's behaviour unchanged); it is shared v3 code, so it waits for Captain Bob.
### 10. Retire v3 (2026-11-08)
- **Ruled** (Captain Bob): "v3 dependencies for v4 should be moved to v4 and the v3 code retired and
removed" -- after #92 ships the plug-and-play stick in alpha.4, as **its own milestone**, "Retire
v3" (first placed in alpha.5; then "That is its own milestone"). #156.
- **What v4 takes from v3 today:** the block layer (`block_subsystem.c`, `blkio`, `log`, the
platform time) and the `VM *` type in two kernel headers. The v4 engine includes nothing from v3;
a v4 boot branches to `sk_v4_run()` before v3's VM is set up.
- **My calls, open to a ruling when alpha.5 starts** (no preference given): tag the tree first
(`archive/v3-final`); the block layer to `v4/storage/`; `proof/` (all 52 theories are of the v3
VM) archived under the tag and removed with the nightly `proofs` stage; the v3-only features --
the fleet, the word ACL, MINT/WIREBIND, the DoE runtime -- go with v3, their designs kept here and
in the tag, for v4 to rebuild.
- **Also filed** (#155, alpha.4, for a ruling): a block flush rewrites the whole BAM, 24 MiB each way
now that the stick's BAM is sized for 256 GiB (section 9).
### 11. The documents on the .com: the Book of Fabric and the dictionary (2026-11-08)
- **Ruled** (Captain Bob): "some of our document built pdf's should be published on .com; The Book of
Fabric and a 'dictionary' document with the word, stack notations and descriptions. Alphabetical."
-- v4's words only; a **Documents** page on the .com, beside Downloads; with **alpha.4**. #138 (the
Book of Fabric, already in alpha.4) and #157 (the dictionary and the page).
- **My call:** the dictionary's names come from the live system's word list, joined at build to a
table of stack notations and descriptions in the tree, and the build fails when a live word has
no entry -- so it cannot fall behind v4's 317 words (`docs/reference/DICTIONARY.md` is v3's, and
goes with v3).
- **Ruled** (Captain Bob, the same day): the Book of Fabric is **published** with alpha.4 -- asked
because the record goes well past the SSRN whitepaper that everything published so far is based
on (the license has been reviewed): "Publish. Fabric is all about steady state."
### 12. A DoE per release (2026-11-08)
- **Ruled** (Captain Bob): "a pipeline that will run and publish a DoE of some small kind we can use
to support patent claims to a SMALL degree ... R and LaTeX ... published each release on .com's
XWiki with charts and tables in the XWiki dialect. This will be a milestone too." Milestone **DoE
per release**, #158.
- **Found:** the R and LaTeX pipeline exists (`experiments/bare_metal/analysis/`), but it measured
v3's physics runtime, which goes with v3 (#156), and no DoE has run since 2026-09-16 (#141). So
the per-release DoE measures v4, from the release's own image.
- **My calls:** the design fixed and published before it runs; effect sizes with confidence
intervals; every run reported, failures included; the report states its limits (TCG, one server,
the sample). Rulings left for the milestone's start: the claim, the factors, the time budget,
charts as R images or XWiki's `{{chart}}` macro, where the pages sit.
### 13. #92, Task 3: every acceptance run is a first boot (2026-11-08)
- **Built:** a v4 `qemu` boot attaches a fresh data stick and nothing else (`kernel/Makefile`:
`DATASTICK` on, `ARTDISK`/`ZUSEDISK` empty, unless `KERNEL_ARGS` holds `system=v3`, whose defaults
are unchanged); `scripts/qemu_session.py` boots the Makefile's defaults except for the modes that
ask for the minted pair by name, or for no drive; `scripts/nightly.sh accept stick-high` boots the
PC stick as built (`stick_genesis`). `.claude/CLAUDE.md` ("The disks"), `disk/README.md` (the
pair: tests and v3 only), `STICK.md` 11 follow.
- **Tested first, seen to fail:** `zuse` on the old defaults -- the pair's "identity confirmed", no
genesis line.
- **Accepted:** amd64, aarch64, riscv64 each mint Zuse on a fresh data stick and reach the prompt,
538/538; the PC stick as built, loaded high, the same; `dict_hash 0xfec8c47cfc6f437f` on the
three; test-32 39 programs, 0 failures. Regressions pass: `stick_zuse`, `raw_ident`, `headless`,
`hotplug`, the seven GPT modes, `entropy` on the three.
- **One failure, and its rerun:** `v3_keys` failed once -- Hestia logged `virtio_blk: request never
completed` and the v3 boot stalled reading Zuse's marker over virtio; its rerun passed with no such
line. Task 3 changes no drive a v3 boot gets, so it is counted as v3's virtio path under load, not
a regression -- written down here, since a lost virtio request is a fault of its own (v3 goes with
#156).
### 14. #155: a BAM flush moves only the pages that hold the volume (2026-11-08)
- **Ruled** (Captain Bob, "Next up #155"): the change recommended in section 9.
- **Built:** `bam_flush_to_disk()` and `bam_sync_from_disk()` (`v3/src/block_subsystem.c`, the block
layer v4 runs on) read and write only the BAM pages that hold a slot's bits -- its reserved bits
and one per user block (`bam_pages_used()`). The pages past them are never set, so the bytes on
disk are the same; v3's behaviour is unchanged.
- **Tested first, seen to fail:** `bam_flush` (the PC stick grown to 16 GiB; three `SAVE-BUFFERS` of
an Artemis block, timed; the BAM hashed): 5.1, 5.6, 6.1 s against a limit of 2 s -- set after
seeing that baseline, written down so. After: 1.1 s each. The BAM's bytes the same either way.
- **Accepted:** 538/538 and `POST: PASSED` on the three and the stick loaded high, `dict_hash
0xfec8c47cfc6f437f`, test-32 39 programs, 0 failures; regressions pass, `v3_keys` among them (v3
runs on the same code).
+13 -4
View File
@@ -122,9 +122,13 @@ gains the partitions below). Three partitions:
- **The minimum stick: 8 GB.** Sticks on the shelf are 16–64 GB; 8 GB is the floor.
- **The identity partition stays 500 MiB.** About half a million 1 KiB blocks for Zuse's keys and
her own pool.
- **Artemis grows to fill the stick at its first boot (§5a),** up to **2 TiB** for the partition
(the block layer numbers 1 KiB blocks with 32 bits: 4 TiB is its hard limit; 2 TiB keeps a margin
and is past any thumb drive). Space past 2 TiB is left unused, and the boot says so.
- **Artemis grows to fill the stick at its first boot (§5a),** up to **256 GiB** for the partition
(**amended 2026-10-29**, Captain Bob: "256 GiB is ruled" -- plan
`plans/2026-10-29-stick-5-proxy-zuse-and-real-zuse.md`, R1. This said 2 TiB: the block layer
numbers 1 KiB blocks with 32 bits, so 4 TiB is its hard limit, but the block subsystem keeps two
bytes of kernel heap per block and the heap is 2 GiB, so a 2 TiB Artemis could not attach; 256 GiB
takes about 384 MiB. The stick's Artemis is formatted with a BAM sized for 256 GiB, so growth
writes metadata only.) Space past 256 GiB is left unused, and the boot says so.
- **A stick under 8 GB** is not grown: it runs at the 2 GiB it was written with, and the boot says
so.
- **The Artemis partition is formatted when the image is built (my call),** not on first boot:
@@ -168,7 +172,7 @@ Before genesis, on a stick whose GPT ends where the 2 GiB image ended and whose
first boot of a freshly written stick), the kernel grows Artemis:
- It moves the backup GPT header and entry array to the disk's end, extends the Artemis partition's
last LBA to the end of the usable space (capped at 2 TiB of partition), and rewrites both headers
last LBA to the end of the usable space (capped at 256 GiB of partition, amended -- §4), and rewrites both headers
with their CRCs (the GPT writer; `INSTALL` reuses it).
- It grows Artemis's volume to the partition: its `STFR` header's size, its free map for the new
blocks, and its metadata fence (with the genesis marker's slot) moved to the new top, as the block
@@ -348,6 +352,9 @@ first and seen to fail:
`qemu` targets behind `DATASTICK=1`, off by default -- until increments 4 and 5 the kernel cannot
take Artemis from it or mint Zuse onto it, so as the default it would leave every acceptance boot
headless. Increment 5 turns it on and retires the scratch pair and the virtio disk.
**Done 2026-11-08** (plan `2026-10-29-stick-5`, Task 3): a v4 `qemu` boot attaches a fresh data
stick and nothing else; the scratch pair stays only for the tests that ask for it and for
`system=v3`.
4. **Artemis and Zuse from one disk:** the boot device from the loader, the partitions found and
attached, virtio Artemis off the v4 path; recognition of a minted stick; entropy on the v4 path;
`system=v3` refused on a stick (§4, §5).
@@ -357,6 +364,8 @@ first and seen to fail:
recorded) and a 4 GB one (below the minimum: not grown, said so).
**Amended 2026-10-29:** the genesis is the proxy's, with the version 2 marker (§6); the fresh
stick's first boot reaching `[zuse@Hera] ok>` with nothing set up is the test of plug and play.
**Done 2026-11-08** (plan `2026-10-29-stick-5`, Tasks 1-3; `FABRIC-3.md` XLVIII.8-9): growth is
capped at 256 GiB (R1); every acceptance run is now a first boot.
5a. **The real Zuse stick (2026-10-29)** (§6a): `MINT-ZUSE` and its confirmation, the GPT and
identity written to the second stick, the marker's real key; recognition of the real Zuse
stick; the fixed screen and its R; the old stick refused after a replacement.
@@ -146,7 +146,7 @@ xHCI USB sticks, `scripts/qemu_session.py`.
- **The Artemis partition must be formatted to take the marker:** `blk_subsys_confirm_format` only
if the slot is provisional and its `artemis_sig_t` checked out (§4).
- [ ] **Step 1: Failing tests** (harness):
- [x] **Step 1: Failing tests** (harness):
- **`genesis`** (three ISAs): a fresh data stick (`DATASTICK=1 ZUSEDISK=`), built once into the
session directory (`DATASTICK_IMG=<work>/data.img DATASTICK_DEP=`) and booted twice, one QEMU at
a time. First boot: the genesis line, `[zuse@Hera] ok> `, `3 4 + .` → `7 ok`. Second boot:
@@ -155,12 +155,12 @@ xHCI USB sticks, `scripts/qemu_session.py`.
reaches the prompt. Today: FAIL (headless).
- **Changed:** `stick_boot` expected the blank stick headless; it now expects the genesis line and
the prompt.
- [ ] **Step 2:** Run each: FAIL as listed.
- [ ] **Step 3:** Implement.
- [ ] **Step 4:** The new sessions pass; regression: `zuse` (the pair, version 1: logs in as the
- [x] **Step 2:** Run each: FAIL as listed.
- [x] **Step 3:** Implement.
- [x] **Step 4:** The new sessions pass; regression: `zuse` (the pair, version 1: logs in as the
proxy), `stick_zuse`, `stick_artemis`, `two_sticks`, `artemis_unsigned`, `raw_ident`, `hotplug`,
`midpull`, `waitpull`, `typeahead`, the GPT modes, `v3_keys` (v3's genesis and marker unchanged).
- [ ] **Step 5:** Suite; full acceptance; commit `feat(kernel): the proxy Zuse -- a stick's first
- [x] **Step 5:** Suite; full acceptance; commit `feat(kernel): the proxy Zuse -- a stick's first
boot mints its own Zuse; the genesis marker's version 2` with the logs.
### Task 2: Artemis grows to fill the stick
@@ -195,7 +195,7 @@ xHCI USB sticks, `scripts/qemu_session.py`.
GPT, open Artemis, `sk_v4_grow_artemis`, then on as Task 1. Under 8 GB → the "not grown" line,
once. Past the cap → the "left unused" line.
- [ ] **Step 1: Failing tests:**
- [x] **Step 1: Failing tests:**
- **`stick_grow`** (amd64, `--target qemu-stick --stick-gib 16`): first boot: `grown to fill the
stick`, Artemis's `blk: disk` line over 12000000 user blocks (`KERNEL_ARGS=--log-level=info`),
the genesis line, the prompt; the first boot's time printed by the harness (POST to prompt).
@@ -205,11 +205,11 @@ xHCI USB sticks, `scripts/qemu_session.py`.
prompt. Today: FAIL (no line).
- **`check_images.sh`:** the PC stick's and data stick's Artemis BAM is the cap's size
(`mkartemis --check` reports it). Today: FAIL.
- [ ] **Step 2:** Run each: FAIL as listed.
- [ ] **Step 3:** Implement.
- [ ] **Step 4:** They pass; regression: `genesis`, `stick_genesis`, `stick_zuse`, `two_sticks`,
- [x] **Step 2:** Run each: FAIL as listed.
- [x] **Step 3:** Implement.
- [x] **Step 4:** They pass; regression: `genesis`, `stick_genesis`, `stick_zuse`, `two_sticks`,
`artemis_unsigned`, `midpull` (replug: not grown again).
- [ ] **Step 5:** Suite; full acceptance; commit `feat(kernel): Artemis grows to fill the stick at
- [x] **Step 5:** Suite; full acceptance; commit `feat(kernel): Artemis grows to fill the stick at
its first boot -- metadata only, capped at 256 GiB` with the logs and the first-boot time.
### Task 3: acceptance on a fresh data stick
@@ -227,13 +227,13 @@ xHCI USB sticks, `scripts/qemu_session.py`.
**Interfaces:** `make -f kernel/Makefile ARCH=<arch> clean qemu` boots v4 with a fresh data stick
on port 2 and no other drive: a first boot every time, the proxy minted, the prompt.
- [ ] **Step 1: Failing test:** `zuse` with the new default (no `--make`): the genesis line and the
- [x] **Step 1: Failing test:** `zuse` with the new default (no `--make`): the genesis line and the
prompt on all three ISAs. Today: FAIL (the pair is the default; no genesis line).
- [ ] **Step 2:** Run it: FAIL.
- [ ] **Step 3:** Change the defaults and the docs.
- [ ] **Step 4:** `zuse` passes on three ISAs; `qemu-stick-high` reaches the prompt from a fresh
- [x] **Step 2:** Run it: FAIL.
- [x] **Step 3:** Change the defaults and the docs.
- [x] **Step 4:** `zuse` passes on three ISAs; `qemu-stick-high` reaches the prompt from a fresh
PC stick; regression: `v3_keys`, `stick_zuse`, `raw_ident`, the GPT modes, `entropy`.
- [ ] **Step 5:** Suite; full acceptance as newly written; commit `test(build): acceptance boots a
- [x] **Step 5:** Suite; full acceptance as newly written; commit `test(build): acceptance boots a
fresh data stick -- every run is a first boot` with the logs.
### Task 4: `MINT-ZUSE` -- the real Zuse onto a second stick

Some files were not shown because too many files have changed in this diff Show More