Author SHA1 Message Date
Claude 5df4d73480 feat(kernel): MINT-ZUSE, a word of the lone node (request 2) (#92, 4.6) [skip ci]
word_count 317 -> 318; no POST case (it waits for a stick and YES, as BYE has none).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 18:15:26 +00:00
Claude 8b83e0a72d feat(kernel): sk_v4_mint_zuse -- the real Zuse minted onto a second stick, read back before the marker names her (#92, 4.5) [skip ci]
Asks for a stick, shows its size, writes nothing until YES; then gpt_write_one, the partition's first devblocks zeroed, a fresh Zuse minted, read back, and only then the marker's real key. Any failure before the marker: 'failed -- nothing changed'. The gate remembers the last stick it turned away as a spare, offered first by the next mint. Builds on three ISAs; not yet called.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 18:14:54 +00:00
Claude cfa60fd0ec feat(kernel): a stick offered to a waiting mint, not attached or refused (#92, 4.4) [skip ci]
sk_v4_identity_offer_wait() beats until a stick that is not this system's arrives (offered), a key is pressed, or the system stick leaves; sk_v4_identity_recheck_offered() runs the arrival check again once the mint has written it. Builds on three ISAs; not yet called.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 18:12:54 +00:00
Claude e94cd3245d feat(gpt): gpt_write_one -- a new disk of one partition, for the real Zuse's stick (#92, 4.3) [skip ci]
The old MBR zeroed first, the backup header and entries, the primary, the protective MBR last: a write torn anywhere leaves no table. Builds clean on amd64, aarch64, riscv64; checked on the host against blank 600 MiB and 32 MiB images and a used Zuse stick (sfdisk --verify clean, gpt_read reads it back). Not yet called.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 18:12:04 +00:00
Claude 1074520ec9 test(stick): mint_zuse seen to fail -- MINT-ZUSE unknown; its prompt check tightened (#92, 4.2) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 18:10:20 +00:00
Claude 4706ddf39a test(stick): MINT-ZUSE's first test, mint_zuse; Task 4's progress kept in the plan (#92, 4.1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 17:58:38 +00:00
Claude 9bb49ee623 FABRIC-3 XLVIII.15: the license's name in the headers; the 32 patent, formal and report files kept as they are [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 17:56:28 +00:00
Claude 16b9747d33 chore(license): the source headers name the Starship License 1.0 (SL-1.0), as LICENSE does [skip ci]
347 headers said "Licensed under the StarForth License, Version 1.0" -- a
shortening (Captain Bob, 2026-11-08: "License file SL I think I shortened
accidently"); LICENSE is, and has been since the first commit, the
Starship License 1.0 (SL-1.0, SPDX LicenseRef-Starship-1.0). 349 files,
566 occurrences, now "Starship License, Version 1.0 (SL-1.0)".

Left as they are, pending a ruling: docs/patent/ (the patent figures),
docs/formal/ (the citable volumes) and the generated reports under
docs/working/experiments/ (32 files). Comments and license text only:
the amd64 kernel builds, every changed script parses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 17:54:24 +00:00
rajames 594d2f93f0 Merge pull request 'The plug-and-play stick (#92 Tasks 1-3) and a BAM flush that moves only the volume (#155)' (#159) from StarForth-v4.0.0 into master
Reviewed-on: #159
2026-11-08 17:51:55 +00:00
Claude 411193166c Merge master into StarForth-v4.0.0: bring in #154's merge commit, so #159 is up to date with its base
Acceptance / Acceptance (pull_request) Successful in 20m15s
No file changes: master's only commit not on this branch is the merge of #154, whose contents are already here. Gitea's branch protection requires the PR branch to contain the base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 17:31:29 +00:00
Claude 186680724e docs(readme): v4.0.0-alpha.3, Try it, the plug-and-play stick, the acceptance gate
Build / Image RASPI (push) Successful in 5m33s
Build / Image PC (push) Successful in 4m12s
Build / Image MILKV (push) Successful in 6m1s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 11m14s
Acceptance / Acceptance (pull_request) Successful in 19m46s
The README still named v2.1.0 and an old dict_hash. Now: the version
(kernel 4.0.0-alpha.3, engine 3.2.0) and the release; Try it on the .com;
the stick (plug and play, the proxy Zuse, growth -- #92 Tasks 1-3), M9 on
the stick's GPT partitions; how a change reaches master (the acceptance
gate, every run a first boot); signed capsules and the Root CA; v3's
retirement (#156); `make write_stick`, `qemu-stick-high`; the stick and the
Book of Fabric in the documentation table. v4's dict_hash 0xfec8c47cfc6f437f.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 15:32:42 +00:00
Claude 929f0e13c5 fix(blocks): a BAM flush reads and writes only the pages that hold the volume's bits (#155)
Build / Image RASPI (push) Successful in 3m34s
Build / Image PC (push) Successful in 4m40s
Build / Image MILKV (push) Successful in 5m6s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 12m47s
Acceptance / Acceptance (pull_request) Successful in 18m32s
Accepted in full:
- amd64, aarch64, riscv64: PARITY:V4_POST tests=538 pass=538 fail=0,
  POST: PASSED, [zuse@Hera] ok> on a fresh data stick; dict_hash
  0xfec8c47cfc6f437f on the three
- the PC stick as built, loaded high: 538/538, the prompt
- make -C v4 test-32: 39 programs, 0 failures
- regressions: v3_keys, genesis on the three, stick_grow, midpull, hotplug

SAVE-BUFFERS on the 16 GiB stick: 5.1-6.1 s before, 1.1 s after; the BAM's
bytes the same (verdicts in logs/20261108-145611/verdicts/). FABRIC-3
XLVIII.14.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 15:03:43 +00:00
Claude 1354b30a78 logs: #155 regressions -- stick_grow, both boots: PASS [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 14:43:56 +00:00
Claude d2c11d4b6f logs: #155 regressions -- the second boots of genesis on aarch64 and riscv64 [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 14:38:18 +00:00
Claude cd579c8ec1 logs: #155 regressions -- genesis on aarch64 and riscv64: PASS [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 14:38:04 +00:00
Claude c0d0d03986 logs: #155 regressions -- v3_keys (v3 on the shared BAM code), genesis amd64: PASS [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 14:28:02 +00:00
Claude 52f48ed2a9 wip(blocks): a BAM flush reads and writes only the pages that hold the volume's bits (#155) [skip ci]
Not yet accepted. bam_flush_to_disk() and bam_sync_from_disk() read and
wrote every page of the BAM; with the stick's BAM sized for 256 GiB (6144
devblocks, 24 MiB) every flush of a dirty block moved 24 MiB each way.
They now touch only the pages that hold the 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.

Test (qemu_session.py bam_flush, --target qemu-stick --stick-gib 16):
three SAVE-BUFFERS of an Artemis block, each timed, then the BAM hashed.
Before: 5.1 / 5.6 / 6.1 s (the 2 s limit fails; it was set after seeing
this baseline). After: 1.1 / 1.1 / 1.1 s. The BAM's bytes the same either
way: sha256 79197a40...b9e44b50, 5 non-zero bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 14:21:57 +00:00
Claude b399cb7c35 test(build): acceptance boots a fresh data stick -- every run is a first boot (#92, Task 3)
Build / Image RASPI (push) Successful in 3m22s
Build / Image PC (push) Successful in 3m41s
Build / Image MILKV (push) Successful in 3m56s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 11m30s
Task 3 of plan 2026-10-29-stick-5, accepted in full:
- amd64, aarch64, riscv64: the proxy Zuse minted on a fresh data stick,
  PARITY:V4_POST tests=538 pass=538 fail=0, POST: PASSED, [zuse@Hera] ok>;
  dict_hash 0xfec8c47cfc6f437f on the three
- the PC stick as built, loaded high (stick_genesis): 538/538, the prompt
- make -C v4 test-32: 39 programs, 0 failures

Regressions pass. v3_keys failed once (a virtio_blk request never completed,
logs/20261108-132844) and passed on its rerun (logs/20261108-141539).
The plan's Task 3 steps ticked; FABRIC-3 XLVIII.13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 14:16:52 +00:00
Claude bc0faa69df logs: Task 3 regressions -- hotplug, the seven GPT modes, entropy on three ISAs: PASS (#92) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 14:15:01 +00:00
Claude 28f9f317ba logs: Task 3 regressions -- raw_ident, headless (no drive: no prompt): PASS (#92) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:45:18 +00:00
Claude 47b8eb262b logs: Task 3 regression -- stick_zuse: PASS (#92) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:40:21 +00:00
Claude d2353a5f67 FABRIC-3 XLVIII.11: the Book of Fabric is published with alpha.4 (#138) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:40:01 +00:00
Claude 190b0e8b05 logs: v3_keys FAIL -- a virtio_blk request never completed, the boot stalled before Zuse (#92, Task 3) [skip ci]
system=v3: Hestia logged 'virtio_blk: request never completed'; Hera reached the Zuse drive's attach and no further. Task 1's v3_keys (logs/20261108-043612) has no such line and passed. The drives were the same three, passed explicitly. To be rerun; bisected against Task 1 if it fails again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:37:55 +00:00
Claude 0f70f69e06 logs: acceptance stick-high (stick_genesis) and test-32, the verdicts of #92 Task 3's acceptance: PASS [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:29:35 +00:00
Claude a55571b25d FABRIC-3 XLVIII.12: a DoE per release, its own milestone (#158) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:29:14 +00:00
Claude e60cb5c245 logs: acceptance riscv64 on a fresh data stick: PASS (#92, Task 3) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:22:20 +00:00
Claude 24db454141 logs: acceptance aarch64 on a fresh data stick: PASS (#92, Task 3) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:20:27 +00:00
Claude 792e736bc0 logs: acceptance amd64 on a fresh data stick -- genesis, the prompt: PASS (#92, Task 3) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:15:53 +00:00
Claude eca00628f0 FABRIC-3 XLVIII.11: the Book of Fabric and the dictionary on the .com, ruled for alpha.4 (#138, #157) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:15:34 +00:00
Claude 9d6410c06f wip(build): acceptance boots a fresh data stick -- every run is a first boot (#92, Task 3) [skip ci]
Not yet accepted (plan 2026-10-29-stick-5, Task 3).
- kernel/Makefile: a v4 `qemu` boot attaches a fresh data stick
  (DATASTICK=1) and nothing else; ARTDISK/ZUSEDISK keep the minted pair only
  for system=v3 (QEMU_V3_BOOT, from KERNEL_ARGS).
- qemu_session.py: the Makefile's defaults for every mode but those that ask
  for the pair by name (stick_artemis, two_sticks, artemis_unsigned,
  raw_ident, v3_keys) or for no drive; `zuse` now expects the genesis line.
- nightly.sh: accept stick-high runs stick_genesis (the stick as built).
- .claude/CLAUDE.md "The disks", the stick-high line; disk/README.md (the
  pair: tests and v3 only); STICK.md 11, increments 3 and 5 done.

Before the change: zuse on amd64 FAIL -- the pair's "identity confirmed",
no genesis line (logs/20261108-130732).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:13:25 +00:00
Claude ec9eb5f225 FABRIC-3 XLVIII.10: retiring v3 is its own milestone (#156) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:02:43 +00:00
Claude e26c809a17 logs: the zuse session stopped by Captain Bob mid-run (#92, Task 3 -- not a verdict) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:02:01 +00:00
Claude def2336fc4 FABRIC-3 XLVIII.10: retire v3, ruled for alpha.5 (#156); #155 filed [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 13:01:30 +00:00
Claude f81b5d0563 feat(kernel): Artemis grows to fill the stick at its first boot -- metadata only, capped at 256 GiB (#92, Task 2)
Build / Image RASPI (push) Successful in 3m30s
Build / Image PC (push) Successful in 3m51s
Build / Image MILKV (push) Successful in 3m47s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 11m40s
Task 2 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 acceptance boots' logs, the accept-*.txt verdicts and test-32's output
(logs/20261108-123847/verdicts/). The plan's Task 2 steps ticked; FABRIC-3
XLVIII.9, with one item for a ruling: blk_flush rewrites the whole BAM, now
sized for 256 GiB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 12:45:33 +00:00
Claude a5c1136692 logs: Task 2 regressions -- artemis_unsigned, midpull (replug: not grown again): PASS (#92) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 12:31:02 +00:00
Claude 4bc8a01b4c logs: Task 2 regressions -- stick_zuse, two_sticks: PASS (#92) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 12:27:39 +00:00
Claude 7dbc1de864 logs: Task 2 regressions -- genesis on aarch64 and riscv64, stick_genesis, stick_boot: PASS (#92) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 12:21:32 +00:00
Claude add73563b2 logs: genesis on amd64 with the 256 GiB BAM on the data stick: PASS (#92, Task 2) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 12:08:21 +00:00
Claude 5bb247d678 wip(kernel): Artemis grows to fill the stick at its first boot -- metadata only, capped at 256 GiB (#92, Task 2) [skip ci]
Not yet accepted (plan 2026-10-29-stick-5, Task 2, step 3).
- gpt.c: the writer, gpt_grow_last() -- the backup entry array and header to
  the disk's end, the last partition to the last usable sector (whole MiB,
  capped), both headers' CRCs, the backup before the primary, the
  protective MBR's size; gpt_alternate_lba().
- sk_v4_grow.c: the volume grown to its partition -- its fence (the Artemis
  signature, Zuse's genesis marker) moved to the new top, the header last;
  the partition grown no further than the BAM tracks (the block subsystem
  places the fence by the device's size, so a volume must fill it).
- sk_v4_identity.c: a stick of 8 GB or more whose GPT ends short of the disk
  is grown before its partitions are opened; "Artemis: grown to fill the
  stick" / "under 8 GB -- not grown" / "past 256 GiB ... left unused".
- block_subsystem: blk_volume_compute_totals() (compute_totals_from_B,
  public) and blk_subsys_set_format_bam_for(); v3's behaviour unchanged.
- mkartemis --bam-for, mkdiskimage.sh --bam-for, kernel/Makefile
  STICK_GROW_MIN_BYTES / STICK_ARTEMIS_CAP_GIB: the stick's and data stick's
  Artemis BAM sized for 256 GiB (6144 devblocks). STICK.md 5a: 256 GiB (R1).

After: stick_grow PASS (16 GiB: 12129370 user blocks, 8 s POST to prompt;
second boot not grown, recognised; sfdisk --verify: no errors), stick_small
PASS, check_images.sh PASS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 12:03:46 +00:00
Claude 4e935e4825 test(stick): Artemis grows to fill the stick -- the tests, seen to fail (#92, Task 2) [skip ci]
Plan 2026-10-29-stick-5, Task 2, steps 1-2:
- qemu_session.py: --stick-gib N (the session's copy of the stick extended,
  sparse); modes stick_grow (16 GiB: grown, over 12000000 user blocks, the
  prompt, the first boot's time; the second boot of the same copy not grown
  again; sfdisk --verify clean) and stick_small (4 GiB: under 8 GB, not grown,
  said so).
- kernel/Makefile: STICK_GIB and STICK_FRESH on qemu-stick, for those.
- check_images.sh: the PC stick's and data stick's Artemis BAM sized for the
  256 GiB cap (6144 devblocks).

Before the change: stick_grow FAIL (no growth line, 1137649 user blocks,
sfdisk: the backup GPT not at the end); stick_small FAIL (no line);
check_images.sh FAIL on the two BAM checks only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 11:54:53 +00:00
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
rajames e695eadaf7 Merge pull request 'Release machinery for Downloads, the root CA, demo and site updates (#126)' (#154) from StarForth-v4.0.0 into master
Reviewed-on: #154
2026-11-08 03:20:42 +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
618 changed files with 52751 additions and 772 deletions
+15 -11
View File
@@ -291,8 +291,9 @@ The vendored hosted `make` build (above) is NEVER used to validate kernel change
make -f kernel/Makefile ARCH=amd64 clean qemu
make -f kernel/Makefile ARCH=aarch64 clean qemu
make -f kernel/Makefile ARCH=riscv64 clean qemu
# ...the PC stick loaded above 2 GiB, as a PC's firmware loads it (pc machine, 3 GiB; with
# Zuse's pair in the stick: scripts/qemu_session.py stick_zuse amd64 --target qemu-stick-high):
# ...the PC stick loaded above 2 GiB, as a PC's firmware loads it (pc machine, 3 GiB; the stick as
# built, its first boot minting its own Zuse: scripts/qemu_session.py stick_genesis amd64
# --target qemu-stick-high):
make -f kernel/Makefile ARCH=amd64 clean qemu-stick-high
# ...and the 32-bit build -- v4 with 32-bit cells, the F18/Zynq (FPGA) case: its nucleus
# image and every v4 test at that width (no QEMU; not a substitute for the boots above):
@@ -326,14 +327,17 @@ audit artifacts — they are committed to the repo. Do not delete them. There is
timestamped convention (self-documented via its own README); not a contradiction, just a
second, less-structured log location.
**The disks (Captain Bob, 2026-10-26, the identity gate):** with no identity thumbdrive the system
is headless -- no prompt -- so every boot needs Zuse. `kernel/Makefile`'s `ARTDISK` and `ZUSEDISK`
default to the minted Zuse pair, `disk/zuse-scratch/artemis.img` and `zuse-thumb-ident.img` (a
pair: her genesis marker is on that Artemis disk; `disk/README.md`). Since 2026-10-28 `ZUSEDISK`
is that pair laid out as a stick (`make ... zusestick`, `build/<arch>/kernel/zusestick.img`, made
fresh for every boot: identity and Artemis partitions on one USB disk, STICK.md §4); `ARTDISK`
stays the pair's Artemis file. v3 reads identity drives raw, never through a GPT, so a `system=v3`
boot needs `ZUSEDISK=disk/zuse-scratch/zuse-thumb-ident.img` (a copy) to log Zuse in. Put both back as committed (`git checkout -- disk/zuse-scratch`)
**The disks (plan 2026-10-29-stick-5, Task 3, 2026-11-08):** with no identity the system is
headless -- no prompt -- so every boot needs Zuse. A v4 `qemu` boot attaches a **fresh data stick**
(`DATASTICK`, `make ... datastick`, `build/<arch>/kernel/datastick.img`: identity and Artemis
partitions, made fresh for every boot) and nothing else: its first boot mints the stick's proxy
Zuse (STICK.md §6), so **every acceptance run is a first boot** -- plug and play. `DATASTICK=`
boots v4 with no drive (headless). The minted Zuse pair (`disk/zuse-scratch/`, `disk/README.md`)
is for the tests that ask for it by name (`scripts/qemu_session.py`: `stick_zuse`, `two_sticks`,
`stick_artemis`, `raw_ident`, `v3_keys`, the hot-plug and GPT modes) and for `system=v3`, whose
defaults are unchanged: `ARTDISK` the pair's Artemis, `ZUSEDISK` the pair as a stick (v3 reads
identity drives raw, so a `system=v3` boot needs `ZUSEDISK=disk/zuse-scratch/zuse-thumb-ident.img`,
a copy, to log Zuse in). Put the pair back as committed (`git checkout -- disk/zuse-scratch`)
before each architecture. The prompt is `[zuse@Hera] ok> `.
Do not claim a change is accepted until all three architectures have booted, and their logs are
@@ -343,7 +347,7 @@ present in `logs/`:
the three;
- **the PC stick loaded high** (Captain Bob, 2026-10-29, after the SER5 page-faulted in the
loader -- q35 always loads the image below 2 GiB, a PC's firmware does not; `FABRIC-3.md`
§XLIV): `qemu-stick-high` to `[zuse@Hera] ok> ` with the same `PARITY:V4_POST ... fail=0` and
§XLIV): `qemu-stick-high` -- the stick as built, a first boot -- to `[zuse@Hera] ok> ` with the same `PARITY:V4_POST ... fail=0` and
`POST: PASSED`. The amd64 link also refuses any 32-bit absolute or GOT relocation in the image;
don't work around that check, fix the code it names;
- **the 32-bit build** (Captain Bob, 2026-10-14: "the 32 bit build needs to go into the
+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:
+32 -6
View File
@@ -1,10 +1,15 @@
# LithosAnanke v2.1.0
# LithosAnanke v4.0.0-alpha.3
**UEFI-bootable FORTH microkernel.** Boots from firmware, initialises memory and interrupts, then
runs StarForth as its sole userspace runtime. No libc. No OS. Just stone and necessity.
*Lithos* (foundation) + *Ananke* (necessity) — the kernel under StarshipOS.
**Try it in your browser:** [starshipos-f18.com](https://starshipos-f18.com/) — a StarshipOS
machine of your own, booted to `[zuse@Hera] ok>`, thrown away when you leave. **Releases:**
[v4.0.0-alpha.3](https://gitea.starshipos-f18.org/rajames/LithosAnanke/releases) (pre-release),
the kernel `4.0.0-alpha.3` with the StarForth engine `3.2.0`.
---
## Products
@@ -22,7 +27,8 @@ FORTH-79 is recomposed on the F18 engine and stored as a capsule; the StarshipOS
vocabulary gets the same treatment. v3 remains the reference system until v4 meets its
acceptance criteria (`docs/v4.0.0/JUSTIFICATION.md` §16). **Both run on bare metal now:** every
board image carries v4 and v3, boots v4 as built, and one word in its boot configuration
chooses (see below).
chooses (see below) — except the PC stick, which is v4 only. **v3 is being retired** (its own
milestone, #156): what v4 needs of it, the block layer, moves into v4 and the rest is removed.
---
@@ -34,14 +40,22 @@ chooses (see below).
| M7 | StarForth VM integration + parity validation | ✅ Complete |
| M7.1 | Capsule birth · Mama FORTH vocabulary · the Tripod fleet · kernel-Hermes · word-level ACL | ✅ Live |
| M8 | Keyboard input to the REPL — PS/2, virtio and **USB** keyboards (a full keyboard: Caps/Num Lock, keypad) | ✅ In QEMU, all three ISAs |
| M9 | Block storage — Artemis's disk on virtio-blk; identity thumbdrives on USB mass storage | ✅ In QEMU · real disks: no driver yet (`boards/BRINGUP.md` A4) |
| M9 | Block storage — on v4, Artemis and Zuse's identity on the StarshipOS stick (GPT partitions, over USB mass storage); v3's Artemis on virtio-blk | ✅ In QEMU · real disks: no driver yet (`boards/BRINGUP.md` A4) |
| The stick | One USB stick is the whole OS: plug it in, boot, `[zuse@Hera] ok>` — its first boot mints its own Zuse and grows Artemis to fill it (`docs/v4.0.0/STICK.md`, #92) | ✅ Tasks 1–3 of 5 in QEMU · the real Zuse on a second stick next |
| Bare metal | a generic PC (amd64; first on the bench: a Beelink SER5), Raspberry Pi 5 (aarch64), Milk-V Mars (riscv64); Zynq-7020 (ARMv7) not yet ported | Images build; first boots on the bench — `boards/BRINGUP.md` |
**v4 is the default build, and v3 is being retired**: every kernel boots v4 unless its boot
arguments say `system=v3`. POST at boot, on all three ISAs: v4 — **538 tests**,
`PARITY:V4_SYSTEM word_count=317 dict_hash=0xe5a57f3eb72ff94a`; v3 — **1052 tests**,
`PARITY:V4_SYSTEM word_count=317 dict_hash=0xfec8c47cfc6f437f`; v3 — **1052 tests**,
`PARITY:M7.1a word_count=526 hash=0x82f4ae7cb2e2d424`.
**How a change gets in** (the Captain Bob method): `master` is reached only through a pull request
that passed **acceptance** — amd64, aarch64 and riscv64 booted in QEMU to `[zuse@Hera] ok>`, POST
538/538 and one `dict_hash` on all three; the PC stick booted loaded above 2 GiB, as a PC's firmware
loads it; and the 32-bit build's tests. Every acceptance boot starts from a fresh stick, so every
run is a first boot. The same stages run nightly and for every release (`scripts/nightly.sh`); the
serial logs are committed.
### What's live
- **The Tripod** — a named multi-VM fleet: **Hera** (the Mama VM, the governor), **Artemis**
@@ -50,9 +64,14 @@ arguments say `system=v3`. POST at boot, on all three ISAs: v4 — **538 tests**
- **kernel-Hermes** — messaging moved into the kernel (the Hermes VM is gone,
`docs/fabric/FABRIC-3.5.md`): every VM takes its own messages on its own turn, under a
cooperative switcher that every VM takes part in.
- **The plug-and-play stick** (v4) — `make boot_image TARGET=PC` and `make write_stick
DEVICE=/dev/sdX`, plug it in, boot: the stick's first boot mints its own Zuse (no two sticks share
one) and grows its Artemis partition to fill the stick, up to 256 GiB, writing metadata only.
- **Identities on thumbdrives** — Zuse, the superuser, and every user is a minted USB
thumbdrive (Ed25519, Zuse-signed); plugging one in births that user's VMs, pulling it out
ends them. There is only the drive: no password, no PIN.
- **Signed capsules** — the capsules the kernel boots from are signed under the StarshipOS Root CA
(`ci/pki/starshipos-root-ca.pem`, published with every release) and checked at boot.
- **Word-level ACL** — every dictionary entry carries a TTL/allow/mode/pin access-control
record; strict, TTL and pinned modes; two console layers (emergency `ok>` and superuser
`zuse)ok>`). Measured overhead of the live ACL-TTL mechanism: **+0.0603%**, CV 0.000%,
@@ -84,10 +103,16 @@ make # every board with a kernel port + hosted v3 +
make docs # build/docs/LithosAnanke.pdf (LaTeX master: docs/book/main.tex)
make clean TARGET=RASPI # that board's outputs and build/aarch64/kernel
# The kernel in QEMU (OVMF / AAVMF / EDK2), one architecture at a time -- boots v4
# The PC stick, written to a real USB stick (checks the device, asks you to type its name back,
# verifies the write); then boot it from the PC's firmware boot menu
make write_stick DEVICE=/dev/sdX
# The kernel in QEMU (OVMF / AAVMF / EDK2), one architecture at a time -- boots v4 from a fresh
# data stick, so every boot is a stick's first boot
make -f kernel/Makefile ARCH=amd64 clean qemu
make -f kernel/Makefile ARCH=aarch64 clean qemu
make -f kernel/Makefile ARCH=riscv64 clean qemu
make -f kernel/Makefile ARCH=amd64 clean qemu-stick-high # the PC stick itself, loaded high
make -f kernel/Makefile ARCH=amd64 KERNEL_ARGS=system=v3 clean qemu # v3, while it remains
# The Pi 5's native boot path, rehearsed on QEMU's virt machine at EL2
@@ -123,7 +148,8 @@ which to believe. Among them:
| | |
|---|---|
| [The FABRIC record](docs/fabric/) | Every design decision and the work as it happened (`FABRIC-3.md` is the living one) |
| [The FABRIC record](docs/fabric/) | Every design decision and the work as it happened (`FABRIC-3.md` is the living one) — published as *The Book of Fabric* from alpha.4 |
| [The stick](docs/v4.0.0/STICK.md) | The x86-64 StarshipOS stick: plug and play, the proxy Zuse, growth |
| [StarForth v4](docs/v4.0.0/) | The F18-derived engine |
| [Board bring-up](boards/BRINGUP.md) | Getting onto a PC, the Pi 5 and the Mars |
| [Roadmap and versioning](docs/reference/ROADMAP.md) | Milestone plan and release-versioning policy |
+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
+8 -1
View File
@@ -168,7 +168,14 @@ carrying timestamp noise in git history.
image's bytes, each exactly its file's size), fresh before every boot, and
that is `ZUSEDISK`'s default; `make boot_image TARGET=PC
STICK_PAIR=disk/zuse-scratch` puts the pair in the PC stick the same way.
The files here are unchanged. Increment 5 retires the pair.
The files here are unchanged.
**For tests and v3 only (2026-11-08, plan 2026-10-29-stick-5, Task 3):** a
v4 `qemu` boot no longer attaches the pair; it attaches a fresh data stick,
whose first boot mints its own Zuse. The pair stays for the tests that ask
for a known Zuse by name (`scripts/qemu_session.py`'s `stick_zuse`,
`two_sticks`, `stick_artemis`, `raw_ident`, `v3_keys`, the hot-plug and GPT
modes) and as the defaults of a `system=v3` boot.
- **The StarshipOS stick and data stick are not here** (2026-10-27,
`docs/v4.0.0/STICK.md` §4, §9): they are build output, made fresh by
+263
View File
@@ -6191,3 +6191,266 @@ 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).
### 15. The license's name in the headers (2026-11-08)
- **Found:** `LICENSE` is the Starship License 1.0 (SL-1.0) and always has been; 347 source headers
said "StarForth License, Version 1.0" (Captain Bob: "I think I shortened accidently").
- **Done:** 349 files, 566 occurrences, now "Starship License, Version 1.0 (SL-1.0)" (16b9747d).
- **Ruled:** the 32 others **keep "StarForth License" as they are** -- `docs/patent/` (the patent
figures), `docs/formal/` (the citable volumes) and the generated reports under
`docs/working/experiments/`. Not to be swept.
+13 -4
View File
@@ -122,9 +122,13 @@ gains the partitions below). Three partitions:
- **The minimum stick: 8 GB.** Sticks on the shelf are 16–64 GB; 8 GB is the floor.
- **The identity partition stays 500 MiB.** About half a million 1 KiB blocks for Zuse's keys and
her own pool.
- **Artemis grows to fill the stick at its first boot (§5a),** up to **2 TiB** for the partition
(the block layer numbers 1 KiB blocks with 32 bits: 4 TiB is its hard limit; 2 TiB keeps a margin
and is past any thumb drive). Space past 2 TiB is left unused, and the boot says so.
- **Artemis grows to fill the stick at its first boot (§5a),** up to **256 GiB** for the partition
(**amended 2026-10-29**, Captain Bob: "256 GiB is ruled" -- plan
`plans/2026-10-29-stick-5-proxy-zuse-and-real-zuse.md`, R1. This said 2 TiB: the block layer
numbers 1 KiB blocks with 32 bits, so 4 TiB is its hard limit, but the block subsystem keeps two
bytes of kernel heap per block and the heap is 2 GiB, so a 2 TiB Artemis could not attach; 256 GiB
takes about 384 MiB. The stick's Artemis is formatted with a BAM sized for 256 GiB, so growth
writes metadata only.) Space past 256 GiB is left unused, and the boot says so.
- **A stick under 8 GB** is not grown: it runs at the 2 GiB it was written with, and the boot says
so.
- **The Artemis partition is formatted when the image is built (my call),** not on first boot:
@@ -168,7 +172,7 @@ Before genesis, on a stick whose GPT ends where the 2 GiB image ended and whose
first boot of a freshly written stick), the kernel grows Artemis:
- It moves the backup GPT header and entry array to the disk's end, extends the Artemis partition's
last LBA to the end of the usable space (capped at 2 TiB of partition), and rewrites both headers
last LBA to the end of the usable space (capped at 256 GiB of partition, amended -- §4), and rewrites both headers
with their CRCs (the GPT writer; `INSTALL` reuses it).
- It grows Artemis's volume to the partition: its `STFR` header's size, its free map for the new
blocks, and its metadata fence (with the genesis marker's slot) moved to the new top, as the block
@@ -348,6 +352,9 @@ first and seen to fail:
`qemu` targets behind `DATASTICK=1`, off by default -- until increments 4 and 5 the kernel cannot
take Artemis from it or mint Zuse onto it, so as the default it would leave every acceptance boot
headless. Increment 5 turns it on and retires the scratch pair and the virtio disk.
**Done 2026-11-08** (plan `2026-10-29-stick-5`, Task 3): a v4 `qemu` boot attaches a fresh data
stick and nothing else; the scratch pair stays only for the tests that ask for it and for
`system=v3`.
4. **Artemis and Zuse from one disk:** the boot device from the loader, the partitions found and
attached, virtio Artemis off the v4 path; recognition of a minted stick; entropy on the v4 path;
`system=v3` refused on a stick (§4, §5).
@@ -357,6 +364,8 @@ first and seen to fail:
recorded) and a 4 GB one (below the minimum: not grown, said so).
**Amended 2026-10-29:** the genesis is the proxy's, with the version 2 marker (§6); the fresh
stick's first boot reaching `[zuse@Hera] ok>` with nothing set up is the test of plug and play.
**Done 2026-11-08** (plan `2026-10-29-stick-5`, Tasks 1-3; `FABRIC-3.md` XLVIII.8-9): growth is
capped at 256 GiB (R1); every acceptance run is now a first boot.
5a. **The real Zuse stick (2026-10-29)** (§6a): `MINT-ZUSE` and its confirmation, the GPT and
identity written to the second stick, the marker's real key; recognition of the real Zuse
stick; the fixed screen and its R; the old stick refused after a replacement.
@@ -146,7 +146,7 @@ xHCI USB sticks, `scripts/qemu_session.py`.
- **The Artemis partition must be formatted to take the marker:** `blk_subsys_confirm_format` only
if the slot is provisional and its `artemis_sig_t` checked out (§4).
- [ ] **Step 1: Failing tests** (harness):
- [x] **Step 1: Failing tests** (harness):
- **`genesis`** (three ISAs): a fresh data stick (`DATASTICK=1 ZUSEDISK=`), built once into the
session directory (`DATASTICK_IMG=<work>/data.img DATASTICK_DEP=`) and booted twice, one QEMU at
a time. First boot: the genesis line, `[zuse@Hera] ok> `, `3 4 + .` → `7 ok`. Second boot:
@@ -155,12 +155,12 @@ xHCI USB sticks, `scripts/qemu_session.py`.
reaches the prompt. Today: FAIL (headless).
- **Changed:** `stick_boot` expected the blank stick headless; it now expects the genesis line and
the prompt.
- [ ] **Step 2:** Run each: FAIL as listed.
- [ ] **Step 3:** Implement.
- [ ] **Step 4:** The new sessions pass; regression: `zuse` (the pair, version 1: logs in as the
- [x] **Step 2:** Run each: FAIL as listed.
- [x] **Step 3:** Implement.
- [x] **Step 4:** The new sessions pass; regression: `zuse` (the pair, version 1: logs in as the
proxy), `stick_zuse`, `stick_artemis`, `two_sticks`, `artemis_unsigned`, `raw_ident`, `hotplug`,
`midpull`, `waitpull`, `typeahead`, the GPT modes, `v3_keys` (v3's genesis and marker unchanged).
- [ ] **Step 5:** Suite; full acceptance; commit `feat(kernel): the proxy Zuse -- a stick's first
- [x] **Step 5:** Suite; full acceptance; commit `feat(kernel): the proxy Zuse -- a stick's first
boot mints its own Zuse; the genesis marker's version 2` with the logs.
### Task 2: Artemis grows to fill the stick
@@ -195,7 +195,7 @@ xHCI USB sticks, `scripts/qemu_session.py`.
GPT, open Artemis, `sk_v4_grow_artemis`, then on as Task 1. Under 8 GB → the "not grown" line,
once. Past the cap → the "left unused" line.
- [ ] **Step 1: Failing tests:**
- [x] **Step 1: Failing tests:**
- **`stick_grow`** (amd64, `--target qemu-stick --stick-gib 16`): first boot: `grown to fill the
stick`, Artemis's `blk: disk` line over 12000000 user blocks (`KERNEL_ARGS=--log-level=info`),
the genesis line, the prompt; the first boot's time printed by the harness (POST to prompt).
@@ -205,11 +205,11 @@ xHCI USB sticks, `scripts/qemu_session.py`.
prompt. Today: FAIL (no line).
- **`check_images.sh`:** the PC stick's and data stick's Artemis BAM is the cap's size
(`mkartemis --check` reports it). Today: FAIL.
- [ ] **Step 2:** Run each: FAIL as listed.
- [ ] **Step 3:** Implement.
- [ ] **Step 4:** They pass; regression: `genesis`, `stick_genesis`, `stick_zuse`, `two_sticks`,
- [x] **Step 2:** Run each: FAIL as listed.
- [x] **Step 3:** Implement.
- [x] **Step 4:** They pass; regression: `genesis`, `stick_genesis`, `stick_zuse`, `two_sticks`,
`artemis_unsigned`, `midpull` (replug: not grown again).
- [ ] **Step 5:** Suite; full acceptance; commit `feat(kernel): Artemis grows to fill the stick at
- [x] **Step 5:** Suite; full acceptance; commit `feat(kernel): Artemis grows to fill the stick at
its first boot -- metadata only, capped at 256 GiB` with the logs and the first-boot time.
### Task 3: acceptance on a fresh data stick
@@ -227,13 +227,13 @@ xHCI USB sticks, `scripts/qemu_session.py`.
**Interfaces:** `make -f kernel/Makefile ARCH=<arch> clean qemu` boots v4 with a fresh data stick
on port 2 and no other drive: a first boot every time, the proxy minted, the prompt.
- [ ] **Step 1: Failing test:** `zuse` with the new default (no `--make`): the genesis line and the
- [x] **Step 1: Failing test:** `zuse` with the new default (no `--make`): the genesis line and the
prompt on all three ISAs. Today: FAIL (the pair is the default; no genesis line).
- [ ] **Step 2:** Run it: FAIL.
- [ ] **Step 3:** Change the defaults and the docs.
- [ ] **Step 4:** `zuse` passes on three ISAs; `qemu-stick-high` reaches the prompt from a fresh
- [x] **Step 2:** Run it: FAIL.
- [x] **Step 3:** Change the defaults and the docs.
- [x] **Step 4:** `zuse` passes on three ISAs; `qemu-stick-high` reaches the prompt from a fresh
PC stick; regression: `v3_keys`, `stick_zuse`, `raw_ident`, the GPT modes, `entropy`.
- [ ] **Step 5:** Suite; full acceptance as newly written; commit `test(build): acceptance boots a
- [x] **Step 5:** Suite; full acceptance as newly written; commit `test(build): acceptance boots a
fresh data stick -- every run is a first boot` with the logs.
### Task 4: `MINT-ZUSE` -- the real Zuse onto a second stick
@@ -343,3 +343,24 @@ on port 2 and no other drive: a first boot every time, the proxy minted, the pro
- [ ] **Step 6:** A new PC stick (`make boot_image TARGET=PC`, no `STICK_PAIR`) for the SER5, and
the bench steps written in `boards/BRINGUP.md`: plug in, boot, the prompt; `MINT-ZUSE` onto the
second stick; boot with the system stick alone (the fixed screen); with both (the prompt).
---
## Progress (kept current, one line per increment -- where to pick up)
Tasks 1-3 accepted and merged (#159, master 594d2f93); #155 merged with them.
**Task 4, `MINT-ZUSE`** (Captain Bob, 2026-11-08: "work in small increments and memorize frequently"):
- [x] 4.1 the first failing test: `qemu_session.py` mode `mint_zuse` and `add_stick(n, img, port)`
- [x] 4.2 run `mint_zuse` on amd64 before any kernel change: FAIL, "UNKNOWN WORD: 'MINT-ZUSE'" (logs/20261108-175928); the prompt check tightened to need the minted line first
- [x] 4.3 `gpt_write_one()` in `kernel/src/gpt.c` (one partition, protective MBR, both headers): builds clean on three ISAs; checked on the host (a throwaway harness, not in the tree) -- 600 MiB and 32 MiB blank images and the pair's used Zuse stick each give one identity partition, `gpt_read` reads it back, `sfdisk --verify` clean. Not yet called.
- [x] 4.4 `sk_v4_identity_offer_wait()` / `sk_v4_identity_recheck_offered()`: a stick offered, not attached, while a mint waits (`g_mint_waiting`, `g_offered` in `sk_v4_identity.c`; any stick not this system's and readable -- blank, foreign or a bad table; ends on a stick, a key, or the system stick leaving). Builds on three ISAs; not yet called.
- [x] 4.5 `sk_v4_mint.c`: the flow -- plug-in line, size line, `YES`, GPT, zeroed, minted, read back, marker. Builds on three ISAs; not yet called. The gate gained a **spare**: the last stick turned away as not this system's (or handed back by a refused mint) is offered first by the next mint (for `mint_zuse_refuse`: "a second `MINT-ZUSE` is offered again"); and accessors `sk_v4_identity_stick_in/offered_present/release_offered/marker/set_marker`.
- [x] 4.6 `MINT-ZUSE` in `sk_v4_words[]` (request 2): word_count 317 -> 318. Builds; `mint_zuse` running on amd64 (build/t4/mint-46.txt).
- [ ] 4.7 the real Zuse stick recognised and attached after the system stick; her session
- [ ] 4.8 `mint_zuse` passes on amd64; then the other tests: `mint_zuse_refuse`, `mint_pull_system`, `zuse_stick_first`, `mint_small`, the pair's stick offered
- [ ] 4.9 regressions, full acceptance on three ISAs (new dict_hash, equal), FABRIC entry, commit
Working notes: the boot's own words are `sk_v4_words[]` in `kernel/src/v4/sk_v4.c`, served by
`sk_v4_serve(node, request)` with request = index + 1 (`BYE` is 1). Sticks are added in the harness
on port 3 (port 1: the minted pair's stick when a test names it; port 2: the data stick).
@@ -7,7 +7,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -26,7 +26,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -8,7 +8,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -27,7 +27,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -7,7 +7,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -26,7 +26,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -8,7 +8,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -27,7 +27,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -7,7 +7,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -26,7 +26,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -19,7 +19,7 @@ This script analyzes:
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -38,7 +38,7 @@ This script analyzes:
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -20,7 +20,7 @@ in the physics engine validation experiment. Analyzes:
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -39,7 +39,7 @@ in the physics engine validation experiment. Analyzes:
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -7,7 +7,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -26,7 +26,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -8,7 +8,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -27,7 +27,7 @@
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -19,7 +19,7 @@ This script analyzes:
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -38,7 +38,7 @@ This script analyzes:
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -20,7 +20,7 @@ in the physics engine validation experiment. Analyzes:
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:
@@ -39,7 +39,7 @@ in the physics engine validation experiment. Analyzes:
#
# This file is part of the StarForth project.
#
# Licensed under the StarForth License, Version 1.0 (the "License");
# Licensed under the Starship License, Version 1.0 (SL-1.0) (the "License");
# you may not use this file except in compliance with the License.
#
# You may obtain a copy of the License at:

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