Compare commits
86
Commits
v4.0.0-alpha.1
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
594d2f93f0 | ||
|
|
411193166c | ||
|
|
186680724e | ||
|
|
929f0e13c5 | ||
|
|
1354b30a78 | ||
|
|
d2c11d4b6f | ||
|
|
cd579c8ec1 | ||
|
|
c0d0d03986 | ||
|
|
52f48ed2a9 | ||
|
|
b399cb7c35 | ||
|
|
bc0faa69df | ||
|
|
28f9f317ba | ||
|
|
47b8eb262b | ||
|
|
d2353a5f67 | ||
|
|
190b0e8b05 | ||
|
|
0f70f69e06 | ||
|
|
a55571b25d | ||
|
|
e60cb5c245 | ||
|
|
24db454141 | ||
|
|
792e736bc0 | ||
|
|
eca00628f0 | ||
|
|
9d6410c06f | ||
|
|
ec9eb5f225 | ||
|
|
e26c809a17 | ||
|
|
def2336fc4 | ||
|
|
f81b5d0563 | ||
|
|
a5c1136692 | ||
|
|
4bc8a01b4c | ||
|
|
7dbc1de864 | ||
|
|
add73563b2 | ||
|
|
5bb247d678 | ||
|
|
4e935e4825 | ||
|
|
4c38a7b1e6 | ||
|
|
96bc60883d | ||
|
|
a58ddbfc24 | ||
|
|
c587678dbd | ||
|
|
b4d673f929 | ||
|
|
0b49d03526 | ||
|
|
6627f710b2 | ||
|
|
7dca7fb699 | ||
|
|
715c09a9d1 | ||
|
|
c38f4f4965 | ||
|
|
8b1ba39040 | ||
|
|
429eb72aa2 | ||
|
|
91a7150276 | ||
|
|
607ae1c2da | ||
|
|
da800ce844 | ||
|
|
cff3787b92 | ||
|
|
dc9a086603 | ||
|
|
bcd51cb33d | ||
|
|
19a8a036c2 | ||
|
|
258842aafc | ||
|
|
727a707580 | ||
|
|
634a49b533 | ||
|
|
56e4d60844 | ||
|
|
68919741fc | ||
|
|
0e1c9650b4 | ||
|
|
9ed9cf1ad0 | ||
|
|
bfe3506aec | ||
|
|
e695eadaf7 | ||
|
|
8f1ba02b3c | ||
|
|
a293eab1d4 | ||
|
|
cac4e7fb50 | ||
|
|
199720e769 | ||
|
|
d54e2fe276 | ||
|
|
44264d0781 | ||
|
|
55613350c4 | ||
|
|
f747ab78a6 | ||
|
|
1928d53b6b | ||
|
|
a083c5b834 | ||
|
|
88b962b29e | ||
|
|
4d0b9ab771 | ||
|
|
0dbad0f278 | ||
|
|
6bbf4b1afd | ||
|
|
1e3f211daa | ||
|
|
171b3947dd | ||
|
|
1d4898496f | ||
|
|
777f739708 | ||
|
|
b8951bc26b | ||
|
|
50d2bc98d9 | ||
|
|
2d43db252a | ||
|
|
37f62d688b | ||
|
|
cabe974872 | ||
|
|
4a125cdd21 | ||
|
|
d8bf2e1121 | ||
|
|
04006bff12 |
+15
-11
@@ -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=amd64 clean qemu
|
||||||
make -f kernel/Makefile ARCH=aarch64 clean qemu
|
make -f kernel/Makefile ARCH=aarch64 clean qemu
|
||||||
make -f kernel/Makefile ARCH=riscv64 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
|
# ...the PC stick loaded above 2 GiB, as a PC's firmware loads it (pc machine, 3 GiB; the stick as
|
||||||
# Zuse's pair in the stick: scripts/qemu_session.py stick_zuse amd64 --target qemu-stick-high):
|
# 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
|
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
|
# ...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):
|
# 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
|
timestamped convention (self-documented via its own README); not a contradiction, just a
|
||||||
second, less-structured log location.
|
second, less-structured log location.
|
||||||
|
|
||||||
**The disks (Captain Bob, 2026-10-26, the identity gate):** with no identity thumbdrive the system
|
**The disks (plan 2026-10-29-stick-5, Task 3, 2026-11-08):** with no identity the system is
|
||||||
is headless -- no prompt -- so every boot needs Zuse. `kernel/Makefile`'s `ARTDISK` and `ZUSEDISK`
|
headless -- no prompt -- so every boot needs Zuse. A v4 `qemu` boot attaches a **fresh data stick**
|
||||||
default to the minted Zuse pair, `disk/zuse-scratch/artemis.img` and `zuse-thumb-ident.img` (a
|
(`DATASTICK`, `make ... datastick`, `build/<arch>/kernel/datastick.img`: identity and Artemis
|
||||||
pair: her genesis marker is on that Artemis disk; `disk/README.md`). Since 2026-10-28 `ZUSEDISK`
|
partitions, made fresh for every boot) and nothing else: its first boot mints the stick's proxy
|
||||||
is that pair laid out as a stick (`make ... zusestick`, `build/<arch>/kernel/zusestick.img`, made
|
Zuse (STICK.md §6), so **every acceptance run is a first boot** -- plug and play. `DATASTICK=`
|
||||||
fresh for every boot: identity and Artemis partitions on one USB disk, STICK.md §4); `ARTDISK`
|
boots v4 with no drive (headless). The minted Zuse pair (`disk/zuse-scratch/`, `disk/README.md`)
|
||||||
stays the pair's Artemis file. v3 reads identity drives raw, never through a GPT, so a `system=v3`
|
is for the tests that ask for it by name (`scripts/qemu_session.py`: `stick_zuse`, `two_sticks`,
|
||||||
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`)
|
`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> `.
|
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
|
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 three;
|
||||||
- **the PC stick loaded high** (Captain Bob, 2026-10-29, after the SER5 page-faulted in the
|
- **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`
|
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;
|
`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;
|
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
|
- **the 32-bit build** (Captain Bob, 2026-10-14: "the 32 bit build needs to go into the
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#
|
#
|
||||||
# org.starship:kernelImage:<LITHOS_VERSION>-SNAPSHOT, starshipos-snapshots
|
# org.starship:kernelImage:<LITHOS_VERSION>-SNAPSHOT, starshipos-snapshots
|
||||||
# classifier pc StarshipOS.iso amd64, UEFI -- the ISO the amd64 acceptance boot booted
|
# classifier pc StarshipOS.iso amd64, UEFI -- the ISO the amd64 acceptance boot booted
|
||||||
|
# classifier pc-stick pc-stick.img.xz a PC's USB stick, for any UEFI PC (make boot_image TARGET=PC)
|
||||||
# classifier raspi5 raspi5.img.xz Raspberry Pi 5, for Raspberry Pi Imager
|
# classifier raspi5 raspi5.img.xz Raspberry Pi 5, for Raspberry Pi Imager
|
||||||
# classifier milkv MilkV.img.xz Milk-V Mars
|
# classifier milkv MilkV.img.xz Milk-V Mars
|
||||||
# classifier logs logs.tar.gz this run's serial logs and DoE CSVs (the proof log is in
|
# classifier logs logs.tar.gz this run's serial logs and DoE CSVs (the proof log is in
|
||||||
|
|||||||
@@ -2,9 +2,14 @@
|
|||||||
# acceptance protocol, the proofs, the board images -- and the documents, and publishes both to
|
# acceptance protocol, the proofs, the board images -- and the documents, and publishes both to
|
||||||
# starshipos-releases at that version:
|
# starshipos-releases at that version:
|
||||||
#
|
#
|
||||||
# org.starship:kernelImage:<version> classifiers pc, raspi5, milkv, logs (nightly.yml)
|
# org.starship:kernelImage:<version> classifiers pc, pc-stick, raspi5, milkv, logs (nightly.yml)
|
||||||
# org.starship:documentation:<version> classifiers book, vol1, vol2, vol3, api (nightly-docs.yml)
|
# org.starship:documentation:<version> classifiers book, vol1, vol2, vol3, api (nightly-docs.yml)
|
||||||
#
|
#
|
||||||
|
# and makes the tag a Gitea release -- a pre-release for v<x.y.z>-alpha.N and the like -- with the
|
||||||
|
# images, SHA256SUMS, the documents and the StarshipOS Root CA's certificate attached, for anyone
|
||||||
|
# to download (#126; scripts/nightly.sh gitea-release). Needs the secret RELEASE_TOKEN: a token
|
||||||
|
# that may write the repository.
|
||||||
|
#
|
||||||
# The tag must name the version the tree says it is: v<LITHOS_VERSION> (kernel/Makefile). A tag
|
# The tag must name the version the tree says it is: v<LITHOS_VERSION> (kernel/Makefile). A tag
|
||||||
# that does not is refused before anything is built. A release repository takes a version once.
|
# that does not is refused before anything is built. A release repository takes a version once.
|
||||||
name: Release
|
name: Release
|
||||||
@@ -54,7 +59,10 @@ jobs:
|
|||||||
echo "NIGHTLY_VERSION=${tree#v}" >> "$GITHUB_ENV"
|
echo "NIGHTLY_VERSION=${tree#v}" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
- name: Install the dependencies
|
- name: Install the dependencies
|
||||||
run: make ARCH=amd64,aarch64,riscv64 init # the image has all but the documents' packages
|
# INIT_PROOFS=0: the image's Isabelle has HOL-Library prebuilt; a full init would fetch a fresh
|
||||||
|
# Isabelle into the workspace and point isabelle at it, and the proofs would build HOL-Library
|
||||||
|
# from scratch -- killed (release run 196, v4.0.0-alpha.1)
|
||||||
|
run: make ARCH=amd64,aarch64,riscv64 init INIT_PROOFS=0 # the image has all but the documents' packages
|
||||||
|
|
||||||
- name: Acceptance amd64
|
- name: Acceptance amd64
|
||||||
run: scripts/nightly.sh accept amd64
|
run: scripts/nightly.sh accept amd64
|
||||||
@@ -81,6 +89,11 @@ jobs:
|
|||||||
scripts/nightly.sh publish https://nexus.starshipos-f18.org/repository/starshipos-releases
|
scripts/nightly.sh publish https://nexus.starshipos-f18.org/repository/starshipos-releases
|
||||||
scripts/nightly.sh publish-docs https://nexus.starshipos-f18.org/repository/starshipos-releases
|
scripts/nightly.sh publish-docs https://nexus.starshipos-f18.org/repository/starshipos-releases
|
||||||
|
|
||||||
|
- name: Gitea release # the downloads anyone can fetch (#126): no Nexus login
|
||||||
|
env:
|
||||||
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} # a token that may write the repository
|
||||||
|
run: scripts/nightly.sh gitea-release "${{ github.ref_name }}"
|
||||||
|
|
||||||
- name: Keep the release
|
- name: Keep the release
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-11-07 — LithosAnanke v4.0.0-alpha.3: the first published alpha
|
||||||
|
|
||||||
|
`v4.0.0-alpha.2` (`2d43db25`) used the image's HOL-Library as intended, but its release run (200) ran
|
||||||
|
the proofs with Isabelle's defaults -- Java's heap up to 4 GiB, a thread per CPU -- and they were
|
||||||
|
killed in the StarForth session. Nothing was published; the tag stays where it is. The proofs now run
|
||||||
|
capped (`scripts/nightly.sh proofs`: one thread, Java 512 MiB, Poly/ML 900 MiB; 47 s, ~1.8 GiB), and
|
||||||
|
`v4.0.0-alpha.3` is the first alpha published. `docs/fabric/FABRIC-3.md` XLVII.6.
|
||||||
|
|
||||||
|
## 2026-11-07 — LithosAnanke v4.0.0-alpha.2: not published
|
||||||
|
|
||||||
|
`v4.0.0-alpha.1` (`233025da`) was accepted and tagged, but its release run (196) built HOL-Library
|
||||||
|
from scratch in the proofs step and was killed: `release.yml`'s full `make init` replaced the
|
||||||
|
image's Isabelle, the one with HOL-Library prebuilt. Nothing was published; the tag stays where it is
|
||||||
|
(Captain Bob, 2026-11-07). `release.yml` now runs `init INIT_PROOFS=0`, and `v4.0.0-alpha.2` is the
|
||||||
|
first alpha published -- the same system as below. `docs/fabric/FABRIC-3.md` XLVII.5.
|
||||||
|
|
||||||
## 2026-11-07 — LithosAnanke v4.0.0-alpha.1: the first alpha release
|
## 2026-11-07 — LithosAnanke v4.0.0-alpha.1: the first alpha release
|
||||||
|
|
||||||
The first alpha of the kernel, `v4.0.0-alpha.1`: v4, StarForth's F18 engine, is the system every
|
The first alpha of the kernel, `v4.0.0-alpha.1`: v4, StarForth's F18 engine, is the system every
|
||||||
|
|||||||
@@ -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
|
**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.
|
runs StarForth as its sole userspace runtime. No libc. No OS. Just stone and necessity.
|
||||||
|
|
||||||
*Lithos* (foundation) + *Ananke* (necessity) — the kernel under StarshipOS.
|
*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
|
## 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
|
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
|
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
|
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 | StarForth VM integration + parity validation | ✅ Complete |
|
||||||
| M7.1 | Capsule birth · Mama FORTH vocabulary · the Tripod fleet · kernel-Hermes · word-level ACL | ✅ Live |
|
| 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 |
|
| 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` |
|
| 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
|
**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**,
|
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`.
|
`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
|
### What's live
|
||||||
|
|
||||||
- **The Tripod** — a named multi-VM fleet: **Hera** (the Mama VM, the governor), **Artemis**
|
- **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,
|
- **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
|
`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.
|
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
|
- **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
|
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.
|
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
|
- **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
|
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%,
|
`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 docs # build/docs/LithosAnanke.pdf (LaTeX master: docs/book/main.tex)
|
||||||
make clean TARGET=RASPI # that board's outputs and build/aarch64/kernel
|
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=amd64 clean qemu
|
||||||
make -f kernel/Makefile ARCH=aarch64 clean qemu
|
make -f kernel/Makefile ARCH=aarch64 clean qemu
|
||||||
make -f kernel/Makefile ARCH=riscv64 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
|
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
|
# 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 |
|
| [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 |
|
| [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 |
|
| [Roadmap and versioning](docs/reference/ROADMAP.md) | Milestone plan and release-versioning policy |
|
||||||
|
|||||||
+4
-1
@@ -3,7 +3,10 @@
|
|||||||
# 2026-11-07: "New root CA on the CI box. Valid StarshipOS rather than snake oil intermediate").
|
# 2026-11-07: "New root CA on the CI box. Valid StarshipOS rather than snake oil intermediate").
|
||||||
#
|
#
|
||||||
# StarshipOS Root CA Ed25519, 20 years, self-signed. Its key never leaves this box:
|
# StarshipOS Root CA Ed25519, 20 years, self-signed. Its key never leaves this box:
|
||||||
# not in the repository, not in Gitea, not in any image.
|
# not in the repository, not in Gitea, not in any image. Its
|
||||||
|
# certificate (public) is ci/pki/starshipos-root-ca.pem, made on
|
||||||
|
# 2026-11-07, SHA-256 in starshipos-root-ca.sha256; every release
|
||||||
|
# attaches it.
|
||||||
# StarshipOS Capsule Signing Ed25519, 10 years, signed by the root; CA:TRUE, pathlen:0.
|
# StarshipOS Capsule Signing Ed25519, 10 years, signed by the root; CA:TRUE, pathlen:0.
|
||||||
# Its certificate is built into every image (capsules/pki/
|
# Its certificate is built into every image (capsules/pki/
|
||||||
# starshipos-intermediate.der) and checks each capsule at boot;
|
# starshipos-intermediate.der) and checks each capsule at boot;
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBaDCCARqgAwIBAgIUCwt1JkPxCfwr9PTCOadol/m9PCQwBQYDK2VwMDIxEzAR
|
||||||
|
BgNVBAoMClN0YXJzaGlwT1MxGzAZBgNVBAMMElN0YXJzaGlwT1MgUm9vdCBDQTAe
|
||||||
|
Fw0yNjExMDcxNjUwNTZaFw00NjExMDcxNjUwNTZaMDIxEzARBgNVBAoMClN0YXJz
|
||||||
|
aGlwT1MxGzAZBgNVBAMMElN0YXJzaGlwT1MgUm9vdCBDQTAqMAUGAytlcAMhANcn
|
||||||
|
fPpowbNgzMPtDEA7EYJoSkBLPljM6dEBFONfrhHso0IwQDAPBgNVHRMBAf8EBTAD
|
||||||
|
AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU5eU4Iy/Al5g9KZI5+u4jKllG
|
||||||
|
shswBQYDK2VwA0EAjRK1ybZE/VaH31dt3sc8DgqJVTPB6CYovdqWKcJMXC8UKfYJ
|
||||||
|
co9o8MhiIauvSCgZZA2+5VMv4zlke7Lu5TNLDg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DA:A7:40:56:65:41:1A:FE:E6:08:85:3F:6E:AD:83:3A:38:30:83:E6:F0:6D:69:A6:A8:9E:92:BD:85:93:39:81
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
# Deploying "Try it" on the server
|
||||||
|
|
||||||
|
The public demo: each visitor gets a StarshipOS machine of their own in the browser, resumed at
|
||||||
|
Zuse's prompt, gone when they leave. Two at a time on today's server (384 MiB each); a third visitor
|
||||||
|
is told every machine is busy and to try back in a few minutes. Issues #115, #116, #117.
|
||||||
|
|
||||||
|
Run as root on the server, **after PR #148 is merged** (it carries the 384 MiB guests and the busy
|
||||||
|
message), **while CI is idle** (each step that boots QEMU boots one, in the foreground).
|
||||||
|
|
||||||
|
## 1. The checkout and what the build needs (~15 min)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt-get install -y ttyd qemu-system-x86 ovmf python3 git
|
||||||
|
git clone https://gitea.starshipos-f18.org/rajames/LithosAnanke.git /opt/starshipos-demo
|
||||||
|
cd /opt/starshipos-demo
|
||||||
|
git checkout master # after #148: alpha.3's kernel, and the demo's limits
|
||||||
|
make ARCH=amd64 init INIT_DOCS=0 INIT_PROOFS=0 # amd64 only: no docs, no Isabelle
|
||||||
|
```
|
||||||
|
|
||||||
|
Master after #148 is the `v4.0.0-alpha.3` kernel unchanged, plus #148's scripts.
|
||||||
|
|
||||||
|
## 2. The demo's own Zuse (~3 min, two QEMU boots)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
demo/mint-zuse.sh /var/lib/starshipos-demo-zuse
|
||||||
|
ls -la /var/lib/starshipos-demo-zuse/zusestick.img # the stick every session attaches
|
||||||
|
```
|
||||||
|
|
||||||
|
Never anyone's real Zuse: minted for the demo (#111), its writes discarded in every session.
|
||||||
|
|
||||||
|
## 3. The image and the saved machine (~2 min, one QEMU boot)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
demo/build-iso.sh /tmp/StarshipOS.iso
|
||||||
|
DEMO_PROMPT='[zuse@Hera]' demo/make-snapshot.sh /tmp/StarshipOS.iso /var/lib/starshipos-demo \
|
||||||
|
/var/lib/starshipos-demo-zuse/zusestick.img
|
||||||
|
ls -la /var/lib/starshipos-demo/ # StarshipOS.iso identity.img vars.fd state
|
||||||
|
```
|
||||||
|
|
||||||
|
The saved machine belongs to this image, this QEMU and 384 MiB: re-run step 3 after any of them
|
||||||
|
changes. Sessions already running keep theirs.
|
||||||
|
|
||||||
|
## 4. The service (~5 min)
|
||||||
|
|
||||||
|
Ubuntu's `ttyd` package starts its own `ttyd.service`, which runs **`login` on port 7681** -- our
|
||||||
|
port. Left running, it takes the port, and Apache hands visitors the server's own login prompt
|
||||||
|
(found 2026-11-08, after step 5). Disable it first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl disable --now ttyd # the package's service: a login prompt on 7681
|
||||||
|
useradd --system --home /var/lib/starshipos-demo --shell /usr/sbin/nologin starshipos-demo
|
||||||
|
chown -R starshipos-demo: /var/lib/starshipos-demo
|
||||||
|
cp demo/starshipos-demo.service /etc/systemd/system/
|
||||||
|
systemctl daemon-reload && systemctl enable --now starshipos-demo
|
||||||
|
systemctl status starshipos-demo --no-pager | head -5
|
||||||
|
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:7681/ # 200: ttyd answers
|
||||||
|
ss -ltnp | grep 7681 # the ttyd of starshipos-demo, nothing else
|
||||||
|
```
|
||||||
|
|
||||||
|
The service expects the checkout's `demo/` at `/opt/starshipos-demo/demo` (step 1 put it there).
|
||||||
|
|
||||||
|
## 5. TLS and Apache for try.starshipos-f18.com (~10 min)
|
||||||
|
|
||||||
|
DNS: `try.starshipos-f18.com` must point at this server (an A record) before certbot.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
a2enmod proxy proxy_http proxy_wstunnel headers ssl rewrite
|
||||||
|
certbot certonly --apache -d try.starshipos-f18.com
|
||||||
|
cp demo/apache-demo.conf /etc/apache2/sites-available/starshipos-demo.conf
|
||||||
|
a2ensite starshipos-demo && apachectl configtest && systemctl reload apache2
|
||||||
|
curl -sI https://try.starshipos-f18.com/ | head -3 # 200, its own certificate
|
||||||
|
```
|
||||||
|
|
||||||
|
`apache-demo.conf` lets only the .com frame the terminal (`frame-ancestors`).
|
||||||
|
|
||||||
|
## 6. The check (done 2026-11-08)
|
||||||
|
|
||||||
|
From outside: a session ready 1.5 s after the page opens; `3 4 + .` answers `7 ok`, `: SQUARE DUP *
|
||||||
|
; 7 SQUARE .` answers `49 ok`; a third visitor at once is told every machine is busy. The
|
||||||
|
certificate is try.starshipos-f18.com's own (Let's Encrypt), and only the .com may frame it.
|
||||||
|
|
||||||
|
## 7. Tell Claude
|
||||||
|
|
||||||
|
Then I check from outside: a session reaches `[zuse@Hera] ok>`, `3 4 + .` answers `7 ok`, a third
|
||||||
|
visitor gets the busy message, and the .com's Try it page shows the console. Then the "Try it" link
|
||||||
|
goes into the .com's navigation (#117).
|
||||||
|
|
||||||
|
## If something goes wrong
|
||||||
|
|
||||||
|
- `journalctl -u starshipos-demo -n 50` -- ttyd and the sessions
|
||||||
|
- A session that ends at once: the saved machine does not match (re-run step 3)
|
||||||
|
- Memory: `free -h` -- a session's QEMU holds ~150 MB of its 384 MiB guest; two at most
|
||||||
|
(`DEMO_MAX_GUESTS` in the service)
|
||||||
|
- CPU: an idle guest keeps a host core busy (the kernel's idle loop polls -- its own issue), so the
|
||||||
|
service caps all sessions together at one core (`CPUQuota=100%`, `Nice=19`). After changing the
|
||||||
|
service file: `systemctl daemon-reload && systemctl restart starshipos-demo`
|
||||||
+2
-1
@@ -20,7 +20,8 @@ XWiki "Try it" page (iframe) -> Apache: TLS, websocket -> ttyd -> start-session.
|
|||||||
| `start-session.sh` | One visitor's session: resumes the saved machine, ends it on hang-up, close or time-out (#112) |
|
| `start-session.sh` | One visitor's session: resumes the saved machine, ends it on hang-up, close or time-out (#112) |
|
||||||
| `console.py` | Joins the visitor's terminal to the machine only once it runs, discarding keys typed while it loads |
|
| `console.py` | Joins the visitor's terminal to the machine only once it runs, discarding keys typed while it loads |
|
||||||
| `qemu-args.sh` | The machine, shared by the two above: a resumed machine must match the saved one exactly |
|
| `qemu-args.sh` | The machine, shared by the two above: a resumed machine must match the saved one exactly |
|
||||||
| `starshipos-demo.service` | ttyd as a systemd service, on localhost, at most 3 sessions (#114) |
|
| `starshipos-demo.service` | ttyd as a systemd service, on localhost; two guests at once, a busy message for the rest (#114, #116) |
|
||||||
|
| `DEPLOY.md` | Putting it on the server, step by step |
|
||||||
| `apache-demo.conf` | Example vhost: TLS, the websocket, framing allowed for the `.com` only (#115) |
|
| `apache-demo.conf` | Example vhost: TLS, the websocket, framing allowed for the `.com` only (#115) |
|
||||||
| `xwiki-try-it.xwiki` | The "Try it" page, its own page on the `.com` XWiki (`TryIt`), in the landing page's style |
|
| `xwiki-try-it.xwiki` | The "Try it" page, its own page on the `.com` XWiki (`TryIt`), in the landing page's style |
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -3,8 +3,10 @@
|
|||||||
# A session resumes a machine saved by make-snapshot.sh, and QEMU can resume a saved machine only
|
# A session resumes a machine saved by make-snapshot.sh, and QEMU can resume a saved machine only
|
||||||
# into the same machine: the same board, CPU, memory, firmware and devices. Both scripts build the
|
# into the same machine: the same board, CPU, memory, firmware and devices. Both scripts build the
|
||||||
# command line here, so they cannot drift apart. It is the machine `make -f kernel/Makefile
|
# command line here, so they cannot drift apart. It is the machine `make -f kernel/Makefile
|
||||||
# ARCH=amd64 qemu` boots (q35, TCG, 1 GiB, OVMF, the ISO as a CD), less what a visitor must not
|
# ARCH=amd64 qemu` boots (q35, TCG, OVMF, the ISO as a CD) -- in 384 MiB, not its 1 GiB: v4 boots
|
||||||
# have: no network device, no Artemis disk, no display, and QEMU's seccomp sandbox on.
|
# to Zuse's prompt from 256 MiB, refuses at 128 ("no memory for the block chain"), measured
|
||||||
|
# 2026-11-07 (#116) -- less what a visitor must not have: no network device, no Artemis disk, no
|
||||||
|
# display, and QEMU's seccomp sandbox on.
|
||||||
#
|
#
|
||||||
# demo_qemu_args <state-dir> <vars.fd> -> fills the array QEMU_ARGS
|
# demo_qemu_args <state-dir> <vars.fd> -> fills the array QEMU_ARGS
|
||||||
#
|
#
|
||||||
@@ -18,7 +20,7 @@ demo_qemu_args() {
|
|||||||
QEMU_ARGS=(
|
QEMU_ARGS=(
|
||||||
-machine q35,accel=tcg
|
-machine q35,accel=tcg
|
||||||
-cpu qemu64,+rdrand
|
-cpu qemu64,+rdrand
|
||||||
-m 1024
|
-m 384 # v4 boots from 256 MiB; 384 leaves room (#116)
|
||||||
-smp 1
|
-smp 1
|
||||||
-drive "if=pflash,format=raw,readonly=on,file=$OVMF_CODE"
|
-drive "if=pflash,format=raw,readonly=on,file=$OVMF_CODE"
|
||||||
-drive "if=pflash,format=raw,file=$vars"
|
-drive "if=pflash,format=raw,file=$vars"
|
||||||
|
|||||||
@@ -13,8 +13,13 @@ User=starshipos-demo
|
|||||||
Group=starshipos-demo
|
Group=starshipos-demo
|
||||||
Environment=DEMO_STATE=/var/lib/starshipos-demo
|
Environment=DEMO_STATE=/var/lib/starshipos-demo
|
||||||
Environment=DEMO_SESSION_LIMIT=1800
|
Environment=DEMO_SESSION_LIMIT=1800
|
||||||
# -m: sessions at once -- each a QEMU of about 1 GiB and most of a core (issue #116 measures it)
|
Environment=DEMO_MAX_GUESTS=2
|
||||||
ExecStart=/usr/bin/ttyd --port 7681 --interface lo --writable --max-clients 3 \
|
# the guests' slot locks (start-session.sh): /run/starshipos-demo, made for this user, gone at stop
|
||||||
|
RuntimeDirectory=starshipos-demo
|
||||||
|
# --max-clients: the guests and a few more, so a visitor over the limit reaches the busy message
|
||||||
|
# instead of a refused connection; still a cap on open connections
|
||||||
|
# each guest a QEMU of 384 MiB and most of a core (demo/qemu-args.sh; #116)
|
||||||
|
ExecStart=/usr/bin/ttyd --port 7681 --interface lo --writable --max-clients 6 \
|
||||||
--client-option titleFixed=StarshipOS --client-option disableLeaveAlert=true \
|
--client-option titleFixed=StarshipOS --client-option disableLeaveAlert=true \
|
||||||
/opt/starshipos-demo/demo/start-session.sh
|
/opt/starshipos-demo/demo/start-session.sh
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
@@ -25,8 +30,15 @@ ProtectHome=yes
|
|||||||
PrivateTmp=yes
|
PrivateTmp=yes
|
||||||
PrivateDevices=yes
|
PrivateDevices=yes
|
||||||
ReadOnlyPaths=/var/lib/starshipos-demo
|
ReadOnlyPaths=/var/lib/starshipos-demo
|
||||||
MemoryMax=4G
|
# Sized for this server (3.8 GiB, two cores; both wikis, Gitea, Nexus, CI). Since #151 an idle guest
|
||||||
CPUQuota=300%
|
# halts (1% of a core at the prompt, was 100%), so a session costs CPU only while its visitor runs
|
||||||
|
# something. All sessions together get 1.5 cores at the lowest priority (Captain Bob, 2026-11-08):
|
||||||
|
# one busy visitor a full core, two busy at once three-quarters each, and half a core always left
|
||||||
|
# to the wikis and Gitea. 1 GiB holds two sessions (~150 MB resident each) with room. Raise both
|
||||||
|
# with the server (8 GB: MemoryMax=2G, CPUQuota=200% or more).
|
||||||
|
MemoryMax=1G
|
||||||
|
CPUQuota=150%
|
||||||
|
Nice=19
|
||||||
TasksMax=200
|
TasksMax=200
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
|||||||
+24
-3
@@ -12,8 +12,29 @@ here=$(cd "$(dirname "$0")" && pwd)
|
|||||||
. "$here/qemu-args.sh"
|
. "$here/qemu-args.sh"
|
||||||
dir=${1:-${DEMO_STATE:-/var/lib/starshipos-demo}}
|
dir=${1:-${DEMO_STATE:-/var/lib/starshipos-demo}}
|
||||||
limit=${DEMO_SESSION_LIMIT:-1800} # seconds a session may last
|
limit=${DEMO_SESSION_LIMIT:-1800} # seconds a session may last
|
||||||
|
guests=${DEMO_MAX_GUESTS:-2} # machines at once: 384 MiB each (qemu-args.sh, #116)
|
||||||
|
slots=${DEMO_SLOTS:-/run/starshipos-demo} # a lock file per machine
|
||||||
|
|
||||||
[ -f "$dir/state" ] || { echo "The demo is not set up yet: no saved machine in $dir." >&2; exit 1; }
|
[ -f "$dir/state" ] || { echo "The demo is not set up yet: no saved machine in $dir." >&2; exit 1; }
|
||||||
|
|
||||||
|
# One of $guests slots, or a busy message (Captain Bob, 2026-11-07: "Limit guests and have a Busy,
|
||||||
|
# try back in a few minutes"). A slot is a lock this script holds for the session's life (flock -n:
|
||||||
|
# two visitors cannot both take the last one); it goes when the script does, however it ends. The
|
||||||
|
# machine's processes are started without the lock's descriptor ({slot}>&-), so it is this
|
||||||
|
# script's alone.
|
||||||
|
mkdir -p "$slots"
|
||||||
|
slot=
|
||||||
|
for i in $(seq 1 "$guests"); do
|
||||||
|
exec {fd}>"$slots/slot-$i.lock"
|
||||||
|
if flock -n "$fd"; then slot=$fd; break; fi
|
||||||
|
exec {fd}>&-
|
||||||
|
done
|
||||||
|
if [ -z "$slot" ]; then
|
||||||
|
printf '\r\nEvery StarshipOS machine is busy right now (%d at once on this small server).\r\n' "$guests"
|
||||||
|
printf 'Try back in a few minutes.\r\n'
|
||||||
|
sleep 20
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
tmp=$(mktemp -d "${TMPDIR:-/tmp}/starshipos-session.XXXXXX")
|
tmp=$(mktemp -d "${TMPDIR:-/tmp}/starshipos-session.XXXXXX")
|
||||||
trap 'rm -rf "$tmp"' EXIT
|
trap 'rm -rf "$tmp"' EXIT
|
||||||
cp "$dir/vars.fd" "$tmp/vars.fd"
|
cp "$dir/vars.fd" "$tmp/vars.fd"
|
||||||
@@ -28,13 +49,13 @@ printf 'Try: 3 4 + . : SQUARE DUP * ; 7 SQUARE .\r\n\r\n'
|
|||||||
qemu-system-x86_64 "${QEMU_ARGS[@]}" \
|
qemu-system-x86_64 "${QEMU_ARGS[@]}" \
|
||||||
-chardev "socket,id=con,path=$tmp/con.sock,server=on,wait=off" -serial chardev:con \
|
-chardev "socket,id=con,path=$tmp/con.sock,server=on,wait=off" -serial chardev:con \
|
||||||
-qmp "unix:$tmp/qmp.sock,server=on,wait=off" -monitor none \
|
-qmp "unix:$tmp/qmp.sock,server=on,wait=off" -monitor none \
|
||||||
-incoming "file:$dir/state" </dev/null &
|
-incoming "file:$dir/state" </dev/null {slot}>&- &
|
||||||
qemu=$!
|
qemu=$!
|
||||||
( sleep "$limit"; kill "$qemu" 2>/dev/null ) &
|
( sleep "$limit"; kill "$qemu" 2>/dev/null ) {slot}>&- &
|
||||||
timer=$!
|
timer=$!
|
||||||
# The bridge is a tracked child too: bash runs a trap only once its foreground command returns,
|
# The bridge is a tracked child too: bash runs a trap only once its foreground command returns,
|
||||||
# so a hang-up would otherwise wait on the bridge. `wait` returns to the trap at once.
|
# so a hang-up would otherwise wait on the bridge. `wait` returns to the trap at once.
|
||||||
python3 -I "$here/console.py" "$tmp/qmp.sock" "$tmp/con.sock" 0<&0 &
|
python3 -I "$here/console.py" "$tmp/qmp.sock" "$tmp/con.sock" 0<&0 {slot}>&- &
|
||||||
bridge=$!
|
bridge=$!
|
||||||
trap 'kill "$bridge" "$qemu" "$timer" 2>/dev/null; rm -rf "$tmp"' EXIT
|
trap 'kill "$bridge" "$qemu" "$timer" 2>/dev/null; rm -rf "$tmp"' EXIT
|
||||||
trap 'exit 0' HUP TERM INT
|
trap 'exit 0' HUP TERM INT
|
||||||
|
|||||||
+8
-1
@@ -168,7 +168,14 @@ carrying timestamp noise in git history.
|
|||||||
image's bytes, each exactly its file's size), fresh before every boot, and
|
image's bytes, each exactly its file's size), fresh before every boot, and
|
||||||
that is `ZUSEDISK`'s default; `make boot_image TARGET=PC
|
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.
|
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,
|
- **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
|
`docs/v4.0.0/STICK.md` §4, §9): they are build output, made fresh by
|
||||||
|
|||||||
@@ -6165,3 +6165,283 @@ Isabelle2025-2 (HOL-Library and its build database) is a package in this reposit
|
|||||||
`bb247846...e999cb339e`), and the image fetches it into Isabelle's system heaps, checksum pinned,
|
`bb247846...e999cb339e`), and the image fetches it into Isabelle's system heaps, checksum pinned,
|
||||||
its token a Docker build secret. Shown portable first: a fresh Isabelle home holding only that heap
|
its token a Docker build secret. Shown portable first: a fresh Isabelle home holding only that heap
|
||||||
checks the StarForth session without rebuilding HOL-Library (24 s).
|
checks the StarForth session without rebuilding HOL-Library (24 s).
|
||||||
|
|
||||||
|
### 5. v4.0.0-alpha.1 not published; v4.0.0-alpha.2
|
||||||
|
|
||||||
|
PR #127 merged (`4f675c8b`, acceptance run 192 with the capsules signed); `runner-image.yml` built
|
||||||
|
`lithosananke-runner:4f675c8b75b2` with HOL-Library fetched (checksum OK, 4.8 s); PR #128 moved the
|
||||||
|
workflows onto it (`233025da`, acceptance run 195 in the new image). `v4.0.0-alpha.1` was tagged on
|
||||||
|
`233025da`. Its release run (196) passed acceptance in full, then the proofs step built HOL-Library
|
||||||
|
from scratch and was killed (exit 137): `release.yml` ran a full `make init` for the documents'
|
||||||
|
packages, which also fetched Isabelle into the workspace and pointed `/usr/local/bin/isabelle` at it
|
||||||
|
-- an Isabelle without the image's HOL-Library. Nothing was published. Ruled (Captain Bob,
|
||||||
|
2026-11-07): the tag stays where it is; `release.yml` runs `init INIT_PROOFS=0` (as
|
||||||
|
`nightly-docs.yml` does), `LITHOS_VERSION` becomes `4.0.0-alpha.2`, and `v4.0.0-alpha.2` is the
|
||||||
|
first published alpha.
|
||||||
|
|
||||||
|
### 6. v4.0.0-alpha.2 not published either; v4.0.0-alpha.3
|
||||||
|
|
||||||
|
PR #130 merged (`2d43db25`, acceptance run 199; run 197 before it failed one riscv64 check, #131);
|
||||||
|
`v4.0.0-alpha.2` tagged there. Its release run (200) passed acceptance and used the image's
|
||||||
|
Isabelle and HOL-Library, as XLVII.5 meant -- then the StarForth session was killed (exit 137) in
|
||||||
|
the proofs: Isabelle ran with its defaults, Java's heap up to 4 GiB and a thread per CPU, more than
|
||||||
|
the server (3.8 GiB, ~2.3 GiB free with the wikis stopped; perhaps a per-job cap besides). Capped
|
||||||
|
-- one thread, Java 512 MiB, Poly/ML 900 MiB, in a settings file of a home made for the run, its
|
||||||
|
heaps linked to the user's -- the session passes in 47 s at ~1.8 GiB, through
|
||||||
|
`scripts/nightly.sh proofs` itself (`logs/20261107-195341`). Nothing was published. Ruled (Captain
|
||||||
|
Bob, 2026-11-07): the tag stays; `LITHOS_VERSION` `4.0.0-alpha.3`, the first published alpha; the
|
||||||
|
review list begun meanwhile goes to the milestone v4.0.0-alpha.4.
|
||||||
|
|
||||||
|
## XLVIII. After the first published alpha: the review, the protocol, the SDK, the demo's limits (2026-11-07)
|
||||||
|
|
||||||
|
### 1. Ruled
|
||||||
|
|
||||||
|
- **A ranked list for the next release** (Captain Bob: "a list of problems, deficiencies, smells and
|
||||||
|
so on placed in issues by rank priority"): milestone **v4.0.0-alpha.4**, its index #147. Must:
|
||||||
|
Gitea's plain-HTTP logins (#133), rotating what was exposed (#134), the riscv64 flake (#131), the
|
||||||
|
developer protocol (#135), CI's litter (#129). Should: a failed check prints its serial log
|
||||||
|
(#136), capsule trust against the root and unsigned capsules (#139, a ruling), the queue's
|
||||||
|
cancelling of waiting runs (#140, a ruling), CLAUDE.md's drift (#137), the Book of Fabric (#138),
|
||||||
|
downloads (#126). Nice: the empty DoE CSVs (#141 -- no DoE has run since 2026-09-16: noise, not
|
||||||
|
breakage), DoE columns always 0 (#142), mkcapsule's warnings (#143), a stale header (#144),
|
||||||
|
tracked files a build rewrites (#145), the sites' small things (#146).
|
||||||
|
- **The developer protocol** (#135): "We can simply run nightly as developers to further make sure
|
||||||
|
nothing sneaks in. Just no Nexus push ... a protocol for programmers. Then the protocol evidence
|
||||||
|
can be submitted in the PR." -- `scripts/nightly.sh protocol`, a `PROTOCOL.md` per run, checked
|
||||||
|
by CI against the PR's head.
|
||||||
|
- **The Book of Fabric** (#138): the FABRIC record as one book, published with every release --
|
||||||
|
and this record kept at the pace of the work, so the book is (Captain Bob: "the book of fabric
|
||||||
|
needs to keep pace").
|
||||||
|
- **v4.0.0-alpha.5: the SDK**, for FORTH and capsule developers; a systems SDK later, FPGA when we
|
||||||
|
get there (milestone 11). In it:
|
||||||
|
- **A capsule repository in blocks**, like `~/.m2/repository` (#149): on Artemis, indexed by
|
||||||
|
coordinates and capsule hash, a TTL by default as the rest of the system has, pinning one-way,
|
||||||
|
verified in and on use, composed in FORTH; filled by hand now, from Nexus once there is
|
||||||
|
networking. To rule: its block range and size, the default TTL, what is pinned.
|
||||||
|
- **K under network latency** (#150): "Networking latency will be a super good K test." -- the
|
||||||
|
repository pulling from Nexus with delay, jitter, loss and bandwidth dialled in (`tc netem`),
|
||||||
|
K and the DoE's measures per architecture. After networking, #141 and #142.
|
||||||
|
- **The demo's limits** (#116): "Limit guests and have a Busy, try back in a few minutes."
|
||||||
|
|
||||||
|
### 2. Built
|
||||||
|
|
||||||
|
- **#136:** `scripts/qemu_session.py`'s `check()` prints, on a FAIL, the serial lines after an anchor
|
||||||
|
the check names (the boot-disk checks: `Boot successful!`), else the log's last lines, control
|
||||||
|
characters as escapes -- so #131's next occurrence explains itself in the job's output.
|
||||||
|
- **The demo:** guests of **384 MiB** (`demo/qemu-args.sh`); `start-session.sh` takes one of
|
||||||
|
`DEMO_MAX_GUESTS` slots (2), a lock held for the session's life, and with every slot taken tells
|
||||||
|
the visitor every machine is busy and to try back in a few minutes; the service makes the locks'
|
||||||
|
directory and lets ttyd take 6 connections so the extra visitors reach the message.
|
||||||
|
|
||||||
|
### 3. Verified
|
||||||
|
|
||||||
|
- The demo machine, booted here with only `-m` changed: POST 538/538 and Zuse's prompt at 1024, 512,
|
||||||
|
384 and 256 MiB (82-84 s); at 128 MiB POST passes, then "StarForth v4: no memory for the block
|
||||||
|
chain". The slots: every slot held -- the busy message; slot 1 held -- slot 2 taken.
|
||||||
|
- `excerpt()` against a real riscv64 serial log, with an anchor and without; a riscv64 acceptance
|
||||||
|
with the new script, passing as before.
|
||||||
|
- With both wikis up again (Shenandoah, the .com's heap at 512 MiB, the .org's given 256 more): the
|
||||||
|
server at 2.6 of 3.8 GiB used, 1.2 GiB available, 2 GiB of swap used; Build 204 (three images, the
|
||||||
|
v4 tests) passed alongside them.
|
||||||
|
|
||||||
|
### 4. Try it, deployed (2026-11-08)
|
||||||
|
|
||||||
|
Captain Bob ran `demo/DEPLOY.md` on the server (#115): try.starshipos-f18.com with its own Let's
|
||||||
|
Encrypt certificate, ttyd behind Apache, framing allowed to the .com alone. Checked from outside: a
|
||||||
|
session ready 1.5 s after the page opens, `3 4 + .` -> `7 ok`, `: SQUARE DUP * ; 7 SQUARE .` ->
|
||||||
|
`49 ok`, a third visitor at once told every machine is busy.
|
||||||
|
|
||||||
|
Found on the way:
|
||||||
|
- Ubuntu's `ttyd` package starts its own `ttyd.service` -- `login` on port 7681, ours -- and
|
||||||
|
until it was disabled the page served the server's login prompt to anyone. `DEPLOY.md` step 4
|
||||||
|
now disables it first and checks what listens on 7681.
|
||||||
|
- **An idle StarshipOS keeps a host core 100% busy** (#151): the demo machine at its prompt, idle
|
||||||
|
20 s, QEMU at 100% of a core, 148 MiB resident -- the kernel's idle loop polls, never halts. Two
|
||||||
|
visitors' sessions with Gitea's diff statistics on a burst of pushes (#152, 1.75 GiB) filled the
|
||||||
|
server's swap and stalled both wikis. The service now caps all sessions together at one core at
|
||||||
|
the lowest priority (`CPUQuota=100%`, `Nice=19`, `MemoryMax=1G`), until #151 is fixed.
|
||||||
|
- **Try it in the .com's navigation** (#117): "Try it" added to the canvas's Home and Inquiries
|
||||||
|
artboards, the .com rebuilt from them (`site/com`) and installed. Checked as a visitor: the home
|
||||||
|
page, the "Try it" link, the Try it page in 1.1 s, its framed console Ready.
|
||||||
|
|
||||||
|
### 5. #151: the idle loop halts (2026-11-08)
|
||||||
|
|
||||||
|
Ruled (Captain Bob): "Fix the kernel problem." The v4 system waited for a key -- `sk_v4_readline()`
|
||||||
|
with nothing typed, and `sk_v4_identity_wait()` headless until Zuse -- in `arch_relax()`, a spin.
|
||||||
|
Both now wait in `arch_halt()` (`hlt` on amd64, `wfi` on aarch64 and riscv64) until the next
|
||||||
|
interrupt: the heartbeat's timer, which is ISR-driven on all three (`heartbeat_tick()`), wakes them
|
||||||
|
at 100 Hz, so a key is seen within a tick, as the cursor's blink and the identity beat already
|
||||||
|
were. v3's REPL (`repl.c`) still spins; v3 is not in acceptance.
|
||||||
|
|
||||||
|
Verified: idle at Zuse's prompt for 20 s, QEMU's CPU **100% -> 1%** of a core on amd64 (the demo
|
||||||
|
machine), and **1%** on aarch64 and riscv64 (`logs/20261108-011614`, `-011931`); the acceptance
|
||||||
|
protocol passes -- amd64 `logs/20261108-005539`, aarch64 `-005753`, riscv64 `-010136`, POST
|
||||||
|
538/538, `dict_hash 0xfec8c47cfc6f437f` on all three, `7 ok` typed and answered; the stick loaded
|
||||||
|
high; `test-32` (39 programs, 0 failures). The demo's CPU cap (`CPUQuota=100%`) can be relaxed
|
||||||
|
once this reaches the server.
|
||||||
|
|
||||||
|
### 6. #131 closed: QEMU's capture, not our kernel (2026-11-08)
|
||||||
|
|
||||||
|
Run 197's riscv64 serial log, read from Gitea's artifact store on the server (`acceptance-logs-185`),
|
||||||
|
had the line with one character doubled -- "Boot diisk: not a StarshipOS stick" -- and a doubled
|
||||||
|
byte in OpenSBI's banner too, printed before our kernel runs. So the byte was doubled in QEMU's
|
||||||
|
serial capture under the server's load, not by the kernel (Captain Bob closed #131). The check that
|
||||||
|
failed was right to: it refuses a line that is not what was printed. The capture itself (the log is
|
||||||
|
`logfile=` on the socket chardev the acceptance types through) is what is left to harden.
|
||||||
|
|
||||||
|
### 7. Downloads (#126): what a release publishes, and what a download must boot to (2026-11-08)
|
||||||
|
|
||||||
|
- **Ruled** (Captain Bob): the Downloads page goes live with alpha.4, filled by the release itself;
|
||||||
|
the StarshipOS Root CA's certificate is published with it.
|
||||||
|
- **Built:** the release builds the PC's USB stick too (`scripts/nightly.sh images`, classifier
|
||||||
|
`pc-stick`; `pc` stays the ISO QEMU boots), and makes the tag a Gitea release -- a pre-release for
|
||||||
|
an alpha -- with the images, `SHA256SUMS`, the documents and the Root CA's certificate attached
|
||||||
|
for anyone to download (`scripts/nightly.sh gitea-release`, run by `release.yml` with the secret
|
||||||
|
`RELEASE_TOKEN`). Tested against a stand-in Gitea API: the release, its notes and ten files; a
|
||||||
|
second run adds nothing.
|
||||||
|
- **Found:** a downloaded image boots headless today -- "Zuse: no genesis on this disk -- the system
|
||||||
|
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
@@ -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 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
|
- **The identity partition stays 500 MiB.** About half a million 1 KiB blocks for Zuse's keys and
|
||||||
her own pool.
|
her own pool.
|
||||||
- **Artemis grows to fill the stick at its first boot (§5a),** up to **2 TiB** for the partition
|
- **Artemis grows to fill the stick at its first boot (§5a),** up to **256 GiB** for the partition
|
||||||
(the block layer numbers 1 KiB blocks with 32 bits: 4 TiB is its hard limit; 2 TiB keeps a margin
|
(**amended 2026-10-29**, Captain Bob: "256 GiB is ruled" -- plan
|
||||||
and is past any thumb drive). Space past 2 TiB is left unused, and the boot says so.
|
`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
|
- **A stick under 8 GB** is not grown: it runs at the 2 GiB it was written with, and the boot says
|
||||||
so.
|
so.
|
||||||
- **The Artemis partition is formatted when the image is built (my call),** not on first boot:
|
- **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:
|
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
|
- 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).
|
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
|
- 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
|
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
|
`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
|
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.
|
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
|
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;
|
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).
|
`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).
|
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
|
**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.
|
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
|
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
|
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.
|
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
|
- **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).
|
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
|
- **`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
|
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:
|
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).
|
reaches the prompt. Today: FAIL (headless).
|
||||||
- **Changed:** `stick_boot` expected the blank stick headless; it now expects the genesis line and
|
- **Changed:** `stick_boot` expected the blank stick headless; it now expects the genesis line and
|
||||||
the prompt.
|
the prompt.
|
||||||
- [ ] **Step 2:** Run each: FAIL as listed.
|
- [x] **Step 2:** Run each: FAIL as listed.
|
||||||
- [ ] **Step 3:** Implement.
|
- [x] **Step 3:** Implement.
|
||||||
- [ ] **Step 4:** The new sessions pass; regression: `zuse` (the pair, version 1: logs in as the
|
- [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`,
|
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).
|
`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.
|
boot mints its own Zuse; the genesis marker's version 2` with the logs.
|
||||||
|
|
||||||
### Task 2: Artemis grows to fill the stick
|
### 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,
|
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.
|
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_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`),
|
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).
|
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).
|
prompt. Today: FAIL (no line).
|
||||||
- **`check_images.sh`:** the PC stick's and data stick's Artemis BAM is the cap's size
|
- **`check_images.sh`:** the PC stick's and data stick's Artemis BAM is the cap's size
|
||||||
(`mkartemis --check` reports it). Today: FAIL.
|
(`mkartemis --check` reports it). Today: FAIL.
|
||||||
- [ ] **Step 2:** Run each: FAIL as listed.
|
- [x] **Step 2:** Run each: FAIL as listed.
|
||||||
- [ ] **Step 3:** Implement.
|
- [x] **Step 3:** Implement.
|
||||||
- [ ] **Step 4:** They pass; regression: `genesis`, `stick_genesis`, `stick_zuse`, `two_sticks`,
|
- [x] **Step 4:** They pass; regression: `genesis`, `stick_genesis`, `stick_zuse`, `two_sticks`,
|
||||||
`artemis_unsigned`, `midpull` (replug: not grown again).
|
`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.
|
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
|
### 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
|
**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.
|
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).
|
prompt on all three ISAs. Today: FAIL (the pair is the default; no genesis line).
|
||||||
- [ ] **Step 2:** Run it: FAIL.
|
- [x] **Step 2:** Run it: FAIL.
|
||||||
- [ ] **Step 3:** Change the defaults and the docs.
|
- [x] **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 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`.
|
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.
|
fresh data stick -- every run is a first boot` with the logs.
|
||||||
|
|
||||||
### Task 4: `MINT-ZUSE` -- the real Zuse onto a second stick
|
### 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
Reference in New Issue
Block a user