Author SHA1 Message Date
Claude 4c38a7b1e6 feat(kernel): the proxy Zuse -- a stick's first boot mints its own Zuse; the genesis marker's version 2 (#92, Task 1)
Build / Image RASPI (push) Successful in 3m35s
Build / Image PC (push) Successful in 3m52s
Build / Image MILKV (push) Successful in 3m29s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 11m18s
Task 1 of plan 2026-10-29-stick-5, accepted in full:
- amd64, aarch64, riscv64: PARITY:V4_POST tests=538 pass=538 fail=0,
  POST: PASSED, [zuse@Hera] ok>; dict_hash 0xfec8c47cfc6f437f on the three
- the PC stick loaded high: 538/538, POST: PASSED, the prompt
- make -C v4 test-32: 39 programs, 0 failures

The logs of the acceptance boots (aarch64 044253, riscv64 044558, the stick
high 044725; amd64 044115 is already in), the four accept-*.txt verdicts and
test-32's output. The plan's Task 1 steps ticked; FABRIC-3 XLVIII.8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:54:00 +00:00
Claude 96bc60883d logs: acceptance amd64 for #92 Task 1: PASS [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:43:26 +00:00
Claude a58ddbfc24 FABRIC-3 XLVIII.8: #92 Task 1, the proxy Zuse -- built, tested first, regressions [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:41:25 +00:00
Claude c587678dbd logs: stick_boot and stick_artemis at --log-level=info: PASS (#92, Task 1) [skip ci]
The reruns of 035439 and 035956, with the log level their plans run them at.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:40:46 +00:00
Claude b4d673f929 logs: v3_keys -- v3's genesis and marker unchanged: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:37:17 +00:00
Claude 0b49d03526 logs: gpt_read_error: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:35:49 +00:00
Claude 6627f710b2 logs: gpt_no_header: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:33:15 +00:00
Claude 7dca7fb699 logs: gpt_bad_entries: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:30:45 +00:00
Claude 715c09a9d1 logs: gpt_bad_crc: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:28:18 +00:00
Claude c38f4f4965 logs: gpt_foreign: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:25:50 +00:00
Claude 8b1ba39040 logs: gpt_hotplug: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:23:25 +00:00
Claude 429eb72aa2 logs: gpt_zuse -- a GPT drive with only an identity partition is not used: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:20:54 +00:00
Claude 91a7150276 logs: typeahead -- what was typed while headless does not run: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:18:23 +00:00
Claude 607ae1c2da logs: waitpull -- pulled while a line waits, re-attached: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:16:12 +00:00
Claude da800ce844 logs: midpull -- pulled mid-line, replugged, Artemis attached again: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:14:06 +00:00
Claude cff3787b92 logs: hotplug -- added, pulled, added again: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:12:07 +00:00
Claude dc9a086603 logs: raw_ident -- a raw identity drive is not used: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:09:15 +00:00
Claude bcd51cb33d logs: artemis_unsigned -- a bad Artemis signature: not used, nothing minted: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:06:25 +00:00
Claude 19a8a036c2 logs: two_sticks -- a blank data stick beside Zuse's is still not used: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:03:32 +00:00
Claude 258842aafc logs: stick_artemis run without --log-level=info -- its disk-size check found no info lines: FAIL, to be rerun (#92, Task 1) [skip ci]
Artemis attached and Zuse confirmed; the run omitted the info log level its blk: disk check reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 04:01:35 +00:00
Claude 727a707580 logs: stick_zuse -- the PC stick with the pair: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 03:59:34 +00:00
Claude 634a49b533 logs: zuse -- the minted pair's version 1 marker logs in as the proxy: PASS (#92, Task 1) [skip ci]
Also the DoE CSV of the stick_boot run (20261108-035439), missed from its commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 03:58:03 +00:00
Claude 56e4d60844 logs: stick_boot run without --log-level=info -- its disk-size check found no info lines: FAIL, to be rerun (#92, Task 1) [skip ci]
The genesis line and [zuse@Hera] ok> passed; the run omitted the KERNEL_ARGS=--log-level=info that plan stick-3 runs stick_boot with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 03:56:18 +00:00
Claude 68919741fc logs: stick_genesis -- the PC stick as built boots to [zuse@Hera] ok> with nothing set up: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 03:54:38 +00:00
Claude 0e1c9650b4 logs: genesis on riscv64, two boots -- minted, then recognised: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 03:53:11 +00:00
Claude 9ed9cf1ad0 logs: genesis on aarch64, two boots -- minted, then recognised: PASS (#92, Task 1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 03:49:32 +00:00
Claude bfe3506aec wip(kernel): the proxy Zuse -- a stick's first boot mints its own Zuse (#92, Task 1) [skip ci]
Work in progress on StarForth-v4.0.0; not yet accepted (plan
2026-10-29-stick-5, Task 1).

- zuse_genesis_marker.h: the marker's version 2 -- the proxy's key and the
  real Zuse's -- beside version 1.
- capsule_zuse_boot.c: capsule_zuse_boot_check_key() (the identity-record
  half of the check) and capsule_zuse_boot_genesis_mint() (the mint half of
  v3's genesis) split out; v3's two callers unchanged in behaviour.
- sk_v4_marker.c: the v4 boot reads version 1 as a proxy with no real Zuse,
  and writes version 2.
- sk_v4_identity.c: no marker and a blank identity partition -> genesis:
  mint, read back, then the marker; the proxy logs in. A marker with a real
  key: no session for the proxy (the fixed screen is Task 5).
- qemu_session.py: boot()/shutdown(), so a mode can boot twice; modes
  genesis and stick_genesis; stick_boot now expects genesis and the prompt.

Logs: genesis on amd64 before the change (both boots: "no genesis on this
disk", FAIL) and after (minted, then recognised: PASS). The DoE CSV of
032532 is from a run whose QEMU never started (no display; its empty log
directory was removed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 03:43:33 +00:00
Claude 8f1ba02b3c acceptance: run the gate on this branch's head before the PR into master
Acceptance / Acceptance (pull_request) Successful in 18m12s
The commits under this one skip CI on their own push; this one does not, so the PR
into master runs acceptance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 02:54:47 +00:00
Claude a293eab1d4 pki: the StarshipOS Root CA's certificate, public, in the tree (#126) [skip ci]
ci/pki/starshipos-root-ca.pem, made on the CI box by make-ca.sh
(2026-11-07, Ed25519, to 2046-11-07; Captain Bob), and its SHA-256
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
in starshipos-root-ca.sha256. Verified: self-signed, CA:TRUE, and it issued
capsules/pki/starshipos-intermediate.der (openssl verify: OK). Every
release attaches it (gitea-release), and the Downloads page shows its
fingerprint; it is also the anchor #139 would build into the kernel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 02:36:45 +00:00
Claude cac4e7fb50 site/com: Read the paper links to the SSRN abstract (#146) [skip ci]
The canvas's Home artboard had left it a placeholder, which the build
pointed at the .org. Now https://papers.ssrn.com/sol3/papers.cfm?abstract_id=5930134
(Captain Bob, 2026-11-08), on the canvas (version 14) and on the wiki.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 02:33:36 +00:00
Claude 199720e769 FABRIC-3 XLVIII.7: Downloads -- the PC stick, the Gitea release, #92 into alpha.4 [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 02:32:36 +00:00
Claude d54e2fe276 release: the PC stick image, and a Gitea release anyone can download from (#126)
Build / Image RASPI (push) Successful in 3m37s
Build / Image PC (push) Successful in 3m40s
Build / Image MILKV (push) Successful in 3m17s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 9m53s
- scripts/nightly.sh images builds the PC's USB stick too (make boot_image
  TARGET=PC -> pc-stick.img.xz, in SHA256SUMS); publish sends it to Nexus
  as classifier pc-stick. pc stays the ISO QEMU boots.
- scripts/nightly.sh gitea-release <tag>: the tag as a Gitea release -- a
  pre-release for -alpha.N and the like -- notes from the tag's message with
  the checksums, the images, SHA256SUMS, the documents and the StarshipOS
  Root CA's certificate attached; run again, it adds only what is missing.
  release.yml runs it after the Nexus publish, with the secret RELEASE_TOKEN.

Tested here: images builds pc-stick.img.xz (785 KB); gitea-release against
a stand-in Gitea API made a pre-release with the notes and ten files, and a
second run added nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 02:32:03 +00:00
Claude 44264d0781 FABRIC-3 XLVIII.6: #131 closed -- QEMU's capture doubled a byte, not our kernel [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 02:25:06 +00:00
Claude 55613350c4 demo: CPUQuota 150%, as set on the server (#116) [skip ci]
Since #151 an idle guest halts (1% of a core at the prompt), so the cap no
longer has to hold back spinning sessions. Captain Bob set 1.5 cores for
all sessions together on the server (2026-11-08): one busy visitor a full
core, half a core always left to the wikis and Gitea. Confirmed on the
server with a live session idle for 3 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 02:09:52 +00:00
rajames f747ab78a6 Merge pull request 'kernel: v4 waits for a key in arch_halt(), not a spin (#151); Try it deployed' (#153) from StarForth-v4.0.0 into master 2026-11-08 01:59:29 +00:00
Claude 1928d53b6b kernel: v4 waits for a key in arch_halt(), not a spin (#151)
Build / Image RASPI (push) Successful in 3m9s
Build / Image PC (push) Successful in 4m27s
Build / Image MILKV (push) Successful in 3m18s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 10m27s
Acceptance / Acceptance (pull_request) Successful in 15m15s
An idle StarshipOS kept a CPU core 100% busy: sk_v4_readline(), with
nothing typed, and sk_v4_identity_wait(), headless until Zuse, waited in
arch_relax(). Both now halt until the next interrupt (hlt; wfi on aarch64
and riscv64): the heartbeat's timer, ISR-driven on all three, wakes them at
100 Hz, so a key is still seen within a tick.

Idle at the prompt, QEMU's CPU: 100% -> 1% of a core on amd64, 1% on
aarch64 and riscv64. Acceptance passes: amd64 logs/20261108-005539, aarch64
-005753, riscv64 -010136 (POST 538/538, one dict_hash, 7 ok), the stick
loaded high, test-32 (39 programs, 0 failures). FABRIC-3 XLVIII.5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 01:21:36 +00:00
Claude a083c5b834 site/com: Try it in the .com's navigation (#117) [skip ci]
The canvas's Home and Inquiries artboards gain a 'Try it' link (canvas
versions 12, 13); canvas/ copies them, build.py rebuilds the pages, and
install.sh put them on the wiki. Checked as a visitor: the home page, the
link, the Try it page in 1.1 s, its framed console Ready. FABRIC-3 XLVIII.4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 00:49:46 +00:00
Claude 88b962b29e demo: one core for all sessions, lowest priority, 1 GiB; Try it deployed [skip ci]
An idle StarshipOS guest keeps a host core 100% busy (measured 2026-11-08:
QEMU at 100% of a core, 148 MiB, the guest idle at its prompt; #151).
starshipos-demo.service: CPUQuota=100% and Nice=19 for all sessions
together, MemoryMax=1G -- sized for this server, where the old 300% and 4G
let two visitors starve both wikis and Gitea. DEPLOY.md says how to apply
it. FABRIC-3 XLVIII.4: Try it deployed and checked from outside; the ttyd
package's own login service; #151, #152.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 00:38:54 +00:00
Claude 4d0b9ab771 demo/DEPLOY.md: disable the ttyd package's own service first [skip ci]
Ubuntu's ttyd package starts ttyd.service, which runs login on port 7681;
installed by step 1, it took the port, and try.starshipos-f18.com served
the server's login prompt until it was disabled (2026-11-08). Step 4 now
disables it first and checks what listens on 7681. And the check from
outside, done: ready in 1.5 s, 7 ok, 49 ok, the third visitor busy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 00:25:26 +00:00
Claude 0dbad0f278 demo: DEPLOY.md, the server checklist for Try it [skip ci]
Five steps on the server after #148: the checkout and amd64 build tools,
the demo's own Zuse, the image and the saved machine at 384 MiB, the
service, TLS and Apache for try.starshipos-f18.com; then the check from
outside and the .com's navigation link (#115, #116, #117).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 00:07:58 +00:00
rajames 6bbf4b1afd Merge pull request 'acceptance prints the serial log of a failed check (#136); the demo limits its guests (#116)' (#148) from StarForth-v4.0.0 into master 2026-11-08 00:07:45 +00:00
Claude 1e3f211daa FABRIC-3 XLVIII: the review, the protocol, the SDK, the demo's limits
Build / Image RASPI (push) Canceled after 0s
Build / Image PC (push) Canceled after 0s
Build / Image MILKV (push) Canceled after 0s
Build / v4 tests (32- and 64-bit cells) (push) Canceled after 0s
Acceptance / Acceptance (pull_request) Successful in 16m20s
Today's rulings and work since XLVII.6, kept at the pace of the work
(Captain Bob, 2026-11-07: 'the book of fabric needs to keep pace'): the
alpha.4 list (#147) and what is in it, the developer protocol (#135), the
Book of Fabric (#138), the SDK milestone with the capsule repository (#149)
and the latency DoE (#150), #136 and the demo's guests and busy message,
with what was measured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 23:19:28 +00:00
Claude 171b3947dd demo: two guests of 384 MiB, and a busy message for the rest (#116)
Build / Image RASPI (push) Canceled after 0s
Build / Image PC (push) Canceled after 0s
Build / Image MILKV (push) Canceled after 0s
Build / v4 tests (32- and 64-bit cells) (push) Canceled after 0s
Acceptance / Acceptance (pull_request) Canceled after 0s
Captain Bob, 2026-11-07: 'Limit guests and have a Busy, try back in a few
minutes.' start-session.sh takes one of DEMO_MAX_GUESTS slots (default 2),
a lock it holds for the session's life (flock -n: two visitors cannot both
take the last one; QEMU and the bridge are started without its descriptor);
with every slot taken, the visitor's terminal says every machine is busy and
to try back in a few minutes, and the session ends without a machine. The
service: DEMO_MAX_GUESTS=2, RuntimeDirectory for the locks, ttyd's
--max-clients 6 so a visitor over the limit reaches the message. The guest:
384 MiB (v4 boots from 256 MiB, refuses at 128; measured, #116). Tested
here: every slot held -> the busy message; slot 1 held -> slot 2 taken.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 23:18:40 +00:00
Claude 1d4898496f acceptance: a failed check prints the serial log where it looked (#136)
Build / Image PC (push) Successful in 3m20s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 10m1s
Build / Image MILKV (push) Successful in 2m55s
Build / Image RASPI (push) Successful in 2m42s
Acceptance / Acceptance (pull_request) Successful in 18m44s
Run 197's riscv64 failure (#131) could only be read from the run's logs
artifact, which Gitea's API does not list. qemu_session.py's check() now
prints, on a FAIL, the serial lines after the first match of an anchor the
check names, or the log's last lines; control characters as escapes, so a
stray byte or terminal sequence in a line shows instead of only failing a
match. The boot-disk checks anchor on 'Boot successful!'. A passing run
prints as before (riscv64 here, logs/ committed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 22:49:03 +00:00
117 changed files with 14891 additions and 131 deletions
+1
View File
@@ -6,6 +6,7 @@
#
# org.starship:kernelImage:<LITHOS_VERSION>-SNAPSHOT, starshipos-snapshots
# 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 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
+11 -1
View File
@@ -2,9 +2,14 @@
# acceptance protocol, the proofs, the board images -- and the documents, and publishes both to
# 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)
#
# 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
# that does not is refused before anything is built. A release repository takes a version once.
name: Release
@@ -84,6 +89,11 @@ jobs:
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
- 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
uses: actions/upload-artifact@v3
with:
+4 -1
View File
@@ -3,7 +3,10 @@
# 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:
# 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.
# Its certificate is built into every image (capsules/pki/
# starshipos-intermediate.der) and checks each capsule at boot;
+10
View File
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBaDCCARqgAwIBAgIUCwt1JkPxCfwr9PTCOadol/m9PCQwBQYDK2VwMDIxEzAR
BgNVBAoMClN0YXJzaGlwT1MxGzAZBgNVBAMMElN0YXJzaGlwT1MgUm9vdCBDQTAe
Fw0yNjExMDcxNjUwNTZaFw00NjExMDcxNjUwNTZaMDIxEzARBgNVBAoMClN0YXJz
aGlwT1MxGzAZBgNVBAMMElN0YXJzaGlwT1MgUm9vdCBDQTAqMAUGAytlcAMhANcn
fPpowbNgzMPtDEA7EYJoSkBLPljM6dEBFONfrhHso0IwQDAPBgNVHRMBAf8EBTAD
AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU5eU4Iy/Al5g9KZI5+u4jKllG
shswBQYDK2VwA0EAjRK1ybZE/VaH31dt3sc8DgqJVTPB6CYovdqWKcJMXC8UKfYJ
co9o8MhiIauvSCgZZA2+5VMv4zlke7Lu5TNLDg==
-----END CERTIFICATE-----
+1
View File
@@ -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
+96
View File
@@ -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
View File
@@ -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) |
| `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 |
| `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) |
| `xwiki-try-it.xwiki` | The "Try it" page, its own page on the `.com` XWiki (`TryIt`), in the landing page's style |
+5 -3
View File
@@ -3,8 +3,10 @@
# 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
# 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
# have: no network device, no Artemis disk, no display, and QEMU's seccomp sandbox on.
# ARCH=amd64 qemu` boots (q35, TCG, OVMF, the ISO as a CD) -- in 384 MiB, not its 1 GiB: v4 boots
# 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
#
@@ -18,7 +20,7 @@ demo_qemu_args() {
QEMU_ARGS=(
-machine q35,accel=tcg
-cpu qemu64,+rdrand
-m 1024
-m 384 # v4 boots from 256 MiB; 384 leaves room (#116)
-smp 1
-drive "if=pflash,format=raw,readonly=on,file=$OVMF_CODE"
-drive "if=pflash,format=raw,file=$vars"
+16 -4
View File
@@ -13,8 +13,13 @@ User=starshipos-demo
Group=starshipos-demo
Environment=DEMO_STATE=/var/lib/starshipos-demo
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)
ExecStart=/usr/bin/ttyd --port 7681 --interface lo --writable --max-clients 3 \
Environment=DEMO_MAX_GUESTS=2
# 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 \
/opt/starshipos-demo/demo/start-session.sh
Restart=on-failure
@@ -25,8 +30,15 @@ ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ReadOnlyPaths=/var/lib/starshipos-demo
MemoryMax=4G
CPUQuota=300%
# Sized for this server (3.8 GiB, two cores; both wikis, Gitea, Nexus, CI). Since #151 an idle guest
# 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
[Install]
+24 -3
View File
@@ -12,8 +12,29 @@ here=$(cd "$(dirname "$0")" && pwd)
. "$here/qemu-args.sh"
dir=${1:-${DEMO_STATE:-/var/lib/starshipos-demo}}
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; }
# 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")
trap 'rm -rf "$tmp"' EXIT
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[@]}" \
-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 \
-incoming "file:$dir/state" </dev/null &
-incoming "file:$dir/state" </dev/null {slot}>&- &
qemu=$!
( sleep "$limit"; kill "$qemu" 2>/dev/null ) &
( sleep "$limit"; kill "$qemu" 2>/dev/null ) {slot}>&- &
timer=$!
# 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.
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=$!
trap 'kill "$bridge" "$qemu" "$timer" 2>/dev/null; rm -rf "$tmp"' EXIT
trap 'exit 0' HUP TERM INT
+143
View File
@@ -6191,3 +6191,146 @@ 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.
@@ -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

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