218 Commits
Author SHA1 Message Date
Claude ee28530b1c logs: the protocol for e8e7ec8b -- PASS (#189 Phase 2, the word accounts at call)
Build / Image PC (push) Successful in 10m18s
Build / Image MILKV (push) Successful in 7m59s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 23m14s
Build / Image RASPI (push) Successful in 9m34s
Acceptance / Acceptance (pull_request) Failing after 34m15s
All eight stages passed: the four boots (POST 539/539, word_count=377, dict_hash=0xa854ba15b437d288 on all
three architectures, Hera's words admitted to the Stadium after POST on each), test-32 (39 programs, 0
failures), the proofs, the images, the documents. logs/20261113-191247/PROTOCOL.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 19:46:19 +00:00
Claude e8e7ec8b9f feat(v4): word accounts at call -- the word ID in the header, the kernel's records, the Stadium charged per tick (#189)
ENGINE step 4 Phase 2 (plan docs/v4.0.0/plans/2026-11-13-engine-step4-phase2-word-accounts.md). Rulings,
Captain Bob 2026-11-13: "ID field in the header"; "Per heartbeat tick"; the ACL "All of it in Phase 4".

- The word ID, at xt-4 before the flags (ENGINE.md 3b). The system's words are numbered as they are
  assembled, by a new directive, #id, (and #ids, the count), in the C assembler (text.c) and in the
  machine ROM's (capsules/v4/rom), which counts in the system's own (NEXT-ID). (HEADER) numbers later
  words; FORGET gives back the IDs it frees, always the newest; COLD resets to (BOOT-ID); (SEAL) records
  it. All 313 system headers carry the cell.
- The kernel's records (v4/mesh.h): (TELL-DEFINED) and (TELL-FORGOTTEN), requests -19/-20 on port 0,
  which the kernel puts in (WORD-DEFINED)/(WORD-FORGOTTEN) when it seals a node, and reads the system's
  own words once. A bit per address marks a word's xt (calls into the ROM or headerless code are not
  words); at call, the bit test and a count. v4_mesh_charge hands the owner the calls since.
- The Stadium: stadium_words_charge -- N calls as N of stadium_word_dispatch's dispatches, shared by calls
  when the reservoir is short; sk_v4.c charges every node's words at the tick beside its opcodes, and
  stadium_word_forget before an ID is used again.
- Tests first: test_text.c, test_host_dict.c, test_host_quit.c (numbering, FORGET, COLD),
  test_mesh_boot.c (44 checks), kernel/tests/test_stadium_words.c; qemu_session.py: Hera's words
  admitted after POST.
- amd64: Stadium words: promotions=141 after POST, CONSERVED; POST 539/539; word_count=377;
  dict_hash 0xa854ba15b437d288 (the new cell); the boot 142 s against Phase 1's 153 s.
- v4 test, test-32: all pass; v4-checks: 80 programs under the sanitizers, 0 failures; the hosted
  builds alike. docs/reference/v4-dictionary.tsv: the two new words; FABRIC-3 XLVIII.24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 19:12:44 +00:00
Claude d64ad4a1c3 logs: the protocol for 046ce0be -- PASS (#189, the mesh boot to spec and its edges)
Build / Image PC (push) Successful in 10m39s
Build / Image MILKV (push) Successful in 6m1s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 16m34s
Acceptance / Acceptance (pull_request) Failing after 40m20s
Build / Image RASPI (push) Successful in 11m3s
All eight stages passed: the four boots (POST 539/539, word_count=375, dict_hash=0xbbf72b1f752a1a51 on
all three architectures, the edge cases on amd64), test-32 (39 programs, 0 failures), the proofs, the
images, the documents. logs/20261113-170011/PROTOCOL.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 17:36:21 +00:00
Claude 046ce0be65 feat(v4): the mesh boot to spec -- Hera born empty in the kernel's fabric; births, kills, every node stepping together (#189)
ENGINE step 4 Phase 1, Tasks 5b-5d, and the edge cases (Captain Bob, 2026-11-13: "Build it to proper
spec"; "Check for the edge cases"; "Yes, add it to v4-checks").

- v4/system/mesh.c, v4/include/v4/mesh.h: the nucleus assembled by the ROM and given to Hera as F18
  cells; Hera born empty at place 0, the kernel on port 0, the console on port 1; told she is 10, in the
  registry, the kernel's words, FORTH-79, sealed, POST, the kernel's capsules. NODE-BORN / NODE-KILL in
  the owner's room.
- No scheduler: v4_mesh_tell returns once the node told says how its text ended, and
  v4_mesh_step / v4_mesh_busy let the host step the fabric while it waits, so nodes run between
  lines as during them. A text left "waiting" is owed its end: the next line ends it "Interrupted"
  and is then run (MESH.md 7b.6).
- kernel: sk_v4.c boots through the mesh; its idle steps the fabric while a node can run, and halts
  only when none can (#151 kept). stadium_return_quota and stadium_ops_forget on a kill.
- Tests: v4/tests/test_mesh_boot.c (32 checks: the boot, births, kills, rebirth, a live number, a
  fault, no such node, Hera not killing herself, no room, a line too long, a node running for ever,
  a wait broken by the next line), run by `make -C v4 test` and under ASan+UBSan by `sanitize`
  (v4-checks); kernel/tests quota return; scripts/qemu_session.py births() and the edges on bare
  metal.
- Docs: ENGINE.md 6 "who runs next" struck (settled: no scheduler); the Phase 1 plan; FABRIC-3
  XLVIII.23; .claude/memory/rules.md: alpha.5 closed to new work.
- Evidence: v4-checks 80 programs under the sanitizers, 0 failures; the hosted builds alike; two
  stopped v4-checks runs labelled STOPPED; three development amd64 boots labelled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 17:00:08 +00:00
Claude d7d3e088db logs: the developer protocol on f10d2bc8 -- PASS, all eight stages
Build / Image RASPI (push) Successful in 5m53s
Build / Image MILKV (push) Successful in 9m0s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 20m46s
Acceptance / Acceptance (pull_request) Successful in 23m51s
Build / Image PC (push) Successful in 10m4s
#189 Phase 1 Task 5a: Hera in the kernel's fabric and registry. On the
four boots: NODE-ME . gives 0 ok, the physics lines as before, POST
539/539; word_count 375 and dict_hash 0x06531687cc075aee on all three
architectures (centre.4th and hera.4th loaded); test-32 39 programs 0
failures; proofs; images; documents, the dictionary covering all 375
live words. Every boot under timeout 570. logs/20261113-142432/PROTOCOL.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 14:50:29 +00:00
Claude f10d2bc835 feat(kernel): Hera in the kernel's fabric and registry; centre.4th and hera.4th on her
#189, ENGINE step 4 Phase 1, Task 5a. Captain Bob, 2026-11-13: "Full
births now"; "Hera as now, in a fabric".

- sk_v4.c: the kernel's fabric (v4/fabric.h), Hera's node at its one
  place, entered in its registry (v4/manage.h) as node 10. The registry's
  answers are real: a birth is "no room" -- the fabric has one place
  until 5b; CAPSULE-OPEN/-LINE read the kernel's capsule directory,
  checked as the boot checks (no capsule of F18 code is there until 5b);
  a born node's parity line. She is not told her number: the boot's
  console addresses node 0 (told 10, the boot stopped after POST -- kept,
  labelled, logs/20261113-132712).
- boot.h/boot.c: v4_boot's `request` hook (the registry's requests) and
  `capsules` (the kernel's own, loaded before the seal, so POST runs on
  them). hosted.c sets neither: the hosted product's boot is as it was.
- kernel/Makefile: manage.c in the kernel's v4 engine.
- qemu_session.py: a v4 acceptance boot asks NODE-ME . and wants 0.
- v4-dictionary.tsv: the 55 words of centre.4th and hera.4th, written
  from their source and manage.h; mkdictionary.py loads the kernel's
  capsules into the hosted system before WORDS, so the live list is the
  kernel's -- 375 words.
- .claude/memory/rules.md, rule 6: every boot command under timeout 570.

Seen to fail first (logs/20261113-132410): NODE-ME was an unknown word.
After: amd64 NODE-ME . gives 0 ok; POST 539/539; word_count 375. v4
suite: test, test-32 99 programs 0 failures; v4-checks 79 under the
sanitizers 0 failures, the hosted builds alike.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 14:24:27 +00:00
Claude c32cd04388 logs: the developer protocol on b1cac339 -- PASS, all eight stages
Build / Image RASPI (push) Successful in 6m54s
Build / Image PC (push) Successful in 10m7s
Build / Image MILKV (push) Successful in 7m35s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 21m45s
Acceptance / Acceptance (pull_request) Successful in 29m35s
#189 Phase 1, Tasks 1-4: v4 in the kernel's boot. On the four boots: the
Stadium made ("Stadium: 83886 cells"), POST 539/539, "Stadium opcodes: 30
resident, hottest opcode 8", "Stadium conservation: CONSERVED", the quota
self-test and the heartbeat's ticks -- the new physics check passing;
word_count 320 and dict_hash 0x47570d4ced6ce255 on all three
architectures, unchanged; test-32 39 programs 0 failures; proofs; images;
documents. logs/20261113-125011/PROTOCOL.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 13:17:24 +00:00
Claude b1cac339c1 feat(kernel): v4 boots in the kernel's boot -- the Stadium, its checks, the opcode patrons
#189, ENGINE step 4, Phase 1 (plan 2026-11-13-engine-step4-phase1), Tasks
1-4. Captain Bob, 2026-11-13: Q1 "A new node key", Q2 "Per heartbeat
tick", Q3 "All of v3's", Q4 "In Phase 1" / "Full births now", who runs
next "Hera by compudynamics now" (Task 5, to come).

- stadium.c/.h: stadium_node_key(node) ("NODE" | number),
  stadium_boot_init_for(first), stadium_birth_node(key, name);
  stadium_boot_init() and stadium_birth_hera() are them for Hera's key, so
  v3's path is as it was (only an impossible panic's words changed).
- kernel_main.c: the system is chosen and said first, then the Stadium,
  sessions, switch-signal and kernel-Hermes tables for both systems in
  v3's order; v4: Hera, node 10, patron zero under her node key, the word,
  block and opcode layers. The quota self-test and the heartbeat's line
  are functions now, called by both systems.
- sk_v4.c/.h: sk_v4_run() goes -- sk_v4_boot() returns, the kernel's
  checks after POST (opcodes, words, conservation, quota, heartbeat), then
  sk_v4_prompt(). sk_v4_charge_opcodes() at the heartbeat's service points
  (the key wait, after each line) and once after POST.
- stadium_ops.c/.h: a node's 32 opcodes as Stadium patrons (HEAT-OP's
  feed, "Both"): retirements charged as the word layer's dispatches, a
  quantum each, the reservoir's floor kept, shared by retirements when
  short; cooling per tick as words. ~0.5 us a charge on the host: kept.
- qemu_session.py: a v4 acceptance boot fails without "Stadium: N cells",
  "Stadium conservation: CONSERVED" and the heartbeat's ticks (#189).

Tests first (logs/20261113-122142): the physics check failed on the v4
boot; test_stadium_node, test_stadium_ops (and its share case, after a
real boot showed ";" taking all the heat) failed before. Now: kernel host
tests all pass; amd64 v4 boot passes, POST 539/539, dict_hash unchanged,
"Stadium opcodes: 30 resident, hottest opcode 8", CONSERVED; a system=v3
boot prints its Stadium lines as on 2026-11-06.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 12:50:02 +00:00
Claude 3f4988e19e logs: the developer protocol on 892e3889 -- PASS, all eight stages
Build / Image RASPI (push) Successful in 8m31s
Acceptance / Acceptance (pull_request) Successful in 30m54s
Build / Image PC (push) Successful in 7m39s
Build / Image MILKV (push) Successful in 8m15s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 19m49s
A2 (#189): every word but the ten called. POST 539/539 on the four
boots; word_count 320 and dict_hash 0x47570d4ced6ce255 on all three
architectures; test-32 39 programs 0 failures; proofs; images; documents.
Boot times (stage, with its build) against be456d44's run: amd64 123 s ->
118 s, aarch64 208 -> 197, riscv64 96 -> 93 -- no slower under QEMU.
logs/20261113-053019/PROTOCOL.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 05:59:25 +00:00
Claude 892e3889f5 feat(v4): every word but the ten is called, so it can be checked
Plan 2026-10-20 (ENGINE step 4), Task A2, for #189. Captain Bob,
2026-11-13: "The ten"; "Accept it".

- compile.f18 (COMPILE,): a word is copied in line only when it is flagged
  in-line and compile-only (24) -- the ten that work on the return stack,
  >R R> R@ I J LEAVE and the later UNLOOP 2>R 2R> 2R@. Every other word,
  in-line ones too, is a call the hook at `call` sees.
- EXECUTE calls the xt: `call xt` (opcode 3, slot 0) and a ; in (EXEC),
  run. INTERPRET runs a word by (GO): `call xt` and `jump (IL)` in
  (RUNX), entered by a jump, at the old return-stack depth.
- host_map.h: (EXEC) BUF0_W-22, (RUNX) BUF0_W-115, from what was free.
- Its cost, accepted: one return entry at the bottom of a chain (30 deep
  from the prompt, not 31) and one per explicit EXECUTE while its word
  runs; the hosted boot +2.4% (2.917 s to 2.987 s), instructions +0.4%.
- Tests first (logs/20261113-045122/a2): inline_words_are_called,
  residue_stays_inline, execute_passes_the_hook, rstack_kept_across_call,
  abandoned_definition_not_called -- 3 of 1096 failed before. The depth
  checks moved to the new figures; SEE shows the calls; two layout checks
  use in-line test words; 2>R 2R@ 2R> checked in test_host_quit.
- DECOMPOSITION.md EXECUTE, the plan's A2 and rulings, FABRIC-3 XLVIII.22.

Suite: test, test-32 99 programs 0 failures; v4-checks 79 under the
sanitizers 0 failures, the hosted builds alike; hosted POST 539/539.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 05:30:10 +00:00
Claude bacb7b0616 logs: the developer protocol on be456d44 -- PASS, all eight stages
Build / Image PC (push) Successful in 8m18s
Build / Image MILKV (push) Successful in 8m20s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 20m22s
Acceptance / Acceptance (pull_request) Successful in 34m10s
Build / Image RASPI (push) Successful in 8m11s
#190 (POST regenerated, 539 cases) and #16 (v4-checks nightly). POST
539/539 on the four boots, at the new floor; word_count 320 and dict_hash
0xcac4cf58ed493172 on all three architectures; test-32 39 programs 0
failures; proofs; images; documents, the dictionary covering all 320
live words. logs/20261113-031936/PROTOCOL.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 03:48:51 +00:00
Claude be456d44e9 fix(v4): #190 POST regenerates the same; #16 sanitizers and hosted-check nightly
Captain Bob, 2026-11-13: "Create the issues then fix them before the long
acceptance test runs"; #16: "Nightly".

#190 -- make -C v4 post79 did not reproduce POST:
- mkpost.py runs v3 with address randomisation off (setarch -R): its
  printed addresses (>IN, FIND) are the same each run, so POST79.md is.
- v4/Makefile post79 builds hosted v3 from this tree's source first and
  uses it, not the lfs/ copy, which can be older.
- post_cases.c and POST79.md regenerated: 539 cases -- LOAD.rest_of_line,
  which v3 gets through since it changed after 2026-10-07. Two runs the
  same. POST_FLOOR 538 -> 539 (#173).
- test_host_unit.c takes the table's count, not 538 typed in the test.

#16 -- scripts/nightly.sh v4-checks: make -C v4 sanitize hosted-check,
logged under logs/<TS>/v4-checks/, refused without qemu-user; nightly.yml
runs it after publishing, before the proofs, installing qemu-user if the
image lacks it.

Evidence (logs/20261113-014927/post79, -024314): before, regenerated with
nothing changed: 539 cases and addresses differing run to run; after: the
same twice, hosted POST 539/539; test, test-32 99 programs 0 failures;
v4-checks 79 programs under the sanitizers 0 failures, the hosted builds
alike. The first verification failed at test_host_unit.c:442 (kept); a
stray v4-checks run stopped at once is kept, labelled (-014453).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 03:19:24 +00:00
Claude abfb30d0c4 logs: the developer protocol on dd6c393a -- PASS, all eight stages
Build / Image PC (push) Successful in 10m45s
Build / Image RASPI (push) Successful in 9m59s
Build / Image MILKV (push) Successful in 9m16s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 23m13s
Acceptance / Acceptance (pull_request) Successful in 35m0s
A1 (the hook at call), the merge of master (the six runner.capacity
comments) and HEAT-OP/ANTICLOCK (#189). POST 538/538 on the four boots;
word_count 320 and dict_hash 0xd148437fb39a1afd on all three
architectures (318 and 0x8c92508f748f99cf before: the two new words);
test-32 39 programs 0 failures; proofs; images; documents, the
dictionary covering all 320 live words. logs/20261113-005100/PROTOCOL.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 01:22:02 +00:00
Claude dd6c393a89 feat(v4): HEAT-OP[0..31] and ANTICLOCK, read by HEAT-OP@ and ANTICLOCK@
#189 -- Captain Bob, 2026-11-12: "Add HEAT-OP. If it's a huge performance
hit, we'll revert it. If not ... it stands"; a full 33-cell array, as
DECOMPOSITION.md section 7 draws it; the Stadium feed is Phase 1's.

- node.h/node.c: v4_node_heat_regs_attach; a data fetch from base+k gives
  opcode k's count, base+32 the anti-clock (the low cell at 32 bits); a
  store changes nothing. Reset detaches them.
- host_map.h: HEAT_REG at word 13824, in what was free between the
  dictionary space and SEND_TEXT; the compile-time check covers it.
  Nothing moved. map-*.f18: HEAT-OP 13824, ANTICLOCK 13856.
- image.h/image.c/mkmap.c: the image carries the address; v4_image_born
  attaches the node's own counts.
- system.f18: HEAT-OP@ ( op -- n ), op mod 32; ANTICLOCK@ ( -- n ).
  word_count 318 -> 320 (hosted 317 -> 319): dict_hash changes.
- v4-dictionary.tsv: both words; DECOMPOSITION.md 7 records the build.

Also in this batch:
- Makefile: make init installs qemu-user -- hosted-check needs it
  (Captain Bob: "Add to make init now").
- .claude/memory/rules.md, rule 5: stop and ask when something comes up
  (Captain Bob: "you are supposed to stop and ask").

Tests first (logs/20261113-005047/heat-op): test_node did not compile;
test_host_quit 3 of 1337 failed. Suite: 199 programs, 7448554 checks, 0
failures; hosted-check, the three alike. Timing: no measurable cost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 00:50:56 +00:00
Claude 9710bd1779 Merge master into StarForth-v4.0.0: the six runner.capacity comments
Captain Bob, 2026-11-13: "I merge master in". PR 164 could not merge:
master's six comment-only commits of 2026-11-11 (751bfe26..268e5593,
"record runner.capacity: 1 decision ... (FABRIC-3, #140)") edit the
concurrency blocks the branch deletes for #140 ("It should be global").

Resolved in every workflow for the branch -- no concurrency group --
with master's fact kept as a line of the #140 comment: the capacity is
explicit in the runner's config.yaml, runner.capacity: 1. Each file
parses; scripts/test_acceptance_signing.sh passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 00:14:21 +00:00
Claude 3c97534c8b feat(v4): a hook at call, for whoever runs the node
Plan 2026-10-20 (ENGINE step 4), Task A1, for #189 -- Captain Bob,
2026-11-12: the physics blocks alpha.5; order A, 1, 2, then 7.

- exec.h/exec.c: v4_call_hook, es->on_call/on_call_ctx; called at `call`
  once the return address is pushed, before P moves. NULL: as before.
- heat.h/heat.c: the per-call-target table (4096 slots, no capsule word
  counted), its freeze mask and v4_heat_call_* go (ENGINE.md step 3: "The
  per-call-target count goes"); the kernel will keep a word's accounts.
- tests: test_call_hook_sees_every_call, seen to fail first (no on_call);
  test_heat's per-call tests go with the table.
- the plan records today's rulings (order; HEAT-OP: both, a full array).

Suite (logs/20261112-225951/v4-tests): test, test-32, sanitize, 0
failures; hosted-check, the three alike. amd64 boot: POST 538/538,
dict_hash 0x8c92508f748f99cf, unchanged -- nothing sets the hook yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 23:01:52 +00:00
Claude f38761ff66 logs: the developer protocol on c76a742f -- PASS, all eight stages
Build / Image RASPI (push) Successful in 7m13s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 21m41s
Acceptance / Acceptance (pull_request) Successful in 34m9s
Build / Image PC (push) Successful in 5m54s
Build / Image MILKV (push) Successful in 8m2s
#188 (the Jacquard selector) and 7e0728e4 (a release refuses an unsigned
build). POST 538/538 on all four boots, dict_hash 0x8c92508f748f99cf on the
three, test-32 39 programs 0 failures, proofs, images, documents.
logs/20261112-210531/PROTOCOL.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 21:37:58 +00:00
Claude c76a742f2b #188: the Jacquard selector's 64 cards, L7 permanently on, L2 a real gate
Captain Bob, 2026-11-12: "Wire L2, keep L7 on". The table held the 128
cards of the 7-bit L1-L7 space; nothing read L7, and the rolling window
recorded whatever the card said, so the 128 were 32 behaviours.

- compudynamics.c: cd_tuning_word() sizes the table to 64 (L1-L6).
- ssm_jacquard.c: card_bits() makes a card's 7-bit mask, L7 set, where a
  card is read, seeded and started (C4: 17 -> card 8);
  ssm_l8_force_config() still takes the 7-bit index, its L7 bit implied.
- physics_execution_hooks.c, kernel vm_core.c: the rolling window records
  only while L2 is on (or before there is a config).
- ssm_jacquard.h says what is wired, bit by bit (it said L7 was);
  v3/CLAUDE.md and the L8 reference corrected in place; FABRIC-3 XLVIII.21.

Tests first, seen to fail against HEAD (logs/20261112-210510/kernel-tests):
test_ssm_jacquard 4 of 7, test_physics_l2 1 of 4; all pass now. v4 reads
no rolling window: acceptance is unchanged; the protocol runs next.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 21:05:24 +00:00
Claude 7e0728e46b ci: a release refuses an unsigned build
Captain Bob, 2026-11-12: "release MUST refuse unsigned builds". release.yml's
"The capsule-signing key" step warned when CAPSULE_SIGN_KEY was missing and the
release went on, unsigned. Now it is an ::error:: and the step fails, as the
gate into master's does (#174). build.yml and nightly.yml still warn.

scripts/test_acceptance_signing.sh now takes the step from both acceptance.yml
and release.yml as CI runs them. Against release.yml as it was: the release's
unsigned case passed, no error -- 2 failures (acceptance's 3 checks passed).
Now 6 checks, all pass. logs/20261112-205446/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 20:54:46 +00:00
Claude 9077618c49 logs: the developer protocol on e0dcaa16 -- PASS, all eight stages
Build / Image RASPI (push) Successful in 9m57s
Build / Image PC (push) Successful in 11m0s
Build / Image MILKV (push) Successful in 5m18s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 11m33s
Acceptance / Acceptance (pull_request) Successful in 27m34s
logs/20261112-185800/PROTOCOL.md, for #142, #173, #174 and the notes: the four
boots 538/538, word_count=318, dict_hash 0x8c92508f748f99cf on all three; the
new post-count stage (#173) on the real boots: all four at or above the floor,
all passed; test-32 39 programs, 1,869,223 checks, 0 failures; the proofs
(40 s); the images; the documents. The tree clean before and after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 19:29:28 +00:00
Claude e0dcaa163b notes: the release order, the documents last; the floor, the signing, the host tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:57:50 +00:00
Claude b0038376a7 ci: the gate into master refuses an unsigned build (#174)
Captain Bob, 2026-11-12: "Yes, reject unsigned builds". acceptance.yml's
"The capsule-signing key" step warned when CAPSULE_SIGN_KEY was missing and
the PR's acceptance went on, unsigned. Now it is an ::error:: and the step
fails, so the gate does too. A local or protocol build may still be unsigned
(kernel/Makefile, v4/Makefile): the refusal is the gate's. build.yml,
nightly.yml and release.yml still warn -- release.yml is Captain Bob's to rule.

scripts/test_acceptance_signing.sh takes the step from acceptance.yml as CI
runs it and runs it with and without a key. Against the workflow as it was:
the unsigned case passed, no error -- 2 failures. Now: no key fails with an
::error::, a key is handed to the build as SIGN_KEY. logs/20261112-185739/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:57:39 +00:00
Claude 947d044872 logs: #173's tests against nightly.sh before the stage, run for real
4738aee4's log has a placeholder where the run against the code before #173
belongs ("see the session") -- not evidence. Rerun against
scripts/nightly.sh as it was (4738aee4~1): every one of the 7 cases fails,
the stage not existing. post-count-before-rerun.log; the first log is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:56:32 +00:00
Claude 4738aee4c0 ci: acceptance asserts POST's test count against a floor in the tree (#173)
Captain Bob, 2026-11-12: "Yes". Acceptance checked POST: PASSED, so a POST
that lost cases still passed. Now scripts/nightly.sh post-count, which the
stick-high stage runs after dict-hash: each of the four boots must report
PARITY:V4_POST with every test passed and at least the floor's tests --
v4/system/POST_FLOOR, 538 today, raised when POST grows and never lowered
without Captain Bob. A boot with no POST line, not run, or no floor file is
refused, not skipped.

scripts/test_nightly_post_count.sh, written first and seen to fail (the stage
not existing), then 7 cases: 538 and 600 pass; fewer than the floor, a
failure, no POST line, a boot not run, no floor -- refused. Run on the boots
of the last protocol (d7b2f6bf): all four 538 of 538. logs/20261112-185620/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:56:20 +00:00
Claude e453fde3d4 fix(v3): the DoE row's cache and bucket hits are measured, not written as 0 (#142)
Captain Bob, 2026-11-12: "correct deficiencies". heartbeat_capture_tick_snapshot
wrote cache_hits_delta and bucket_hits_delta as 0 ("TODO: wire ..."), though
physics_hotwords_cache.c counts both. Now each is read from the VM's hot-words
cache as a delta since the previous tick, the way word_executions_delta is
(and after the cache's stats are reset, the count since then); a VM with no
cache has 0. word_executions_delta was measured already: doe_log.c's "TODO: 0"
for it was stale, and its three column notes are corrected.

kernel/tests/test_heartbeat_export.c, 4 checks: a VM in memory with a cache
whose counters the test sets, captured tick by tick. Against the code as it
was: 3 failures (the hits 0 where the cache counted 5 and 3, then 7 and 7).
Now: 0. Built for amd64, aarch64, riscv64 and the hosted v3. Shared v3 code,
under the ruling. v3 is not part of acceptance; no DoE has run since 2026-09-16.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:55:30 +00:00
Claude 83898b524d logs: the developer protocol on d7b2f6bf -- PASS, all eight stages
logs/20261112-182015/PROTOCOL.md, for the kernel host-test chunk: the harness
and #170, #171, #176, #177, #178, #182. The four boots 538/538 -- a data stick
enumerating through the moved USB descriptor walk, genesis through the identity
code's new seed handling -- word_count=318, dict_hash 0x8c92508f748f99cf on all
three; test-32 39 programs, 1,869,223 checks, 0 failures; the proofs (37 s);
the images, no race; the documents. The tree clean before and after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:48:21 +00:00
Claude d7b2f6bf54 fix(v4): the identity code wipes Zuse's seed after every drive it handles (#176, the identity code)
sk_v4_genesis never wiped its seed or its read-back; sk_v4_drive_arrived
never wiped the proxy's seed after her login; sk_v4_real_zuse_arrived wiped
the seed only on a match. (The logged-in Zuse's own key stays in g_zuse_seed,
by design.)

Option 1: the three use one buffer the identity module owns, g_seeds (seed,
then its read-back), and sk_v4_drive_arrived -- which every drive goes through,
and which alone calls the other two -- runs the drive's handling (now
handle_drive()) and then wipes it, whichever way it went.
sk_v4_identity_seeds() lets the host tests read it.

kernel/tests/test_sk_v4_identity.c, 10 checks, through the real drive-arrival
path: a fake xHCI controller marks a slot attach-pending, the identity code's
idle beat handles it, the real gpt.c reads the stick's table from the RAM disk;
the block layer, signatures, key mint, marker and console faked. Genesis; a
genesis not read back; the proxy logging in; a real Zuse named, then her stick
logging in. Against the code before the wipe: 5 failures (every case's seeds
left). Now: 0. The harness gains fake_disk_bind. Built for amd64, aarch64,
riscv64. #176 done with 2bac2ac8 (the mint).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:20:09 +00:00
Claude 2bac2ac8fc fix(v4): MINT-ZUSE wipes Zuse's seed on every return, not only on success (#176, the mint)
sk_v4_mint_zuse wiped seed and rseed only when the real Zuse was minted; its
refusals and every failure after YES left them in stack memory.

Option 1 (Captain Bob, 2026-11-12: "1 is great"): the seeds are in a 64-byte
buffer the caller owns. sk_v4_mint_zuse_with(seeds) runs the mint (now a
private mint()) and then wipes the buffer, whichever way it returned -- one
place, every exit; sk_v4_mint_zuse() gives it a buffer of its own.

kernel/tests/test_sk_v4_mint.c, 17 checks: the real gpt.c on the RAM disk, the
identity code, key mint, signature checks, marker and keyboard faked; each of
the mint's eight exits run with the buffer filled with 0xEE first -- no stick,
under 64 MiB, not YES, the key mint failing, the read-back not hers, no
marker, the marker write failing, and minted. Against the mint as it was: 7
failures (every exit but success). Now: 0. Both runs in logs/20261112-181719/. Built for
amd64, aarch64, riscv64. The identity code's two (sk_v4_genesis,
sk_v4_real_zuse_arrived) follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:17:19 +00:00
Claude 3c053f02a6 fix(v4): the build refuses an Artemis cap its 32-bit block numbers cannot hold (#182)
sk_v4_grow.c's dev_rw4k computes 1 KiB block numbers as (uint32_t)devblock * 4,
which wraps past 4 TiB; Artemis is capped at 256 GiB (STICK_ARTEMIS_CAP_GIB,
kernel/Makefile), so it is latent -- but nothing said so where the cast is. Now
a compile-time check there (the C99 negative-array pattern the tree uses): a
cap past 4 TiB stops the build, and a cap not defined at all is an #error, not
a skipped check. gpt.c's casts are bounded by the disk's own size, itself a
32-bit count of 1 KiB blocks, checked before each: each now says so.

kernel/tests' check_cap, seen to fail first (a 4096 GiB cap built); now 3
checks, 0 failures -- 256 GiB builds, 4096 GiB and none refused. Built for
amd64, aarch64, riscv64. The plan's increments 2 and 3 marked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:07:23 +00:00
Claude 41f8648dd9 fix(v4): a controller's drive slots are allocated once, never replaced (#178)
sk_v4_idle allocated a controller's slot array again whenever max_slots + 1
was more than it held -- the old array dropped, neither copied nor freed --
while the identity code holds pointers into it (g_offered, g_spare,
g_pending_real, g_real_drive, g_zuse_dev). Its two slot loops then ran to
max_slots whatever the array held.

sk_v4_slots_get() (kernel/src/v4/sk_v4_slots.c): allocated once, zeroed, at the
size first asked for; never replaced; the slots that may be used are those it
has. sk_v4_idle uses it, and its loops stop at the array's end.

kernel/tests/test_sk_v4_slots.c, kmalloc_aligned faked, seen to fail first
against the allocation as it was (4 failures: replaced when more were asked
for, 17 said usable where 9 existed, a held pointer left behind, an allocation
for 0); now 6 checks, 0 failures. Built for amd64, aarch64, riscv64; latent
today (max_slots does not grow), so the boots show no change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:05:57 +00:00
Claude c778f6e0e7 fix(v4): the kernel's fatal stops halt, interrupts off, instead of spinning (#177)
sk_v4_run's three stops -- "not started", "did not let go of POST's
blocks", "stopped on a fault" -- ended in for (;;) { }: a core spinning at
100%, the thing #151 removed from the prompt. Each now calls sk_v4_stop()
(kernel/src/v4/sk_v4_stop.c): interrupts off, then arch_halt() for ever. Each
still says why first. sk_v4_stop.c added to the loader's and the kernel's v4
sources.

kernel/tests/test_sk_v4_stop.c, with arch_halt and arch_disable_interrupts
faked (the halt jumps back out after three calls; an alarm fails a spin):
against the stop as it was -- "spun for 2 s without halting"; now -- 2
checks, 0 failures: halts in a loop, interrupts off before the first halt.
Built for amd64, aarch64 and riscv64. #177's "seen on the three
architectures": no boot reaches these stops, so it is shown on the host only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:04:31 +00:00
Claude 8649463a58 logs: #170/#171's test against the old decision, run again correctly
a8824655's evidence log shows its "before" run failing to compile: the copy
of usb_config.c with the old decision was cut at the wrong brace by my script.
The failure the commit describes was real (seen in the session), but the log
did not show it. Rerun with a correct copy:
test_usb_config-before-rerun.log -- 20 checks, 10 failures (wTotalLength 1 to
9 asked for again; the cut unsaid). The first log is kept, as what it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:02:03 +00:00
Claude a882465573 fix(usb): a configuration of 9 bytes or less is refused, and a cut one is said (#170, #171)
After the configuration descriptor's first 9 bytes the event loop asked for
min(wTotalLength, 128) whatever it was. A wTotalLength of 9 or less was then
asked for again as "short" -- for ever, that slot never leaving enumeration
(#170); 0 also issued a zero-length data stage. A set longer than the 128-byte
buffer was cut without a word, its later interfaces never seen (#171).

The decision is usb_config_request_length() (moved out of the event loop,
then fixed): 9 or less is 0 -- "xhci: a configuration of N bytes has no
interface -- not used", and nothing more is asked; longer than the buffer is
cut and said -- "xhci: config of N bytes cut to 128 -- rest unseen" (at most
53 characters). The buffer stays 128 bytes; its size is #171's to rule.

kernel/tests/test_usb_config.c, seen to fail first against the decision as it
was (10 failures: wTotalLength 1 to 9 asked for again, the cut unsaid), now
20 checks, 0 failures. Both runs in logs/20261112-180140/kernel-tests/. Built for amd64,
aarch64 and riscv64; the boots come with the protocol. #171's other box, a
composite device on the SER5, is Captain Bob's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:01:40 +00:00
Claude 8b482bedb8 refactor(usb): the configuration-descriptor walk moved out of the event loop, unchanged
xhci.c's XHCI_XFER_CONFIG_DESC_FULL case walked the descriptor set inline, in
the event loop, where nothing could test it. The walk is now
usb_config_parse() (kernel/src/usb/usb_config.c), returning what it found;
the case acts on it as before -- the same messages, the same decisions: the
first Interface descriptor only, a BOT interface's bulk endpoints (the last of
each direction), a boot keyboard's first interrupt IN endpoint, bLength 0
ending the walk, nothing read past len. One difference, in debug output only:
the bulk endpoints are logged IN then OUT, not in descriptor order.

kernel/tests/test_usb_config.c, 7 checks, pins the walk as moved: a BOT stick
as QEMU presents it, a boot keyboard with its HID descriptor, a mouse before a
drive (the first interface only), a drive with bulk IN only, bLength 0, an
endpoint cut by len, an interface cut before its protocol byte. All pass.
Built for amd64, aarch64, riscv64; the boots come with the protocol (a data
stick enumerates through this path). The fixes for #170 and #171 follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 17:59:52 +00:00
Claude 37b1527279 test: kernel host tests -- the harness, and gpt.c tested on the host
Captain Bob, 2026-11-12: "Build an appropriate test harness! Love the idea."
The kernel had no tests below the boots, so defects QEMU cannot provoke could
not be tested first. Plan: docs/v4.0.0/plans/2026-11-12-kernel-host-tests.md.

kernel/tests/: one host program per kernel source, built with that source as
it is, the kernel's flags (-std=c99 -Wall -Wextra -Werror), and fakes --
the console captured line by line, a deterministic RNG that can fail, and a RAM
disk whose reads, writes or flushes fail at chosen 1 KiB blocks.
make -C kernel/tests test runs them; SRC_<test>= runs a test against other
code, which is how a test is seen to fail against the code before a fix.

test_gpt.c, 12 checks: a table written and read back; 16, 17 and 18 used
entries against max 16 and an entry out of range after the 16th (#180); the
RNG, the first write, a later write and a flush failing (#168). Against gpt.c
before #168 and #180: 4 failures, each defect caught. Now: 0. Both runs in
logs/.../kernel-tests/. Not yet a protocol stage: to rule (the plan, step 5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 17:57:04 +00:00
Claude 8a0dab7f48 logs: the developer protocol on 9700a7b4 -- PASS, all eight stages
Build / Image RASPI (push) Successful in 8m32s
Build / Image PC (push) Successful in 7m45s
Build / Image MILKV (push) Successful in 8m4s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 20m11s
Acceptance / Acceptance (pull_request) Successful in 39m52s
logs/20261112-164108/PROTOCOL.md, for the batch #172, #169, #185, #144, #143,
#181, #180 and the #187 test: the four boots 538/538, word_count=318,
dict_hash 0x8c92508f748f99cf on all three -- the new dict-hash stage (#172)
naming each; test-32 39 programs, 1,869,223 checks, 0 failures (the manage
test's 78 among them, #169); the proofs (43 s); the images, no race (#185);
the documents. The tree clean before and after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 17:11:21 +00:00
Claude 9700a7b404 fix: gpt_read checks every entry, and says when there are more than max (#180)
gpt_read() stopped at max used entries (16 for the identity code, 4 in the
mint): a disk whose StarshipOS partitions came after the first max read as
having none, and the entries after max were never range-checked.

Now every entry is checked and every used one counted; a good table with more
used entries than max is GPT_MANY (the first max in parts), and the identity
code says "GPT: a USB drive has more than 16 partitions -- not used". Other
callers treat anything but GPT_OK as before.

Tested first, seen to fail: qemu_session.py gpt_many -- a data stick with its
two partitions as entries 17 and 18 after 16 others, and the same with an entry
19 past the usable range: both "not this system's stick" before (silently cut,
entry 19 never checked; logs/20261112-162236). After: "more than 16
partitions" and "a damaged partition table" (logs/20261112-162921).
Regressions: gpt_bad_entries, gpt_foreign PASS. gpt_zuse FAILS, on a stale
expectation unrelated to this change -- an identity-only GPT drive with no
system stick has been held silently as a possible real Zuse since #92 Task 4;
its log is kept here. The gpt_many images are made before the boot: a first
version made them after, failed in sgdisk and left its QEMU running, stopped
by hand (logs/20261112-162003).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 16:41:00 +00:00
Claude ab63789e5b test: qemu_session.py ident_attach_fail -- the identity partition unreadable (#179, #187)
A data stick hot-plugged with every read at its identity partition's first
sector (LBA 2048) failing, after a boot with no drive; it expects a message
naming the identity partition, Artemis let go (both partitions or neither,
#179), no prompt, and the same stick without the fault going on to genesis.
add_stick() takes fail_read_sector for it.

It FAILS today, and is kept so (Captain Bob, 2026-11-12: "keep the test"):
the partition attaches anyway and Zuse is minted onto it, because
blk_format_or_load_disk() ignores the header read's result and takes an
unreadable disk as blank -- filed as #187. #179 is parked: its half-attached
state cannot be reached from a disk fault. The run: logs/20261112-160050.

Not part of acceptance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 16:15:03 +00:00
Claude 90ea372859 docs(v4): heat.c's and the stacks' comments say what the code does (#181)
- heat.c call_index(): the comment read as an unfinished thought ("hash-mod or
  just take low bits?", "ignore for now? Or clamp?"). It now states the rule
  the code follows: indexed by the target, a target past the table not counted,
  -1 telling the callers so; the table D-6's stand-in, which ENGINE step 4
  Part A1 plans to remove.
- stack.h points 1 and 2 said there was no overflow detection "and there never
  will be" and that a depth exceeded corrupted silently -- D-2, which D-16
  revised. Now: guarded before every opcode, a mesh node 10 and 9, the host node
  32 and 32 (D-17); C code that serves a node checks the depth itself.
- stack.c named an 8-ring and depths 10 and 9 only, and said D-2's rule still
  held.
- DATASHEET-F18.md section 13 item 4 (this gap) struck, resolved in place.

Comments only: test_stack and test_heat unchanged at both widths (730,137 and
8,272 checks, 0 failures).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 15:30:17 +00:00
Claude 216947a4d4 tools: mkcapsule builds warning-free -- the truncations impossible or handled (#143)
The kernel build's only warnings were five -Wformat-truncation in mkcapsule's
--resolve: two snprintf copies of a capsule name into the claim registry, and
the capsule's path built from base_dir and its name.

- The names: both are char[CAPSULE_NAME_MAX], and names are checked to fit when
  read (line 335) -- copied whole with memcpy, nothing to truncate.
- The path: base_dir may be up to 4095 bytes, so it can be cut, and a cut path
  names another file -- now refused, the capsule left unchanged and counted
  rejected, with the reason.

Seen to fail first: built with -Werror=format-truncation, 5 errors. After: 0,
and 0 warnings with the kernel's flags; the manifest it writes is
byte-identical, --lint passes. The too-long-path refusal is on --resolve's
interactive conflict path and was not driven by a test. CLAUDE.md's count of
open warnings corrected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 15:29:13 +00:00
Claude c0b714645f docs: kernel_main.c's header states what is there; CLAUDE.md's warning about it goes (#144)
The header said "M6: Infrastructure present (validation deferred)" and "M7:
Not started (VM integration pending)", and "(LithosAnanke branch)" -- there
is no such branch since the split. .claude/CLAUDE.md had warned since
2026-08 not to propagate it instead of it being corrected. Now: M0-M6 and M7
complete, M7.1 in progress (as CLAUDE.md's Architecture section gives them),
v4 the system booted by default; the correction dated in place. The note in
CLAUDE.md's Gotchas goes, as #144 asks. Comments only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 15:28:00 +00:00
Claude d783fd11c3 build: the two map files are one grouped target, so their sub-make runs once (#185)
kernel/Makefile gave capsules/v4/sys/map-64.f18 and map-32.f18 one rule with
two plain targets -- in GNU make, two rules sharing a recipe. Under -j both
ran at once: two make -C v4 sysmap built and ran the same v4/build/mkmap-<w>
side by side (Build run 255's RASPI job: "mkmap-32: Permission denied").
Now one grouped target (&:, GNU make 4.3+, as here and in the CI image).

Seen to fail first: the two targets with -j8, mkmap removed each time, 12
runs -- 6 failed ("Text file busy", "Permission denied"). After: 0 of 12.
Both sets of runs in logs/20261112-152711/race-185/. The map files are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 15:27:11 +00:00
Claude c642af541b fix(v4): a manage request with too few values, or no room, is refused (#169)
v4_manage_serve took its arguments with v4_dstack_pop and never checked the
stack's depth: a request with too few values acted on stale ring values, and
one whose results did not fit dropped the oldest silently -- around the D-16
guards. Now each request's arity (manage.h) is checked first: fewer values
than it takes, or no room for what it leaves, is error 12 with the stack as it
was -- as a block request is refused (blocks.c).

test_manage.c, written first and seen to fail (12 of 13 requests at both cell
widths; NODE-BORN passed only because the stale value read was below 1): every
request with one value fewer than it takes, and NODE-ME and CAPSULE-CELL on a
stack with no room -- refused, the stack unchanged. After: 78 checks, 0
failures at 32 and 64 bits; all v4 tests at 64 bits, 40 programs, 1,871,313
checks, 0 failures (logs/20261112-152602/v4-test).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 15:26:02 +00:00
Claude c28cc0191b ci: the dict_hash check counts three hashes, not one distinct value (#172)
The stick-high stage passed when one distinct dict_hash appeared: an
architecture whose boot left no accept file, no LOG: line, no serial log or no
PARITY:V4_SYSTEM line gave nothing, and two that agreed passed for three.

It is now a stage of its own, scripts/nightly.sh dict-hash, which stick-high
runs: one hash from each of amd64, aarch64 and riscv64, all found and one value;
otherwise refused, naming the architectures with none or the values that
differ. NIGHTLY_OUT points the stages at another directory, for the tests.

scripts/test_nightly_dict_hash.sh, written first and seen to fail (6 of 6, the
stage not existing), then 7 cases: agree -- pass; differ, no PARITY line, no
LOG: line, not booted, no serial log, none at all -- refused. Two of them
caught lookups that ended the script silently under set -e; guarded.

Captain Bob, 2026-11-12: "172 then finish alpha.5".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 15:17:08 +00:00
Claude ff797d80cb logs: the developer protocol on 54311be1 (#168) -- PASS, all eight stages
Build / Image PC (push) Successful in 7m53s
Build / Image MILKV (push) Successful in 6m36s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 20m23s
Build / Image RASPI (push) Successful in 9m44s
Acceptance / Acceptance (pull_request) Successful in 42m23s
logs/20261112-124144/PROTOCOL.md: the four boots 538/538, word_count=318,
dict_hash 0x8c92508f748f99cf on all three; test-32 39 programs, 1,869,197
checks, 0 failures; the proofs (StarForth, 37 s); the images; the documents.
The tree clean before and after.

Stage 3 (riscv64) was stopped while booting, when Captain Bob interrupted to
mean the build pipeline; its partial serial log and console output are kept,
labelled, in logs/20261112-124831/. It was rerun on the same commit and
passed (logs/20261112-130801).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 13:30:49 +00:00
Claude 54311be18a fix: MINT-ZUSE says the stick was erased when it was (#168)
failed() printed "MINT-ZUSE: failed -- nothing changed" on every failure
after YES, though by then gpt_write_one() had rewritten the stick's partition
table and the identity partition's first blocks had been zeroed.

gpt_write_one() now tells the two apart: GPT_EIO when its first write failed
(nothing written), GPT_PART when a later write or flush failed (the disk is
changed). MINT-ZUSE keeps "failed -- nothing changed" for GPT_EIO only, and
says "failed -- the stick was erased; Zuse not minted" for every failure
after the table is written. The marker is still written last.

Tested first, seen to fail: qemu_session.py mint_part_fail (writes fail only
at the identity partition's first sector, LBA 2048) -- "nothing changed",
logs/20261112-122132. After: mint_part_fail PASS; mint_fail (every write
fails) still "nothing changed", PASS; replace (the success path) PASS. Their
logs here. FABRIC-3 XLVIII.20.

Captain Bob, 2026-11-12: "start #168".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 12:41:36 +00:00
Claude 7e30b4525e logs: the developer protocol on defd47e5 -- PASS, all eight stages
Build / Image PC (push) Successful in 9m16s
Build / Image MILKV (push) Successful in 6m54s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 19m51s
Build / Image RASPI (push) Successful in 6m42s
Acceptance / Acceptance (pull_request) Successful in 27m4s
logs/20261112-114545/PROTOCOL.md: one stage per foreground command (paused
between stages 2 and 3 for Captain Bob's emergency, then resumed on the same
commit): the four boots 538/538, word_count=318, dict_hash
0x8c92508f748f99cf on all three; test-32 39 programs, 1,869,197 checks, 0
failures; the proofs (StarForth, 44 s); the images; the documents. The tree
clean before and after.

The evidence for the held batch: plan section 8 (the FMEA in the PR review),
the notes, and scripts/ci_litter_check.sh (#129).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 12:18:29 +00:00
Claude defd47e5ff scripts: ci_litter_check.sh -- #129's week-later check, run on the server
Each cleanup #129 set up (Captain Bob, 2026-11-07), and what proves it ran:
the Docker prune's and the package cleanup's logs written in the last 8 days;
no image older than 8 days that no container uses; at most KEEP (5)
lithosananke-runner tags; no artifact older than ARTIFACT_DAYS (30) + 1; no
Nexus snapshot asset older than 8 days (with NEXUS_USER/NEXUS_PASSWORD,
skipped and said so without); a dated disk line appended to HISTORY each run,
so "disk use flat" is a comparison of weeks. PASS:/FAIL:/SKIP:/INFO:,
RESULT:, exit 0 only if nothing fails.

Tested here against fixtures (a stale log, an old artifact, no docker -- each
FAIL; clean -- PASS) and a stand-in docker (one stale unused image of three --
FAIL, the in-use and the recent ones kept). The registry check ran against
the real registry: 2 tags. Not run here: the real Docker, Nexus.

Captain Bob, 2026-11-12: "Correct the issue text and write the check script".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 11:25:28 +00:00
Claude ffaf9d8e45 notes: the developer protocol, and its strictness ruled
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 00:47:24 +00:00
Claude 4d4706c389 plan: the FMEA in the PR review -- section 8, for ruling (CAPA & FMEA gate)
Captain Bob, 2026-11-12: "Is it possible to include the FMEA in the pr
review? That way the items are forced into a manual review beforehand?" --
"Yes, add it to the plan". Each FMEA row names its paths; the PR carries a
review record with a decision for every row its diff touches; a
check_fmea_review.sh beside check_protocol.sh refuses the PR without one, or
with one for another diff. A sixth point to rule. Nothing built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 00:45:35 +00:00
Claude 1f94a048f4 logs: the developer protocol on dd580e07 -- PASS, all eight stages (#135)
Build / Image RASPI (push) Failing after 6m48s
Build / Image PC (push) Successful in 7m29s
Build / Image MILKV (push) Successful in 12m55s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 19m26s
Acceptance / Acceptance (pull_request) Successful in 24m5s
logs/20261112-001304/PROTOCOL.md: scripts/nightly.sh protocol, one stage per
foreground command: accept amd64, aarch64, riscv64, stick-high -- 538/538,
word_count=318, dict_hash 0x8c92508f748f99cf on all three; test-32 39 programs,
1,869,197 checks, 0 failures; the proofs (StarForth, 36 s); the images (PC,
RASPI, MILKV); the documents (book, fabric, dictionary, vol1-3, api). The tree
clean before and after. Every stage's output in logs/20261112-001304/protocol/,
the boots' serial logs and DoE CSVs beside it.

The first protocol run: the evidence the PR's Acceptance check now asks for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 00:44:58 +00:00
Claude dd580e0717 ci: the developer protocol -- nightly.sh protocol, PROTOCOL.md, and the gate checks it (#135)
Build / Image RASPI (push) Successful in 5m13s
Build / Image MILKV (push) Successful in 14m9s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 18m36s
Acceptance / Acceptance (pull_request) Failing after 10m33s
Build / Image PC (push) Successful in 7m34s
scripts/nightly.sh protocol: every stage a PR, the nightly and a release run --
accept amd64, aarch64, riscv64, stick-high, test-32, proofs, images, docs --
in order, never publish; the first failure ends it. protocol <stage>... runs
those only, so each can be its own foreground command (the QEMU rule);
accept-amd64 begins a protocol, recording the commit and whether the tree is
clean. protocol-report writes logs/<TS>/PROTOCOL.md (the commit, the tree,
each stage's result and output, POST and dict_hash per architecture compared,
test-32's totals, the proofs' log, the images' and documents' SHA-256) and
keeps every stage's output in logs/<TS>/protocol/ -- nothing is left only in
build/nightly. PASS only if every stage passed on the commit it began on and
the tree is unchanged but for the evidence.

acceptance.yml: scripts/check_protocol.sh on the PR's head, first, before the
boots. The PR template asks for PROTOCOL.md; .claude/CLAUDE.md names the
protocol as the acceptance a developer runs.

Captain Bob, 2026-11-07 (#135); 2026-11-12: "Keep working on alpha.5".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 00:12:55 +00:00
Claude 7a43cc3514 ci: check_protocol.sh -- a commit carries passing protocol evidence for its tree (#135)
scripts/check_protocol.sh [<rev>]: refused (exit 1) unless <rev> carries a
logs/<TS>/PROTOCOL.md naming a commit whose protocol passed on a clean tree,
and that commit differs from <rev> only in the evidence (logs/ and
experiments/bare_metal/runs/, committed after the run). Any other change since
makes the evidence stale: the protocol is run again.

scripts/test_check_protocol.sh, written first and seen to fail (8 of 8, and
tightened so a missing script is not taken for a refusal): no protocol, stale,
failed, dirty, unknown commit -- refused; fresh, fresh among stale ones, other
files in logs/ -- passes. 8 of 8 pass.

Not yet wired into acceptance.yml: that comes with nightly.sh protocol.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 00:07:04 +00:00
rajames 268e55937e ci: record runner.capacity: 1 decision in nightly-docs.yml (FABRIC-3, #140) 2026-11-11 21:35:32 +00:00
rajames b0e33c9a93 ci: record runner.capacity: 1 decision in release.yml (FABRIC-3, #140) 2026-11-11 21:35:25 +00:00
rajames 265d65b5f8 ci: record runner.capacity: 1 decision in acceptance.yml (FABRIC-3, #140) 2026-11-11 21:35:21 +00:00
rajames 314cbc57bc ci: record runner.capacity: 1 decision in runner-image.yml (FABRIC-3, #140) 2026-11-11 21:35:15 +00:00
rajames 96a1ad7d80 ci: record runner.capacity: 1 decision in nightly.yml (FABRIC-3, #140) 2026-11-11 21:35:09 +00:00
Claude 75c717ce23 notes: the review findings filed as #168-#183
Build / Image PC (push) Successful in 12m32s
Build / Image MILKV (push) Successful in 14m14s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 21m7s
Build / Image RASPI (push) Successful in 13m22s
Acceptance / Acceptance (pull_request) Successful in 31m26s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 21:34:45 +00:00
rajames 751bfe2675 ci: record runner.capacity: 1 decision in build.yml (FABRIC-3, #140) 2026-11-11 21:34:30 +00:00
Claude 4d42d25c4a plan: a CAPA & FMEA gate in the build pipelines -- for ruling, nothing built
Build / Image RASPI (push) Successful in 14m23s
Build / Image PC (push) Successful in 14m7s
Build / Image MILKV (push) Successful in 11m36s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 20m42s
Acceptance / Acceptance (pull_request) Failing after 50m22s
Captain Bob, 2026-11-11: "I'm thinking about adding a CAPA & FMEA GATE to our
build pipelines", then yes to writing it up. A nightly.sh quality stage run in
the acceptance gate: every kind/escaped issue has a CAPA record whose
preventive control exists and runs in a stage; every FMEA row over the
threshold has a control in the gate. Seeded with five CAPAs from 2026-11-11.
Five points to rule (section 7).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 21:17:30 +00:00
Claude 88d5f777bb ci: one queue for all of CI, nothing cancelled (#140)
Every workflow shared the concurrency group qemu. A group keeps one running
and one waiting run, and a run that joins cancels the one waiting: Build
runs 245 and 247 were cancelled at 0 s by PR 164's Acceptance runs.

Captain Bob, 2026-11-11: "It should be global"; the runner has capacity 1.
So the concurrency block is removed from all six workflows (a comment in
each says why): with one runner at capacity 1 every job waits its turn in
Gitea's queue and none is cancelled, and a runner-image rebuild still
blocks the rest. CLAUDE.md's CI section corrected; FABRIC-3 XLVIII.19.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 21:12:06 +00:00
Claude 3c1ccabc8e logs: the v4 tests on feb740c5, and the stage outputs of 9415d7ed's acceptance
logs/20261111-193825/v4-test: make -C v4 test on feb740c5 -- 79 programs,
3,740,484 checks, 0 failures, at V4_CELL_BITS=32 and 64. CI's v4-tests job
(Build run 247) was cancelled at 0 s by the shared qemu concurrency group
(#140), so this is the run of record for that job.

logs/20261111-185352/nightly: what scripts/nightly.sh wrote only under
build/nightly for 9415d7ed's acceptance (d6846b34) -- the four accept
summaries, test-32 (39 programs, 0 failures) and the images stage (PC,
RASPI, MILKV). The test-32 output of the earlier 90c5c140 run was
overwritten in build/nightly before it was kept, and is not recoverable.

Captain Bob, 2026-11-11: all logs are evidence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 21:05:58 +00:00
Claude feb740c5ca docs: FABRIC-3 XLVIII.18 -- a clean tree for alpha.5; README: alpha.4 is a release
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 35m29s
XLVIII.18 records 2026-11-11: the LFS trim (Captain Bob: "they can be
trimmed out"), version.h untracked and BLOCK_MAP.md without its timestamp
(#145), my put-back error and its fix, the acceptance rulings (never in the
background; all logs and CSVs are evidence), the acceptance of 9415d7ed,
and alpha.4's Gitea release marked final.

README: alpha.4's release is no longer a pre-release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 19:09:46 +00:00
Claude d6846b3487 logs: acceptance of 9415d7ed -- all five stages pass, and the images stage
Run one stage at a time in the foreground through scripts/nightly.sh:
  20261111-185352  amd64       PASS
  20261111-185600  aarch64     PASS
  20261111-185950  riscv64     PASS
  20261111-190128  stick-high  PASS
PARITY:V4_POST tests=538 pass=538 fail=0, POST: PASSED, [zuse@Hera] ok>
on every boot; word_count=318 dict_hash=0x8c92508f748f99cf on all three;
test-32 39 programs, 0 failures.

scripts/nightly.sh images -- the stage the version.h put-back had broken --
built PC, RASPI and MILKV and left the tree as committed.
DoE CSVs for every boot (empty, as every v4 acceptance boot's: #141).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 19:08:57 +00:00
Claude 9415d7ede3 fix: put-backs no longer name the untracked version.h (#145)
90c5c140 untracked v3/include/version.h, but six places still put it back
with git checkout. Git refuses the whole checkout when one path is unknown:

- scripts/nightly.sh images (set -e): the stage ended there, so the nightly
  (images, publish, proofs) and release.yml (images, docs, gitea-release)
  would fail. Acceptance does not run images, so it passed.
- scripts/check_images.sh (no -e), demo/build-iso.sh, demo/mint-zuse.sh
  (|| true): silently put nothing back, BLOCK_MAP.md and the SBOM included.
- scripts/qemu_session.py: an error after every boot, otherwise harmless.
- boards/BRINGUP.md: the step said to put it back.

BLOCK_MAP.md stays in every put-back: a signed build (CI's) still rewrites
its Signed column. Found while setting up alpha.5; Captain Bob: fix it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 18:52:46 +00:00
Claude 89dbed7c4e notes: acceptance tests never in the background -- first rule in rules.md
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 36m12s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 17:22:29 +00:00
Claude a7be895c7f notes: acceptance in the foreground, all logs and CSVs are evidence
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 17:21:48 +00:00
Claude 1b1fe66dba logs: acceptance of 90c5c140 -- all five stages pass
amd64, aarch64, riscv64 (clean qemu), stick-high, test-32, run one at a
time in the foreground through scripts/nightly.sh:
  PARITY:V4_POST tests=538 pass=538 fail=0, POST: PASSED, [zuse@Hera] ok>
  on every boot; PARITY:V4_SYSTEM word_count=318
  dict_hash=0x8c92508f748f99cf on all three; test-32 39 programs, 0 failures.
No tracked file changed across the five builds.

  20261111-170703  amd64       PASS
  20261111-170909  aarch64     PASS
  20261111-171235  riscv64     PASS
  20261111-171410  stick-high  PASS

Also kept as evidence:
  20261111-170134  amd64 on aec7ddb5 (before the clean-tree fix), PASS
  20261111-170544  amd64 on 90c5c140, stopped by me during boot: it had been
                   started in the background, against the protocol, and was
                   rerun in the foreground as 20261111-170703
DoE CSVs for every completed boot (experiments/bare_metal/runs).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 17:21:24 +00:00
Claude 90c5c140ea build: a build no longer dirties the tree
v3/include/version.h is written by every build (kernel/Makefile and
v3/Makefile, both FORCE), with a timestamp and the last build's ARCH; the
committed copy was stale (LITHOS_VERSION 2.1.0). Untracked, and .gitignore's
entry corrected: it said include/version.h, the path before the move to v3/,
and matched nothing.

capsules/BLOCK_MAP.md differed on every build only in mkcapsule's
"Generated ... <timestamp>" header. The timestamp is dropped, so the manifest
changes only when the capsules do; two runs are byte-identical.
mkcapsule's warnings unchanged (5, #143).

Captain Bob, 2026-11-11: untrack version.h and fix the ignore; drop the
manifest timestamp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 17:05:01 +00:00
Claude aec7ddb56e chore(lfs): trim 3,939 files whose LFS objects never reached the server
Their pointers were committed in a5ed8c3d (2026-08-01) and the objects were
never uploaded: the server answers 404 for all of them, and no copy exists
(Captain Bob, 2026-11-11: "they can be trimmed out").

Removed: 3,827 phase-1 logs (docs/working/archive/legacy/phase-1), 3 in
docs/working/archive/historical, 106 DoE CSVs in experiments/bare_metal/runs,
QEMU_BASELINE.log, docs/SYSTEM_NARRATIVE.log, docs/ontology.log.

Kept: the 5 LaTeX build logs under docs/patent (legal hold) -- excluded from
fetch instead. .lfsconfig excludes every one of these paths, so older commits
check out and LFS fetches run without 404s.

Every LFS pointer left in the tree (1,195) has its object on the server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 16:56:32 +00:00
Claude 7adc43220d Code review notes, pass 2: identity hot-plug, GPT, USB, acceptance scripts
Findings reported, not fixed (Captain Bob's Law).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 16:22:54 +00:00
Claude ce04420f6b Add Claude's working notes: rules, document notes, code review, discrepancies
Session notes from reading the repo and reviewing the v4 engine and kernel v4 path.
Findings are reported, not fixed (Captain Bob's Law).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 16:18:35 +00:00
Claude CodeandClaude Opus 5.5 06f1d41aea chore(lfs): move 146 QEMU logs into LFS to match .gitattributes
Build / Image MILKV (push) Successful in 13m29s
Build / Image RASPI (push) Successful in 8m20s
Build / Image PC (push) Successful in 7m26s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 23m4s
Acceptance / Acceptance (pull_request) Successful in 41m49s
These logs/ files were committed as plain text even though
.gitattributes routes logs/**/*.log through the LFS filter, so every
fresh clone showed them all as modified. Renormalize them so they are
stored as LFS pointers. File contents are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-11 14:46:17 +00:00
Claude Code c32bc43e36 docs: correct 5 stale items in .claude/CLAUDE.md (closes #137)
Build / Image PC (push) Successful in 6m19s
Build / Image MILKV (push) Successful in 4m5s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 11m52s
Build / Image RASPI (push) Successful in 4m52s
Acceptance / Acceptance (pull_request) Successful in 20m34s
- Capsule count: 23 -> 39 (33 at capsules/*.4th + 6 in artemis/, hestia/, v4/)
- LITHOS_VERSION: 2.1.0 -> 4.0.0-alpha.4 (corrected 2026-11-10)
- CI section: replace stale job IDs (build-amd64-iso etc.) with current
  six-workflow description; acceptance.yml is the PR gate, build.yml runs
  image+v4-tests, nightly/nightly-docs/release/runner-image also documented
- Warnings: 26 -Wunused-parameter + 2 -Wsign-compare + 2 -Wstringop-truncation
  -> 5 -Wformat-truncation in tools/mkcapsule.c (corrected 2026-11-10)
- Dictionary: 526 words, hash 0x82f4ae7cb2e2d424 -> 318 words,
  hash 0x8c92508f748f99cf (corrected 2026-11-10 from PARITY:V4_SYSTEM logs)
2026-11-10 19:26:01 +00:00
Robert James 93828e0eb9 release: v4.0.0-alpha.4
Build / Image RASPI (push) Successful in 6m20s
Build / Image PC (push) Successful in 4m41s
Build / Image MILKV (push) Successful in 5m21s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 13m39s
Acceptance / Acceptance (pull_request) Successful in 20m55s
Runner image / Build and publish the runner image (push) Failing after 10m40s
Release / Release ${{ github.ref_name }} (push) Successful in 56m20s
2026-11-10 15:19:25 +00:00
Claude 468b03a093 site(org): each .com inquiry also e-mailed to rajames440@gmail.com, Reply-To the visitor (#161) [skip ci]
PublicInquiry files the inquiry as before, then mails it through the wiki's mail service: plain text, the subject fixed but for the topic (line breaks removed), Reply-To the visitor's checked address, a link to the filed entry. If it is not sent the inquiry is filed all the same; a new class field, mailed (E-mailed to Captain Bob), says which, shown on the entry's sheet. Installed on the .org; a guest's test inquiry filed and thanked, mailed 0 -- the wiki has no SMTP account yet (Mail.MailConfig: no host), which Captain Bob sets in Administration > Email.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 11:45:40 +00:00
Claude da14d9afc6 site(com): every email address to rajames440@gmail.com (#161) [skip ci]
Home's footer and announcements form, and the four addresses of Inquiries' 'Or write directly' (info@, licensing@, press@starshipos.com, security@starshipos.org): all rajames440@gmail.com (Captain Bob, 2026-11-10). On the design canvas (v18) and in site/com; the pages rebuilt. Installed on the .com with site/com/install.sh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 11:40:07 +00:00
Claude be2c204d56 site(com): Downloads and Documents, built from a release; the nav links; the release's SHA256SUMS covers every file (#126, #157) [skip ci]
The design canvas (v17) gains the Documents artboard -- the Book of Fabric and
the Dictionary of v4 first, then the book, the three volumes and the API
reference, each with its SHA-256, and the SSRN paper -- and Downloads and
Documents in every .com nav; Downloads' reading list becomes a pointer to
Documents. site/com/canvas/ copied from it.

site/com/build.py --release TAG --sums SHA256SUMS builds Downloads and
Documents from the release ([TAG], [RELEASE]/<file>, [SHA:<file>]; a file the
release's SHA256SUMS lacks fails the build). Without a release it builds Home,
Try it and Inquiries exactly as before -- byte for byte -- with no link to the
two pages, so they go live only with alpha.4. install.sh installs them when
built.

scripts/nightly.sh gitea-release: the release's SHA256SUMS now covers every
file it attaches -- the images' sums, then the PDFs and the Root CA's
certificate -- so `sha256sum -c SHA256SUMS` checks all of it and Documents
finds each sum. The Nexus artifacts keep their own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 11:38:50 +00:00
Claude 1a9b142d80 docs: The Dictionary of v4 -- every live word, alphabetical, its stack notation and description; built and published with every release (#157) [skip ci]
make dictionary -> build/docs/Dictionary.pdf (20 pages): mkdictionary.py checks docs/reference/v4-dictionary.tsv against the booted system's words first, so a stale dictionary fails the build; then Markdown, pandoc, docs/book/dictionary.tex (the books' preamble, its own title page: version and commit). Quoted FORTH tokens set as code, so their quotes print straight. The nightly's docs stage builds it; publish sends classifier dictionary; the Gitea release attaches it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 11:31:07 +00:00
Claude 135cccb37d docs(dictionary): batch 3 -- Q..Z and the brackets; every one of the 318 live words has its entry (#157) [skip ci]
LSHIFT corrected (a count out of range is error 9, as DECOMPOSITION.md says, not 0). mkdictionary.py check: covers all 318 live words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 11:29:20 +00:00
Claude e3fc57fb17 docs(dictionary): batch 2 -- D..P (#157) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 11:28:10 +00:00
Claude 1c9a65c970 docs(dictionary): batch 1 -- the symbols, the digits, A..C (#157) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 11:26:58 +00:00
Claude a53cc82dd5 docs(dictionary): mkdictionary.py and the draft table -- every live v4 word, 318 (#157) [skip ci]
The names from the system itself (the hosted v4's WORDS, plus the kernel's sk_v4_words[]); the stack notation and description in docs/reference/v4-dictionary.tsv, drafted from the source where it says (54 stacks, 105 descriptions), the rest to write. check refuses a missing, unfinished or stale entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 11:25:01 +00:00
Claude 41abad0159 docs: The Book of Fabric -- the FABRIC design record as one book, built and published with every release (#138) [skip ci]
`make fabric` -> build/docs/BookOfFabric.pdf (722 pages): Part I the living
record (FABRIC-3), Part II the closed documents in the order written, Part
III the forward-looking notes; its title page carries the version (git
describe --tags: a release's tag) and the commit. Built from the same pandoc
fragments as the book; the book's preamble moved into docs/book/preamble.tex,
shared by both (the book builds as before, 821 pages).

scripts/nightly.sh: the docs stage builds it ($DOCS/fabric.pdf); publish
sends it as classifier `fabric`; gitea-release attaches every PDF in $DOCS,
so every release carries it. Progress for the rest of alpha.4's documents:
docs/v4.0.0/plans/2026-11-10-alpha4-documents.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 11:21:32 +00:00
Claude 836b4423e1 feat(kernel): the fixed screen -- with a real Zuse, the system stick alone can only mint a replacement; the old stick dies (#92, Task 5)
Build / Image RASPI (push) Successful in 4m21s
Build / Image PC (push) Successful in 5m1s
Build / Image MILKV (push) Successful in 7m22s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 12m17s
Acceptance / Acceptance (pull_request) Successful in 19m56s
Runner image / Build and publish the runner image (push) Failing after 5m37s
Release / Release ${{ github.ref_name }} (push) Canceled after 0s
Task 5 of plan 2026-10-29-stick-5, accepted in full, and with it #92:
- amd64, aarch64, riscv64: PARITY:V4_POST tests=538 pass=538 fail=0,
  POST: PASSED; word_count=318 dict_hash=0x8c92508f748f99cf on the three
- the PC stick as built, loaded high: 538/538, the prompt
- make -C v4 test-32: 39 programs, 0 failures

Sessions: fallback, replace, mint_fail, system_pull_real; regressions:
every Task 4 session, genesis, stick_genesis, screen_dark_until_login,
screen_dark_after_logout, kbd_typeahead, emergency. Verdicts in
logs/20261110-075036/verdicts/. The plan's Task 5 ticked; STICK.md 11
increment 5a done; FABRIC-3 XLVIII.17; the SER5 bench steps in
boards/BRINGUP.md 4.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 07:59:58 +00:00
Claude 4742cf8b3b boards(BRINGUP): the SER5 bench steps for the plug-and-play stick and the real Zuse (#92, Task 5 step 6) [skip ci]
First boot (genesis, growth, the time to the prompt), the second boot, MINT-ZUSE onto a second stick, the system stick alone (the fixed screen), both sticks at power-on -- each rehearsed first in QEMU by the qemu_session.py mode named. 3.2's 'boots headless' corrected: the stick's first boot now mints its Zuse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 07:05:11 +00:00
Claude ed1e844d71 logs: mint_fail -- a failed write changes nothing, the old stick still logs in: PASS (#92, 5.6) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 07:04:39 +00:00
Claude 8320310497 logs: replace and system_pull_real PASS; mint_fail's one FAIL was the test's -- it counted the first boot's mint in the second boot's log (#92, 5.6) [skip ci]
mint_fail's own checks passed (failed -- nothing changed, the screen again, the old stick logs in); the check now expects none in this boot's log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 06:58:45 +00:00
Claude b8da642f02 test(stick): the fixed screen's other sessions -- replace, mint_fail, system_pull_real (#92, 5.6) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 06:42:07 +00:00
Claude bb64678692 logs: fallback -- the fixed screen, keys dropped, her stick, R: PASS (#92, 5.3-5.4) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 06:41:16 +00:00
Claude 933f50fa18 feat(kernel): the fixed screen -- with a real Zuse, the system stick alone can only mint a replacement (#92, 5.3-5.5) [skip ci]
The four lines on the screen and serial while the proxy is recognised and her stick is not here; R runs sk_v4_mint_zuse(), every other key is dropped. Her stick pulled: the screen again. The system stick pulled while hers is in: hers let go first (the block chain's tail), remembered for the system stick's return. Builds on three ISAs; fallback running.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 06:34:56 +00:00
Claude 46baa3f0d0 test(stick): fallback seen to fail -- no fixed screen, R does nothing (#92, 5.2) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 06:34:21 +00:00
Claude e824748cbd test(stick): the fixed screen's first test, fallback; Task 5's increments in the plan (#92, 5.1) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 06:22:47 +00:00
Claude 7fee88eb49 feat(kernel): MINT-ZUSE -- the real Zuse minted onto a second stick, read back before the marker names her (#92, Task 4)
Build / Image RASPI (push) Successful in 2m42s
Build / Image PC (push) Successful in 3m17s
Build / Image MILKV (push) Successful in 2m43s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 9m28s
Task 4 of plan 2026-10-29-stick-5, accepted in full:
- amd64, aarch64, riscv64: PARITY:V4_POST tests=538 pass=538 fail=0,
  POST: PASSED; PARITY:V4_SYSTEM word_count=318 dict_hash=0x8c92508f748f99cf
  on the three (MINT-ZUSE, the lone node's second word)
- the PC stick as built, loaded high: 538/538, the prompt
- make -C v4 test-32: 39 programs, 0 failures

Sessions: mint_zuse on the three; mint_zuse_refuse, mint_small,
mint_zuse_used, mint_pull_system, zuse_stick_first; regressions genesis,
two_sticks, hotplug, midpull, typeahead. Verdicts in
logs/20261110-051726/verdicts/. The plan's Task 4 ticked; FABRIC-3 XLVIII.16.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 05:28:38 +00:00
Claude 1881f30e6c logs: MINT-ZUSE on aarch64 and riscv64, the regressions, acceptance on three ISAs and the stick high: PASS (#92, 4.8-4.9) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 05:19:03 +00:00
Claude 012e3c0348 logs: MINT-ZUSE's sessions -- refused, small, a used stick, the system stick pulled, her stick first: PASS (#92, 4.8) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 04:53:09 +00:00
Claude 7a27d6a3e5 test(stick): the rest of MINT-ZUSE's sessions -- refused, small, a used stick, the system stick pulled, her stick first (#92, 4.8) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 04:41:07 +00:00
Claude 34d43a3418 logs: mint_zuse -- the real Zuse minted, her stick recognised, her session: PASS (#92, 4.7) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 04:39:52 +00:00
Claude 3b214394d0 feat(kernel): the real Zuse's stick recognised, attached at the chain's tail; her session (#92, 4.7) [skip ci]
A GPT stick with an identity partition and no Artemis, the system stick in and its marker naming a real Zuse: checked against the real key; a match attached and logged in (a running session moves to her); no match: 'not this system's Zuse stick -- not used'. Arriving first, it is remembered and checked when the marker is read. Builds on three ISAs; mint_zuse running.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 04:37:47 +00:00
Claude acd8061d89 FABRIC-3 XLVIII.15: the header scan, and SPDX headers on 253 files [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 04:13:15 +00:00
Claude 3bd81097e1 chore(license): an SPDX header on every source file that had none (LicenseRef-Starship-1.0) [skip ci]
The header scan (Captain Bob, 2026-11-10): 788 source files -- 351 with the
SL-1.0 header, 12 with the old name (docs/working/experiments, kept by
ruling), 31 under someone else's licence (tools/kconfig, Linux's, GPL-2.0:
kept), and 394 with none. Ruled: the SPDX form; capsules (.4th, .f18) and
proofs (.thy) left for a ruling of their own (mkcapsule's 64x16 block format,
content-addressed capsules).

253 files now begin
    SPDX-License-Identifier: LicenseRef-Starship-1.0
    Copyright (c) 2023-2026 Robert A. James
as a /* */ block (C, headers, assembly, linker scripts) or # lines (scripts,
Makefiles, Kconfig; below a shebang or a coding line); tools/mkcapsule.c,
which had the copyright line, gets the SPDX line only.

Not touched: docs/working/ (archive and old campaign material, as the
ruling kept the experiments); v4/system/post_cases.c (generated by
v4/tools/mkpost.py, "do not edit" -- the generator has the header).

Comments only: the kernel builds on amd64, aarch64, riscv64; make -C v4
test-32: 39 programs, 0 failures; every changed script parses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 04:12:49 +00:00
Claude 13aee1a767 logs: mint_zuse on amd64 -- MINT-ZUSE mints the real Zuse onto a second stick: PASS (#92, 4.6) [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 04:04:00 +00:00
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: http://gitea.starshipos-f18.org/rajames/LithosAnanke/pulls/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: http://gitea.starshipos-f18.org/rajames/LithosAnanke/pulls/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
rajames 777f739708 Merge pull request 'release: v4.0.0-alpha.3; the proofs run capped to fit the server' (#132) from StarForth-v4.0.0 into master
Release / Release ${{ github.ref_name }} (push) Successful in 41m51s
2026-11-07 20:52:52 +00:00
Claude b8951bc26b release v4.0.0-alpha.3: accepted in full, logs
Build / Image PC (push) Successful in 3m56s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 10m7s
Build / Image MILKV (push) Successful in 8m45s
Acceptance / Acceptance (pull_request) Successful in 15m37s
Build / Image RASPI (push) Successful in 4m11s
On 50d2bc98 (LithosAnanke v4.0.0-alpha.3), in this session, one QEMU at a
time in the foreground: amd64 logs/20261107-195526, aarch64 -195725,
riscv64 -200055 (POST 538/538, dict_hash=0xfec8c47cfc6f437f on all three),
the stick loaded high, test-32 (39 programs, 0 failures); the proofs
through the capped stage, logs/20261107-195341 (47 s, ~1.8 GiB).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 20:09:33 +00:00
Claude 50d2bc98d9 release: v4.0.0-alpha.3; the proofs run capped to fit the server
v4.0.0-alpha.2's release run (200) was killed in the StarForth session:
Isabelle's defaults (Java 4 GiB, a thread per CPU). scripts/nightly.sh
proofs now runs one thread, Java 512 MiB, Poly/ML 900 MiB, through a
settings file of a home made for the run (heaps linked to the user's):
47 s, ~1.8 GiB, logs/20261107-195341. Nothing was published from alpha.2;
its tag stays. LITHOS_VERSION 4.0.0-alpha.3. FABRIC-3.md XLVII.6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 19:54:47 +00:00
rajames 2d43db252a Merge pull request 'release: v4.0.0-alpha.2; release.yml keeps the image's Isabelle' (#130) from StarForth-v4.0.0 into master
Release / Release ${{ github.ref_name }} (push) Failing after 17m36s
2026-11-07 19:32:30 +00:00
Claude 37f62d688b logs: three riscv64 boots of v4.0.0-alpha.2, looking for run 197's failure
Build / Image MILKV (push) Canceled after 0s
Acceptance / Acceptance (pull_request) Successful in 16m36s
Build / Image RASPI (push) Canceled after 0s
Build / v4 tests (32- and 64-bit cells) (push) Canceled after 0s
Build / Image PC (push) Canceled after 0s
Acceptance run 197 (#130) failed one riscv64 check: no 'Boot disk: not a
StarshipOS stick' line, with POST, the identity and the prompt all passing.
Booted three more times here on the same tree: each printed the line and
passed (4 of 4 with logs/20261107-184616). The Zuse stick has no ESP
(--esp-mib 0), so the firmware cannot have booted from it; the serial
capture losing or garbling the line is what is left to check, against run
197's own log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 19:15:04 +00:00
Claude cabe974872 release v4.0.0-alpha.2: start #130's acceptance check
Acceptance / Acceptance (pull_request) Failing after 8m7s
The commit before this one quoted the skip marker in its message, so Gitea
skipped its checks too. No change to the tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 18:59:34 +00:00
Claude 4a125cdd21 release v4.0.0-alpha.2: run the acceptance check on #130
The commits before this one carry [skip ci], which Gitea also applies to
the pull request's checks. No change to the tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 18:56:16 +00:00
Claude d8bf2e1121 release v4.0.0-alpha.2: accepted in full, logs [skip ci]
The protocol on 04006bff (LithosAnanke v4.0.0-alpha.2), in this session,
one QEMU at a time in the foreground: amd64 logs/20261107-184040, aarch64
-184241, riscv64 -184616 (POST 538/538, dict_hash=0xfec8c47cfc6f437f on all
three), the stick loaded high -184753, test-32 (39 programs, 0 failures),
the Isabelle/HOL proofs (logs/20261107-185450/).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 18:55:30 +00:00
Claude 04006bff12 release: v4.0.0-alpha.2; release.yml keeps the image's Isabelle [skip ci]
v4.0.0-alpha.1's release run (196) was killed in the proofs: release.yml's
full `make init` fetched Isabelle into the workspace and pointed isabelle
at it, without the image's prebuilt HOL-Library, so the proofs built it
from scratch. Nothing was published. Ruled: the tag stays; release.yml runs
`init INIT_PROOFS=0`; LITHOS_VERSION 4.0.0-alpha.2, the first published
alpha. FABRIC-3.md XLVII.5, CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 18:40:00 +00:00
rajames 233025da88 Merge pull request 'ci: the workflows run in the runner image with HOL-Library' (#128) from StarForth-v4.0.0 into master
Release / Release ${{ github.ref_name }} (push) Failing after 19m2s
2026-11-07 18:17:52 +00:00
Claude 3c21a20f1a ci: the workflows run in lithosananke-runner:4f675c8b75b2, with HOL-Library
Build / Image RASPI (push) Successful in 2m28s
Build / Image PC (push) Successful in 2m56s
Build / Image MILKV (push) Successful in 2m34s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 8m52s
Acceptance / Acceptance (pull_request) Successful in 12m30s
The image runner-image.yml built from master 4f675c8b (run 193): what init
installs, Maven, and the HOL-Library heap fetched prebuilt (checksum OK, 4.8
s), so the proofs build only the StarForth session. Its acceptance run is
this PR's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 17:47:12 +00:00
rajames 4f675c8b75 Merge pull request 'LithosAnanke v4.0.0-alpha.1: the first alpha release' (#127) from StarForth-v4.0.0 into master
Runner image / Build and publish the runner image (push) Successful in 51s
2026-11-07 17:46:01 +00:00
Claude da020a430d ci: one concurrency group for every workflow; a runner-image rebuild blocks the rest
Build / v4 tests (32- and 64-bit cells) (push) Canceled after 0s
Acceptance / Acceptance (pull_request) Successful in 13m6s
Build / Image RASPI (push) Canceled after 0s
Build / Image PC (push) Canceled after 0s
Build / Image MILKV (push) Canceled after 0s
Captain Bob, 2026-11-07: "I also want that rebuilds block other jobs
always." acceptance, nightly and release shared the group qemu; now
runner-image, build and nightly-docs do too, so a rebuild of the runner
image (on the host's Docker daemon) never overlaps another job, whatever
the runner's capacity (#121). On this server every CI run is then one at a
time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 17:17:11 +00:00
Claude 2580a40e1d ci: the runner image fetches HOL-Library, prebuilt, instead of building it
Build / Image MILKV (push) Successful in 2m18s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 8m45s
Build / Image RASPI (push) Successful in 2m13s
Build / Image PC (push) Successful in 2m29s
Acceptance / Acceptance (pull_request) Canceled after 0s
The server cannot build it (5.3 GiB from scratch; capped, still 2.6-3.3
GiB against ~2.3 GiB free). The heap built here by the same Isabelle2025-2
is a generic package in this repository's registry (45 MB, SHA-256
bb247846...e999cb339e); the Dockerfile fetches it into Isabelle's system
heaps with the checksum pinned, the token a build secret. Portable: a
fresh Isabelle home with only this heap checks StarForth without
rebuilding HOL-Library. FABRIC-3.md XLVII.4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 17:15:56 +00:00
Claude 857083359f Merge Captain Bob's c589d3d5 (the same certificate, committed on the CI box) [skip ci] 2026-11-07 17:12:04 +00:00
Claude 458f8f3ec8 release v4.0.0-alpha.1: accepted again with the StarshipOS certificate [skip ci]
The protocol on 4ca935d8: three boots (POST 538/538, one dict_hash), the
stick loaded high, test-32 (39 programs, 0 failures), the proofs. Every
capsule logs 'missing (unsigned)': the kernel reads the new certificate;
CI signs with CAPSULE_SIGN_KEY. FABRIC-3.md XLVII.3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 17:11:40 +00:00
Claude 4ca935d82e pki: the StarshipOS Capsule Signing certificate, in place of snakeoil [skip ci]
Made on the CI box by ci/pki/make-ca.sh (2026-11-07 16:50 UTC): subject
O=StarshipOS, CN=StarshipOS Capsule Signing; issuer O=StarshipOS,
CN=StarshipOS Root CA; 2026-11-07 to 2036-11-06; CA:TRUE, pathlen:0;
Ed25519. SHA-256 of the DER
13a28dda4098ef4f11cba42823a30a9898fdaffdf0c15130126fd2fe029b9a6c. Its key
is the repository secret CAPSULE_SIGN_KEY; the root's stays on the box.
The snakeoil intermediate leaves the tree (its history is in git).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 16:55:37 +00:00
Robert A. James c589d3d5b7 pki: the StarshipOS CA, made on the CI box (Captain Bob, 2026-11-07)
Build / Image RASPI (push) Successful in 3m44s
Build / Image PC (push) Successful in 2m53s
Build / Image MILKV (push) Successful in 2m37s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 9m8s
2026-11-07 16:51:39 +00:00
Claude d7d431f1d6 release v4.0.0-alpha.1: accepted in full, logs and record [skip ci]
The acceptance protocol on b7534107 (LithosAnanke v4.0.0-alpha.1), in this
session, one QEMU at a time in the foreground:
- amd64 logs/20261107-150809, aarch64 -151023, riscv64 -151359: [zuse@Hera]
  ok>, PARITY:V4_POST tests=538 pass=538 fail=0, POST: PASSED,
  dict_hash=0xfec8c47cfc6f437f on all three
- the PC stick loaded high, logs/20261107-151539: the same, no fault
- make -C v4 test-32: 39 programs, 0 failures
- Isabelle/HOL proofs, logs/20261107-152312/isabelle: Finished StarForth

CHANGELOG and FABRIC-3.md XLVII: the ruling, what was verified, and what
an alpha leaves open (the v4.0.0 milestone; unsigned capsules until the
StarshipOS CA).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 15:24:28 +00:00
Claude b7534107f3 kernel: v4.0.0-alpha.1, the first alpha release [skip ci]
Captain Bob, 2026-11-07: "Kernel is 4.0.0. This is our first alpha
release." LITHOS_VERSION 2.1.0 -> 4.0.0-alpha.1; the engine (VERSION)
stays 3.2.0. The 4.x line is a working line (even major); v3.0.0 is no
longer the next number, and an LTS line takes the next odd major when
FABRIC-3.5.md XXX.5's criteria are met. Recorded in kernel/Makefile's
versioning policy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 15:07:17 +00:00
Claude 236839a914 site/brand: the banner says StarshipOS [skip ci]
Captain Bob, 2026-11-07: "The banner XWiki should not say that." Both
wikis now have a colour theme of their own, FlamingoThemes.StarshipOS (the
stock Iceberg, copied, with the starshipOS wordmark as its logo; Iceberg
untouched), and the browser tab's title ends "- StarshipOS". Installed on
both; checked as a guest on each (logo and title), and the .org's top bar
seen logged in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 14:36:36 +00:00
Claude bb3246f924 ci: no Build run for a commit that only changes site/ [skip ci]
Five website commits queued five Build runs (183-187), ~17 minutes of image
builds each on the server both wikis run on; the .org stopped answering.
build.yml now ignores pushes whose changes are all under site/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 13:55:24 +00:00
Claude 038556bb3e site: visitors see the design alone, not XWiki's chrome
Build / Image MILKV (push) Canceled after 0s
Build / Image PC (push) Canceled after 0s
Build / Image RASPI (push) Canceled after 0s
Build / v4 tests (32- and 64-bit cells) (push) Canceled after 0s
Captain Bob, 2026-11-07: "Menu bar". For guests only, the .com pages and
the .org landing page hide XWiki's top bar, breadcrumb, title block, page
menu, panels, footer and tour, and the design runs the full width (a
velocity check on $isGuest; the stylesheet in a literal block). Logged in,
the wiki is all there. Checked on a phone and a desktop: the chrome is
hidden on Main, Inquiries and TryIt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 13:51:15 +00:00
Claude dca3ea56b9 site: no Python caches
Build / Image MILKV (push) Canceled after 0s
Build / v4 tests (32- and 64-bit cells) (push) Canceled after 0s
Build / Image PC (push) Canceled after 0s
Build / Image RASPI (push) Canceled after 13s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 13:47:48 +00:00
Claude c2ff10015f site: the design's colours over the wikis' high-contrast theme; .org inquiries
Build / Image MILKV (push) Canceled after 0s
Build / Image PC (push) Canceled after 0s
Build / Image RASPI (push) Canceled after 0s
Build / v4 tests (32- and 64-bit cells) (push) Canceled after 0s
- site/colorlock.py: both XWikis force black and white with !important (a
  HIGH CONTRAST DARK THEME block in the skin's cssVariablesInit.css). On our
  pages only, the design's colours win: each inline colour made !important,
  and a stylesheet scoped to the page root (.ssos) for the rest. Used by
  site/com/build.py and site/org/build.py; the .com reinstalled with it.
- site/org/inquiries (Captain Bob, 2026-11-07): the .com's inquiries go to an
  admin-only master/detail on the .org -- Inquiries.WebHome (Live Data
  table), one page per inquiry under Inquiries.Entries with a sheet and a
  status, PublicInquiry (public) filing them with its author's rights and
  echoing nothing a visitor sends; a hidden trap field for robots. The .com
  form posts there. Installed and tested: a guest's inquiry filed and
  deleted; one whose name and message were script macros was stored as
  text, nothing ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 13:47:37 +00:00
Claude 7d9dd4e4a9 site/org: installed; rights before pages; objects as XML
Build / Image RASPI (push) Successful in 2m17s
Build / Image MILKV (push) Canceled after 0s
Build / v4 tests (32- and 64-bit cells) (push) Canceled after 0s
Build / Image PC (push) Canceled after 1m3s
The first run on starshipos-f18.org created the dashboards, then XWiki
refused the group and rights objects: a form-encoded POST needs XWiki's
form token (CSRF), an XML one does not. For about two minutes Admin.WebHome
and Contributors.WebHome were readable by guests (links and the names of
secrets, no values). Objects now go as XML, and the spaces' rights are made
before the pages, so a failed run cannot leave a dashboard open. Installed:
Main 200, Admin and Contributors 401 as a guest, 200 as rajames; a second
run changes nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 13:32:56 +00:00
Claude 8918951482 site/com: the .com pages from the design canvas, installed
Build / Image RASPI (push) Successful in 3m1s
Build / Image PC (push) Successful in 3m39s
Build / Image MILKV (push) Successful in 4m27s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 11m56s
Captain Bob, 2026-11-07: build the .com from the StarshipOS.com canvas.
canvas/ holds the artboards as drawn; build.py makes Main, Inquiries and
TryIt as {{html}} pages (the wiki's links and domains, the images as
attachments, the real console in Try it, the forms by e-mail); install.sh
puts them on the wiki and checks a guest's view. Installed on
starshipos-f18.com: every page and image reads 200 as a guest, and renders
without a macro error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 13:31:31 +00:00
Claude 911b1529cc Merge remote-tracking branch 'origin/master' into StarForth-v4.0.0
Build / Image RASPI (push) Successful in 5m30s
Build / Image PC (push) Successful in 3m44s
Build / Image MILKV (push) Successful in 2m59s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 9m50s
2026-11-07 11:36:29 +00:00
rajames e15d9022cf Merge pull request 'ci: the nightly's proofs run last, and cannot hold back the images' (#124) from nightly-proofs-last into master 2026-11-07 11:36:22 +00:00
Claude c27fdc6289 ci: the nightly's proofs run last, and cannot hold back the images
Acceptance / Acceptance (pull_request) Successful in 13m29s
Nightly 174 passed acceptance, then Isabelle was killed building HOL-Library
(exit 137, out of memory on the runner), and the images were never built or
published. The proofs check the theories, not the images: they now run after
the publish, whatever happened before them, and a failure still turns the run
red. Their log stays in the run's logs artifact. A release still runs them
before it publishes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 11:21:59 +00:00
5461 changed files with 18512 additions and 14116 deletions
+72 -40
View File
@@ -116,9 +116,6 @@ what the nightly runs are one and the same.
silently dropped. 1025 = 1024 content bytes + 1 NUL terminator.
### Gotchas in the tree
- **`kernel/src/kernel_main.c`'s own header comment claims "M7: Not started" -- it is STALE.**
M7/M7.1/M7.pre logic is present and functional (`kernel_main.c` ~lines 481-517). Don't
propagate the stale comment.
- **`kernel/src/virtio/virtio_blk.c` relates to the roadmap's "M9 block storage" item** --
implemented via virtio, not AHCI as older docs describe. Don't assume milestone-complete from
source presence alone; that hasn't been verified.
@@ -201,9 +198,10 @@ removed as an active target.)
**Current status: M7.1** — capsule birth protocol, Mama FORTH vocabulary, Tripod multi-VM
fleet (Hera/Artemis/Hestia — Hermes moved into the kernel as kernel-Hermes, FABRIC-3.6.md
Phase 4, 2026-09-22), and word-level ACL (Phases 1–7) are live; POST at boot verifies parity
hash across amd64/aarch64/riscv64 with a 526-word Mama capsule dictionary (word count as of
2026-10-14, `FABRIC-3.md` §XXXVIII, hash `0x82f4ae7cb2e2d424`; verify against a live `PARITY:M7.1a word_count=` line before citing, it
changes with any new C word registration).
hash across amd64/aarch64/riscv64 with a 318-word Mama capsule dictionary (word count as of
2026-11-10, hash `0x8c92508f748f99cf`; corrected 2026-11-10 — this file said 526 words,
hash `0x82f4ae7cb2e2d424` (2026-10-14, `FABRIC-3.md` §XXXVIII); verify against a live
`PARITY:V4_SYSTEM word_count=` line before citing, it changes with any new C word registration).
---
@@ -231,12 +229,11 @@ Output: `build/<arch>/kernel/starkernel_loader.efi` + `build/<arch>/kernel/stark
Two independently tracked version strings flow into the generated `include/version.h`:
`VERSION` (`kernel/Makefile` — the embedded StarForth engine version, currently `3.2.0`;
note this does **not** auto-sync with the standalone StarForth repo's own version) and
`LITHOS_VERSION` (`kernel/Makefile` — the kernel version, currently **`2.1.0`**, bumped at
the `v2.1.0` tag that closed FABRIC-3.6; corrected 2026-10-14 -- this file said `3.1.0` /
`2.0.0`. History: it said `2.0.1` until 2026-09-19, but `FABRIC-3.md` §I.2 had rolled that
back to `2.0.0` on 2026-09-04 because `2.0.1` names the SER5 hardware-track line and claims
hardware progress not yet verified. The versioning policy is **semantic, not sequential** — see the
roadmap table in `kernel/Makefile` before choosing any version).
`LITHOS_VERSION` (`kernel/Makefile` — the kernel version, currently **`4.0.0-alpha.4`**; corrected 2026-11-10 — this file said `2.1.0` (bumped at
the `v2.1.0` tag that closed FABRIC-3.6; corrected 2026-10-14 from `3.1.0` / `2.0.0`, which
replaced `2.0.1` on 2026-09-19 per `FABRIC-3.md` §I.2 — `2.0.1` named the SER5
hardware-track line and claimed unverified progress). The versioning policy is
**semantic, not sequential** — see the roadmap table in `kernel/Makefile` before choosing any version).
### Build configuration (Kconfig — real, wired, not vestigial)
@@ -291,14 +288,34 @@ 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):
make -C v4 test-32
```
**The developer protocol (#135, 2026-11-12) is the acceptance a developer runs, and its evidence
goes in the PR** (Captain Bob, 2026-11-07: "We can simply run nightly as developers ... Just no
Nexus push ... Then the protocol evidence can be submitted in the PR."):
```bash
scripts/nightly.sh protocol # every stage above, then the proofs, the images, the documents; never publish
```
It writes `logs/<TS>/PROTOCOL.md` (the commit, its tree clean or not, each stage's result, POST and
`dict_hash` per architecture, test-32, the proofs, the images' and documents' SHA-256) and each
stage's output in `logs/<TS>/protocol/`. Commit `logs/` and `experiments/bare_metal/runs/`; the
PR's Acceptance check (`scripts/check_protocol.sh`) refuses a head without a passing PROTOCOL.md
for its tree -- any change outside the evidence after the run is stale, and the protocol is run
again. **One stage per foreground command is also a protocol**, and is how an agent runs it (the
QEMU rule: never in the background): `scripts/nightly.sh protocol accept-amd64`, then
`accept-aarch64`, `accept-riscv64`, `accept-stick-high`, `test-32`, `proofs`, `images`, `docs`,
each its own command, then `scripts/nightly.sh protocol-report`. The tools: `make
ARCH=amd64,aarch64,riscv64 init`, plus the HOL-Library heap the CI image has (`ci/runner-image`).
**v4 is the default build (Captain Bob, 2026-10-14: "v4 is the default build ... no, qemu to v4
too ... we are effectively trying to retire v3").** Every kernel build carries v4 and v3 and
boots v4; `system=v3` in the boot arguments (`KERNEL_ARGS` for QEMU, `starforth.cfg` /
@@ -326,14 +343,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 +363,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
@@ -351,11 +371,24 @@ present in `logs/`:
### CI
`.gitea/workflows/build.yml` runs three parallel jobs, each building a real bootable
artifact (not just compiling): `build-amd64-iso` (kernel build + El Torito ISO),
`build-aarch64-iso` (same, ARM boot file naming), `build-riscv64-img` (kernel build + raw
GPT/FAT32 disk image — riscv64 virt doesn't support El Torito ISO or `-bios` QEMU mode, so
it ships a raw disk image instead). No QEMU boot step in CI — artifact packaging only.
**Corrected 2026-11-10** — this file previously named stale job IDs (`build-amd64-iso`,
`build-aarch64-iso`, `build-riscv64-img`) and said "No QEMU boot step in CI."
Six workflows in `.gitea/workflows/`. **One job at a time across all of CI, and none cancelled**
(corrected 2026-11-11, #140 -- Captain Bob: "It should be global"): there is no concurrency group;
the one runner (`starshipos-vps`) has capacity 1, so every job of every workflow waits its turn in
Gitea's queue. The shared `qemu` group this file described kept only one waiting run, and each run
that joined cancelled it:
- **`acceptance.yml`** — PR gate into `master`: 3 QEMU boots (amd64/aarch64/riscv64)
+ PC stick loaded high + `make -C v4 test-32`, all via `scripts/nightly.sh`; branch
protection requires this check to pass before the merge button unlocks.
- **`build.yml`** — push to working branch: 3 board image jobs (`make boot_image TARGET=<board>`,
matrix: PC/amd64, RASPI/aarch64, MILKV/riscv64) + `v4-tests` job (`make -C v4 test`).
- **`nightly.yml`** — QEMU acceptance boots, 32-bit build, Isabelle/HOL proofs, images → Nexus.
- **`nightly-docs.yml`** — doxygen + asciidoctor-latex + texlive → Nexus.
- **`release.yml`** — triggers on `v*` tag push; full acceptance + versioned release artifacts
published to Nexus and a Gitea release created.
- **`runner-image.yml`** — builds the custom Docker runner image published to the Gitea registry.
---
@@ -383,12 +416,11 @@ ID is its XXHash64 content hash — any mutation is detectable.
execute IDENTITY (capsule code) → execute PERSONALITY (block 1 from ramdrive)
→ log parity record (VM ID + capsule hash + dict hash).
**Capsule files:** `capsules/` has 23 `.4th` files (the `mkcapsule` build tool reports "26
capsule(s)" registered — some files apparently register more than one capsule entry; not
further investigated). Includes `init.4th`, `workload-0.4th`–`workload-9.4th`,
`init-l8-{stable,volatile,diverse,temporal,transition,omni}.4th`, plus `doe.4th`,
`doe-campaign.4th`, `lib.4th`, `process.4th`, `ACL.4th`, `zuse.4th` — more than the 17 older
docs claimed.
**Capsule files:** `capsules/` has **39** `.4th` files — corrected 2026-11-10; this file said
23 (then "more than the 17 older docs claimed"). 33 live at `capsules/*.4th`; 6 in
subdirectories: `capsules/artemis/init.4th`, `capsules/hestia/init.4th`,
`capsules/v4/centre.4th`, `capsules/v4/forth79.4th`, `capsules/v4/hera.4th`,
`capsules/v4/starshipos.4th`.
Tool `tools/mkcapsule.c` assembles `.4th` files into the binary capsule directory
format (`capsule_generated.c`) baked into the kernel image; it also regenerates
@@ -434,12 +466,12 @@ status for kernel work.
`TestCase.contract`/`WordTestSuite.suite_contract` trailing field, ~3,010 instances). Fixed
in place across all 20 files (mechanical: added the missing `{0}` initializer, semantically
a no-op since C99 already zero-fills unlisted trailing fields — the fix only silences the
diagnostic). Verified clean on all three architectures. Remaining, still-open warnings as
of the same audit: 26 `-Wunused-parameter` (scattered, several files, not yet fixed), 2
`-Wsign-compare` (`control_words_test.c:127`), and 2 `-Wstringop-truncation` in
`tools/mkcapsule.c` — that last one is a separate host build tool compiled via plain `cc
-Wall -Wextra -O2` (no `-Werror` at all), never actually gated by this policy in the first
place, genuinely unfixed rather than exempted.
diagnostic). Verified clean on all three architectures. Remaining, still-open warnings: **none** (2026-11-12, #143 -- the
5 `-Wformat-truncation` in `tools/mkcapsule.c`, still open on 2026-11-10, are fixed:
same-sized name arrays copied whole, a path too long refused instead of cut) — corrected 2026-11-10; this file said 26 `-Wunused-parameter`,
2 `-Wsign-compare`, and 2 `-Wstringop-truncation` (the -Wunused-parameter and
-Wsign-compare diagnostics were resolved since that audit). `tools/mkcapsule.c` is a
host build tool compiled via plain `cc -Wall -Wextra -O2` (no `-Werror`).
- **No hidden state** — All VM state is explicit in the `VM` struct
- **Platform-agnostic** — Kernel code gated by `__STARKERNEL__` and `STARFORTH_ENABLE_VM`
- **Content-addressed immutability** — Capsule ID = content hash; any mutation is detectable
+10
View File
@@ -0,0 +1,10 @@
# Memory index — LithosAnanke (StarshipOS)
Written by Claude while reading the whole repo, started 2026-11-11 on `StarForth-v4.0.0` @ `06f1d41a`.
Read this first in any new session, then `.claude/CLAUDE.md` (which wins over anything here).
- [rules.md](rules.md) — how to work here: Captain Bob's Law, acceptance, what I got wrong on day one
- [docs-notes.md](docs-notes.md) — notes per document area, in the order read
- [code-review.md](code-review.md) — codebase review notes, per subtree
- [discrepancies.md](discrepancies.md) — where documents, tracker and code disagree (report, do not fix)
- [progress.md](progress.md) — what has been read so far and what is left
+136
View File
@@ -0,0 +1,136 @@
# Code review notes (session 1, 2026-11-11, on StarForth-v4.0.0 @ 06f1d41a)
Per Captain Bob's Law these are FINDINGS TO REPORT, not fixes. Severity is my judgement:
**H** can give wrong results or lose data in a path that runs today; **M** latent (not reached by the products
yet, or needs unusual input); **L** comments, naming, hygiene.
## v4 engine (`v4/src`) — read: exec.c, node.c, stack.[ch], fabric.c, wire.c, manage.c, heat.c
Overall: careful C99. All arithmetic in `v4_ucell` (no signed-overflow UB), D-14/D-16 guards before every
opcode, the engine is libc-free so the kernel links it unchanged. Comments state the rulings they implement.
- **M — `manage.c` pops and pushes without checking stack depth.** `v4_manage_serve()` takes 1–4 arguments
with `v4_dstack_pop()` and never checks `n->ds.depth` (contrast `v4/system/blocks.c:99`, which refuses a block
request with too few values — added after the MESH step-6 review found the same hole there). `v4_dstack_pop`
on an empty stack does not fault; it returns whatever is in the ring. So `NODE-KILL`, `NODE-WIRE`,
`NODE-SLEEP` etc. typed with too few values act on stale numbers, and the result pushes can saturate a full
stack silently. Latent today: only tests call it (products are one node, MESH steps 8–9 not built).
- **M — `1u << (V4_PORTS + k)` in `fabric.c:293` (look_about)** is undefined once `V4_PORTS > 16`; nothing
checks it at compile time. This is exactly issue #20, confirmed in code. `node.h` defaults `V4_PORTS` to 8.
- **L — stale comments, already known:** `stack.h` lines 20–30 ("no overflow detection, and there never will
be") (DATASHEET §13 item 4) and `stack.c` lines 27–30 say the same and hardcode "mod 8" though the ring size
is a build parameter (host node 30/31).
- **L — `heat.c` `call_index()` comment reads as an unfinished thought** ("hash-mod or just take low bits? Or
simply if in range use it", "ignore for now? Or clamp?"). The code is the documented D-6 stand-in, and ENGINE
step-4 Part A (A1) plans to delete `call[]`, the freeze mask and `v4_heat_on_call` — Part A not started.
Under the "no TODO-shaped comments" standing rule this comment is exactly the kind that should not stand.
- **L — `node.c` store/fetch compare against attach registers that are `-1` when detached** ("no valid address
equals"). Safe for opcode paths (addresses are checked first) but a direct C caller passing `-1` would hit the
console/stack-register branch. Only reachable from C.
- OK, checked: branch target page-relative (iword), `unext` restart without refetch, resume after blocking,
fault cancels resume, store refused by the node does not advance A/P (the 11-02 review fix `fd208825`),
wire put/take/move all-or-nothing, queue pool free list, wire cut gives queues back at both ends.
### manage.c finding — confirmed latent (2026-11-11)
`v4_manage_serve` has no caller outside `v4/tests/test_manage.c` (grep of kernel/src, v4/system, v4/tools).
`boot.c:266` serves only blocks and the kernel's word table. test_manage.c tests refusals and depth *after*,
never a request made with too few values. So: real hole, not reachable from a product today; becomes
reachable at MESH steps 8–9. A test written first (Bob's rule) would show it.
## v4 system (`v4/system`) — read: boot.c run_line request loop, post.c judge loop, blocks.c guards
- **L/M — `boot.c` run_line, DONE path:** after the text ends, `for (i < 4096u && !doing && !stopped && !asking)
boot_exec(b)` — if the node has not settled in 4096 steps the line is reported done anyway, with no sign.
Bounded, but a silent cut-off (the method's dominant failure mode). Worth a named check or a comment of why
4096 is enough.
- OK: unknown kernel request → error 12 (D-18), not ignored; port with no one → V4_ERROR_NO_ONE; step limit
→ STOPPED; POST reads the stack before judging, resets it, reports a stopped node and ends POST.
## kernel v4 path (`kernel/src/v4`) — read: sk_v4.c, sk_v4_mint.c, sk_v4_marker.c, sk_v4_grow.c, identity.c 160–320
- **M — MINT-ZUSE says "failed -- nothing changed" when something has changed.** `failed()` is called after
`gpt_write_one()` has rewritten the stick's GPT and after the first 32 Forth blocks are zeroed, so a mint
that fails at `capsule_zuse_boot_genesis_mint`/read-back/marker write has already erased the stick. The
message is false on those paths (only the size and YES refusals are truly "nothing written").
- **L — secrets left in stack memory on failure paths.** `sk_v4_mint_zuse` wipes `seed`/`rseed` only on success;
every `return failed()` after the mint leaves them. `sk_v4_genesis` (identity.c ~237) never wipes `seed`/`rseed`
at all, while `sk_v4_real_zuse_arrived` wipes `seed`. Inconsistent; the seed is also kept in `g_zuse_seed`
by design, so this is hygiene, not a leak path I can show.
- **L — fatal paths spin.** `sk_v4_run` ends in `for (;;) { }` on "not started", "did not let go of POST's
blocks" and "stopped on a fault": a 100% core spin, the thing #151 fixed at the prompt with `arch_halt()`.
- **L — `sk_v4_grow.c` `dev_rw4k`: `(uint32_t)devblock * 4u`** truncates for volumes past 4 TiB of 1 KiB blocks.
Unreachable with the 256 GiB Artemis cap (`STICK_ARTEMIS_CAP_GIB`), so latent only.
- **L — `sk_v4_serve` ignores request numbers other than 1 and 2** silently; safe because boot.c only calls it
for 1..word_count (2), but the guard lives in the caller.
- OK: marker v1/v2 read with CRC and `has_real > 1` refused; marker written only after mint read-back
(STICK.md 6 order); line editor's over-long line refused whole (not truncated and run); logout ends a
waiting line (Bob 2026-10-26); size message buffer sized right (28 bytes incl. NUL).
## kernel v4 identity, the rest (identity.c 320–657) — hot-plug, offer, fixed screen
- **L — `sk_v4_idle` reallocates `g_usb[xc].slots` when `count < max_slots + 1` without copying or freeing the
old array.** `g_offered`, `g_spare`, `g_pending_real`, `g_real_drive` and `g_zuse_dev` (= `&d->part` inside
the old array) would then point into the abandoned array. Only reachable if a controller's `max_slots` grows
after the first allocation, which it does not today — latent, plus a leak.
- **L — partial state on a failed identity attach:** in `sk_v4_drive_arrived`, Artemis is attached and
`g_stick_in = 1` before the identity partition's `blk_subsys_attach_device`; if that fails the function
returns with Artemis attached and no identity, and `d->used` unset. A later pull detaches Artemis correctly
(`art_used`), so it is recoverable; the message names xhci, not the partition.
- **Ruled, not a finding:** the fixed screen lets anyone holding the system stick press R and mint a
replacement real Zuse (STICK.md §6a, Bob 2026-10-29: "the old stick dies for good"; copying a system stick
is "not guarded against", §6a line 252).
- OK: marker cleared when the system stick leaves; a real-Zuse stick seen before the system stick is held
(`g_pending_real`) and judged when it arrives; the offered stick is never the system stick
(`sk_v4_is_this_stick`); waits use `arch_halt()` (#151).
## kernel/src/gpt.c
- Sound overall: header CRC, entry-array CRC, `my_lba == 1`, entries inside the usable range, entry array before
first_usable and 1 KiB-aligned; writes go backup first, then primary, then the protective MBR last, with
flushes between, so a power cut leaves one valid table. `gpt_write_one` zeroes the MBR first.
- **L — `gpt_read` stops validating at `max` entries:** `for (i < nent && n < max)` — with `max = 4`
(`sk_v4_mint_zuse`) or `SK_V4_GPT_PARTS`, a disk whose identity/Artemis entry is past the first `max` used
entries reads as having none, and the entries after `max` are not range-checked. Harmless for this
system's own sticks (one or two partitions); worth knowing for foreign disks.
- **L — no backup-header fallback:** a damaged primary GPT returns GPT_BAD ("damaged partition table -- not
used") though the backup may be good. A choice, not a bug; the message is honest.
- **L — 32-bit fblock arithmetic** (`(uint32_t)(ent_lba / 2u) + i`, `st->first_fblock`): bounded by
`total_blocks` (uint32 of 1 KiB = 4 TiB), consistent with the block layer.
## kernel/src/usb (xhci.c descriptor walk, blkio_usb.c, usb_kbd.c)
- OK: device-controlled lengths are clamped — `xhci_ep0_get_config_descriptor` clamps the request to the
128-byte buffer, every descriptor walk checks `off + field < len` and breaks on `bLength == 0`; HID packet
capped at 64; keyboard report capped at 8 bytes, usage lookup bounds-checked; SCSI block size must divide
1 KiB, capacity saturates at 2^32 Forth blocks.
- **L/M — a device whose `wTotalLength <= 9` loops enumeration:** the second GET_DESCRIPTOR is again classed
`XHCI_XFER_CONFIG_DESC_SHORT` (`length <= 9`), whose handler asks again for `total_len` — for ever, for that
slot. A hostile or broken device only; `wTotalLength = 0` also issues a zero-length data stage.
- **L — config descriptors longer than 128 bytes are cut at 128.** Interfaces past byte 128 are never seen.
BOT is normally the first interface and a boot keyboard is small, so QEMU never shows it; a composite
device on real hardware (SER5 bring-up) could. No message says the descriptor was cut.
## scripts/nightly.sh, scripts/qemu_session.py, .gitea/workflows/acceptance.yml
- OK: `set -euo pipefail`, so a failing `qemu_session.py` or `make test-32` behind `| tee` fails the stage;
`POST: PASSED` is printed by `v4/system/boot.c` only when `v4_post_run` reported no failures, after the
`PARITY:V4_SYSTEM` line; one QEMU at a time via the shared `qemu` concurrency group;
`git checkout -- disk/zuse-scratch` before each architecture.
- **L — the dict_hash agreement check is two-of-three tolerant:** the stick-high stage collects hashes with
`sort -u` and passes if exactly one distinct value appears. An architecture whose log has no
`PARITY:V4_SYSTEM` line (or whose `LOG:` line is missing) contributes nothing and the check still passes.
Today each arch's own stage would have failed first (no POST: PASSED), so it is belt without braces: count
three hashes, not one distinct value.
- **L — the POST test count is not asserted.** The harness checks `POST: PASSED` (and `fail=0` only in the
`stick_v3` mode); a POST that lost cases would still pass. CLAUDE.md says "tests=538 (the count grows)", so
this is policy, but a floor would catch a silently shrinking POST.
- **L — acceptance without `CAPSULE_SIGN_KEY` runs unsigned with a warning, and passes.** Fine for a fork;
for the gate into `master` an unsigned pass may not be what is meant.
## Not yet reviewed (honest)
kernel_main.c (1986 lines) and repl.c (the v3 path), hal, the UEFI loader, virtio, the block subsystem
(`block_subsystem.c`), capsule_zuse_boot / homeblocks_sig / artemis_sig, v4/system/post_cases.c, text.c,
image.c, v4/tools (mkrom, mkmap, hosted), capsules/v4/*.4th, tools/mkcapsule.c beyond the #143 warnings,
qemu_session.py modes other than zuse/stick_genesis, build/nightly/release workflows, Makefiles, v3.
## Filed as issues (2026-11-11, Captain Bob: "File the review findings as issues")
#168 MINT-ZUSE "nothing changed" (should) · #169 manage.c depth (should) · #170 USB wTotalLength<=9 loop (should) ·
#171 USB descriptor >128 cut (should) · #172 dict_hash two-of-three (should) · #173 POST count not asserted ·
#174 unsigned passes · #175 boot.c 4096-step cut-off · #176 seeds not wiped · #177 fatal spins ·
#178 sk_v4_idle realloc · #179 half-attached stick · #180 gpt_read max · #181 stale comments (heat.c, stack.[ch]) ·
#182 latent 32-bit block casts · #183 BLOCK_MAP Signed column. Not filed: fabric.c 1u<<(V4_PORTS+k) -- already #20;
node.c detached attach registers (-1) and sk_v4_serve's silent unknown requests -- C-only, guarded by the caller.
All labelled status/backlog, no milestone: Captain Bob places them.
+35
View File
@@ -0,0 +1,35 @@
# Discrepancies found (report to Captain Bob; do not fix unless asked)
Format: what disagrees → where → which side the code/authority supports.
## Documents vs documents
1. `README.md` says v4 `word_count=317 dict_hash=0xfec8c47cfc6f437f`; `.claude/CLAUDE.md` (working branch, after
c32bc43e) says 318 / `0x8c92508f748f99cf` (since `MINT-ZUSE`, 2026-11-08). README is behind.
2. `.claude/README.md` calls TRIPOD/HERMES/ARTEMIS.md "binding constraints"; `.claude/CLAUDE.md` says they are
frozen history. It also omits CONSOLE.md.
3. `CONTRIBUTING.md` is StarForth-era: `make test`, 780+ tests, feature branches, `hal_*` headers,
`docs/02-experiments/`, "security contact TBD". Contradicts CLAUDE.md throughout.
4. `docs/DEAD-AND-REVISED.md` "Revised" table still gives kernel version as 2.1.0 and parity 526 words as
"is"; current is 4.0.0-alpha.4 and v4's 318 (v3's 526 still true for `system=v3`).
5. `docs/CLAUDE.md` describes a triage "mission" that was carried out 2026-10-14; `.claude/README.md` calls
`docs/CLAUDE.md` "an older, hosted-only snapshot", which is not what it is.
6. `DECOMPOSITION.md` cites `v4/capsule/*.v4` paths throughout; since MACHINE.md (2026-10-15) the sources are
`.f18` blobs under `capsules/v4/sys/`. Its §6.1 packet format and four-port text are superseded by MESH.md.
7. `NUCLEUS.md` §3 (extensions out of scope) is contradicted by V3-PARITY's ruling; the file says so itself.
8. `kernel/src/kernel_main.c` header says "M7: Not started" (issue #144; CLAUDE.md flags it).
## Practice vs configuration
9. LFS: `.gitattributes` routes `*.log` and DoE `.csv` through LFS, but the step plans instruct committing
with the LFS clean filter disabled. Result: logs committed as plain text, every fresh clone shows them
modified. Fixed once by Bob's side (`027b144e`, FABRIC-3 §XLV.2, 1,003 files) and again by me
(`06f1d41a`, 146 files, 2026-11-11). It will recur until either the plans' commit command or
`.gitattributes` changes. Also: 3,944 LFS objects from the 2026-08-01 initial commit are 404 on the server.
## Tracker vs tree (audit of 2026-11-11, by grep/compile, NOT by the acceptance protocol)
10. Open and confirmed still open in code: #141 (1,332 empty DoE CSVs tracked), #143 (5 warnings in
`tools/mkcapsule.c`), #144, #145 (`capsules/BLOCK_MAP.md`, `v3/include/version.h` tracked and regenerated),
#140 (one `qemu` concurrency group), #20 (no compile-time `V4_PORTS` ≤ 16 check), #25 (LaTeX output in docs/).
11. #137 fixed on the working branch (c32bc43e), waiting in PR 164.
12. Milestones: `v4.0.0-alpha.4` and `Public demo terminal` open with 0 open issues;
`Fleet, identity and the DoE` closed with #51, #58, #60 open.
13. Gitea ROOT_URL is `gitea.starshipos-f18.com`; clone URL in use is `.org` (#133 closed).
File diff suppressed because it is too large Load Diff
+30
View File
@@ -0,0 +1,30 @@
# Reading progress (update after every batch)
Session 1, 2026-11-11. Per-read cap ~25k tokens; large files in 400–700 line pages.
## Documents — DONE in full
.claude/CLAUDE.md, .claude/README.md, docs/CLAUDE.md, docs/README.md, docs/DEAD-AND-REVISED.md, README.md,
CONTRIBUTING.md, CHANGELOG.md; docs/v4.0.0/{JUSTIFICATION, ENGINE, NUCLEUS, MACHINE, DATASHEET-F18, STICK,
V3-PARITY, DECOMPOSITION, MESH, POST79}; plans {engine-step4, identity-gate, stick-4, stick-5, alpha4-documents};
docs/fabric/FABRIC-3.md (all 6,515 lines), FABRIC-3.7, FABRIC-4; docs/reference/{ROADMAP, M7.1, word-acl/DESIGN,
kernel-args/DESIGN, hosted-acceptance-test}; boards/BRINGUP.md + all board READMEs; v4/README.md;
experiments/bare_metal/{README, CLAUDE}; disk/README.md; proof/{COVERAGE, FINDINGS}; capsules/README.md;
kernel/src/hal/README.md; docs/working/README.md; docs/formal/CLAUDE.md (first 80 lines).
## Documents — PARTIAL (structure + key sections)
FABRIC-3.5 (§XV, §XXII, §XXXV full), FABRIC-3.6 (handoff, rules, findings full), FABRIC-0 (§1–15 full),
FABRIC-1, FABRIC-2 (§C full), docs/INDEX.md (skimmed).
## Documents — SURVEYED only (not read file by file)
docs/working/** (253), docs/formal/** (255), docs/patent/** (43, legal hold), experiments/** analysis,
.claude/{TRIPOD,HERMES,ARTEMIS,CONSOLE}.md (frozen), capsules/MANIFEST*.md, BLOCK_MAP.md, remaining 11 plans,
docs/reference/{DICTIONARY, STARFORTH_PRIMITIVES, ONTOLOGY, L8_ADAPTIVE_CONFIG_TABLE}.
## Code review — NEXT
v4/ (engine, system, tools, tests) → kernel/src/v4 → kernel/src core (boot, arch, usb, gpt, hal) →
capsules/v4 → tools/mkcapsule.c → scripts/ (nightly.sh, qemu_session.py) → .gitea/workflows → Makefiles → v3 (light).
## Code review status (2026-11-11, end of session 1 pass)
Reviewed: v4/src (all engine files), v4/system boot.c request loop + post.c + blocks.c guards,
kernel/src/v4 (sk_v4.c, mint, marker, grow, identity 160–320). Findings in code-review.md.
Remaining list at the bottom of code-review.md.
+142
View File
@@ -0,0 +1,142 @@
# How to work in this repo
## READ FIRST — rules I have broken in front of Captain Bob (2026-11-11)
1. **NEVER run an acceptance test in the background. EVER.** (Bob: "You are NOT to run acceptance tests in
background EVER!") No `run_in_background`, no `&`, no detached loop, no "it might outlast the tool timeout".
One stage per foreground command, read its result, then the next. I broke this twice on 2026-11-11.
2. **Before doing anything, check it against CLAUDE.md, not just before the session.** Having read a rule is
not following it. I had summarised the foreground rule to Bob and broke it anyway.
3. Every log and every CSV is evidence and is committed — passing, failing, stopped.
4. Never create a branch, never stash, never fix unasked, never push without Bob saying push.
5. **When something comes up -- a missing tool, a surprise, anything not in the plan -- STOP AND ASK
before acting.** (Bob, 2026-11-12: "you are supposed to stop and ask when something comes up ... What
if I had missed that message?") I installed qemu-user unasked when hosted-check could not find
qemu-aarch64, and only said so afterwards, in a summary. Telling him after is not asking him first.
6. **Every foreground boot command is wrapped in `timeout 570`.** A boot that hangs past the tool's
10-minute limit is moved to the background by the tool -- an acceptance run in the background,
against rule 1. It happened 2026-11-13 (a v4 boot that stopped after POST); QEMU was stopped at
once with SIGTERM. `timeout` ends it in the foreground instead.
Source of authority: `.claude/CLAUDE.md` (wins), then the FABRIC record (`docs/fabric/`, FABRIC-3 living),
then `docs/v4.0.0/`, `docs/reference/ROADMAP.md`, `boards/BRINGUP.md`. Code wins over all documents.
## The Captain Bob method (the user may call it "Bulldozer"; that word is not in the tree)
- Owner: Robert A. James, "Captain Bob". Neither agile nor waterfall. One gate: the acceptance protocol.
What a developer runs by hand, what a PR into `master` runs, and what the nightly runs are the same thing
(`scripts/nightly.sh` stages).
- Subversion-like: commit and push straight to the working branch (`StarForth-v4.0.0`). No side branches.
- NEVER create a branch without explicit permission (every time, not once per session).
- NEVER stash without explicit permission. Dirty tree: report and wait.
- NEVER apply a fix that was not explicitly requested. Find a bug: report it.
- `master` only through a PR that passed acceptance. Never push to it, never merge around the gate.
- After any out-of-branch work: return to the working branch, fetch + pull.
- Always start clean: check `git status` and the branch before work.
- Announce the branch and last commit as the first line after a session resumes.
- When told to stop, stop at once. No "one more change".
- Show the plan and wait for yes before destructive operations.
- Do not over-engineer. Compose in FORTH first; new C words only for hardware, atomics, freestanding ops.
- Tags are sacred: each has logs proving its state. `git show <tag>` is the oracle.
- Never delete docs without Bob's confirmation; `git mv`, never `mv`; legal/patent dirs are on hold: ask first.
- Never rename Bob's terms (James Law, SSM, Uberkernel, Hades, Jacquard Selector).
- `logs/` are committed audit artifacts. Never delete them.
## Acceptance (the only test)
In this order, one QEMU at a time, foreground, always `clean` first:
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
make -C v4 test-32
Pass = each boots to `[zuse@Hera] ok> `, `PARITY:V4_POST tests=N pass=N fail=0`, `POST: PASSED`,
`PARITY:V4_SYSTEM ... dict_hash=` equal on all three; stick-high the same; test-32 `0 failures`.
v3 is not part of acceptance. There is no `make test`. Hosted `make` is compile sanity only.
`git checkout -- disk/zuse-scratch` before each architecture.
## FORTH / capsule rules
- BIRTH, RUN, USE are C primitives. FIND is non-standard on purpose. Never modify a registered, tested word.
- ACL policy lives in `capsules/ACL.4th`; only kernel-only words (BIRTH, CAPSULE-BIRTH) are pinned in C.
- Read `experiments/bare_metal/README.md` before touching any `.4th`. Block ranges: 2048–2099 init.4th,
2100–2199 doe.4th, 3000–3999 workloads, 4000+ user capsules. Format: ≤64 chars × ≤16 lines per block,
block ≥ 2048. Check with `mkcapsule --lint capsules/`.
- `INPUT_BUFFER_SIZE` must be 1025.
- Capsule wiring belongs in `sk_vm_bootstrap.c`, not `kernel_main.c`.
## What I got wrong in the first session (2026-11-11) — do not repeat
- Did not read `.claude/CLAUDE.md` before acting.
- Created and deleted a branch (`claude/test-push`) on the remote for a "test push". Branch creation needs
explicit permission; a test push should have been discussed first.
- Tried to merge PR 164 into `master` through the API. Master is reached only by the acceptance gate.
- Judged issues "done / not done" with my own greps instead of the acceptance protocol and the issue's
own "Done when" list.
- Pushed commit `06f1d41a` (LFS renormalise of 146 logs) to the working branch. That one was requested
("Repair the LFS problem"), but note #152: while a PR is open, commit locally and push once.
## Session environment facts
- Remote: `https://gitea.starshipos-f18.org/rajames/LithosAnanke.git`. Gitea's ROOT_URL says `.com`.
- Pushing from a cloud session needs the proxy-injected credential:
`git -c credential.helper='!f(){ echo username=proxy; echo password=proxy-injected; }; f' push ...`
- Gitea API writes (merge, milestones, comments) are blocked by the session's safety classifier.
- 3,944 LFS pointers (mostly `docs/working/` PDFs and data, from the 2026-08-01 initial commit) have no
object on the server (404). `GIT_LFS_SKIP_SMUDGE=1` avoids the noise.
## More rules found in the record (FABRIC-0/2/3/3.5/3.6)
- No stubs or TODOs, ever ("I've never allowed stubs before"). Each increment a complete, real slice.
- Never stub, simulate or develop outside functional, as-intended code ("Piecemeal is how errors and intent
get hidden").
- Name, BEFORE running, the observation that proves a step worked; a green boot is weak evidence.
- Capture a three-ISA baseline before changing anything.
- dict_hash changing is expected; diverging across ISAs is the stop condition.
- Never establish capsule reachability by grep alone; DoE/experiment capsules are live by default.
- Strip dead code first, in its own commit and boot, then code.
- FORTH addresses in C words go through `vm_ptr()`/`VM_ADDR()`.
- Use `ucell_t`/`cell_t`, never bare `long`, for cell arithmetic (32-bit `long` on the aarch64 target).
- New console/log lines ≤ 63 chars; interactive replies to console, the rest through `log_message()`.
- Never assume a running qemu is an orphan; one QEMU at a time; stop with SIGTERM to qemu itself.
- Read the whole of v3's code before telling Bob what v3 does (rulings have been made on false readings).
- Record corrections in place, dated, struck not deleted.
## Learned 2026-11-11 (later the same day)
- **Acceptance runs in the FOREGROUND, one stage per command, check each result before the next.** I first ran
the stages with run_in_background and had to stop that run (its log, 20261111-170544, is kept). A stage takes
~2 min here (amd64 build+boot), well inside the 10-minute foreground limit. Use `scripts/nightly.sh accept
<amd64|aarch64|riscv64|stick-high>` then `scripts/nightly.sh test-32` -- the same stages the PR gate runs.
- **Every log and every CSV is evidence and is committed** (Bob: "We track all logs and all CSV's always as
evidence") -- passing, failing, stopped runs alike. Commit them together after the run, not mid-run.
- Empty DoE CSVs (0 bytes) are normal for v4 acceptance boots and are stored as empty files, not LFS pointers.
- Toolchain for acceptance: `make ARCH=amd64,aarch64,riscv64 init INIT_DOCS=0 INIT_PROOFS=0` (the repo's own).
- Clean tree: since 90c5c140 a build changes no tracked file (version.h untracked; BLOCK_MAP.md has no
timestamp). A *signed* build still rewrites BLOCK_MAP.md's Signed column -- open, Bob's call.
## The developer protocol (#135, built 2026-11-12)
- `scripts/nightly.sh protocol <stage>` one stage per foreground command (accept-amd64 begins it), then
`protocol-report` -> logs/<TS>/PROTOCOL.md; commit logs/ + experiments/bare_metal/runs/; the PR's gate runs
`scripts/check_protocol.sh` on the head first.
- **Strict, ruled** (Bob 2026-11-12: "Keep it strict"): ANY change outside logs/ and the DoE CSVs after the run --
documents and notes included -- makes the evidence stale and needs a full protocol rerun. So batch docs/notes
commits and push them with the next protocol, not one by one. Hold commits that would stale an open PR.
- The docs stage takes ~30 min here (the API reference); it outlasts the foreground limit and the tool
moves it to the background (not an acceptance boot; no QEMU). Proofs need the HOL-Library heap
(ci/runner-image's URL, checksum in its Dockerfile).
## Releasing (Captain Bob, 2026-11-12)
Order for alpha.5 and after: the protocol on everything -> push (on his word) -> merge the PR through the gate ->
move what is left to the next milestone -> the release commit (version, CHANGELOG, README together, as
93828e0e did for alpha.4) -> **the documentation review, the very last thing before the tag**: README.md,
CHANGELOG.md, .claude/CLAUDE.md, docs/README.md, docs/INDEX.md, FABRIC-3, boards/BRINGUP.md, the plans --
every claim, count and issue reference checked against the tree and the tracker as they then are, shown to
him -> the tag, on his word.
- The gate refuses unsigned builds (#174); a protocol run here is unsigned -- the gate's signing is CI's.
- POST's floor is v4/system/POST_FLOOR (#173): raise it when POST grows; never lower it without him.
- Kernel host tests: make -C kernel/tests test (docs/v4.0.0/plans/2026-11-12-kernel-host-tests.md).
- **alpha.5 is closed to new work** (Captain Bob, 2026-11-13: "Don't let me add anything else to this
milestone."). What it holds now is all it gets: #189 (the blocker), #191, #192, #193 and what was already in it.
If he proposes another item for alpha.5, remind him of this ruling and offer the next milestone; only his
explicit word that he is overriding it reopens it.
+4 -1
View File
@@ -10,7 +10,10 @@ The **Acceptance** check runs on this pull request by itself -- amd64, aarch64,
stick loaded high, test-32 -- and `master` takes nothing that has not passed it. Note here
anything it does not cover:
- [ ] Logs from runs made by hand are committed in `logs/`, if any
- [ ] `logs/<TS>/PROTOCOL.md` for the head commit: `scripts/nightly.sh protocol`, run by hand,
its `logs/` and `experiments/bare_metal/runs/` committed (#135). The check refuses a head
without one, or with one for another tree.
- [ ] Logs from other runs made by hand are committed in `logs/`, if any
- [ ] Hardware this was tried on, if any:
## The record
+16 -5
View File
@@ -17,16 +17,18 @@ on:
types: [opened, synchronize, reopened]
workflow_dispatch:
concurrency:
group: qemu # one QEMU at a time on the runner: shared with nightly.yml and release.yml
cancel-in-progress: false
# No concurrency group (Captain Bob, 2026-11-11, #140: "It should be global"). The one runner
# (starshipos-vps) has capacity 1, so every job of every workflow waits its turn in Gitea's queue
# and none is cancelled; a runner-image rebuild still blocks the rest (2026-11-07). A shared
# concurrency group kept only one waiting run, and each run that joined cancelled it.
# The capacity is explicit in the runner's config.yaml: runner.capacity: 1 (FABRIC-3, 2026-11-11).
jobs:
acceptance:
name: Acceptance
runs-on: ubuntu-latest
container:
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:72b6cf370db1 # ci/runner-image (#120)
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:4f675c8b75b2 # ci/runner-image (#120)
credentials: # the registry refuses anonymous pulls
username: rajames
password: ${{ secrets.PACKAGES_TOKEN }}
@@ -37,6 +39,14 @@ jobs:
fetch-depth: 0 # the SBOM's version is git describe
lfs: false # only the logs and DoE CSVs are in LFS; the build needs neither
# The developer protocol's evidence first (#135): the PR's head carries a passing
# logs/<TS>/PROTOCOL.md for its own tree (scripts/nightly.sh protocol, run by hand), or it is
# refused here, before the boots. The head, not the merge commit the checkout made.
- name: The developer protocol's evidence
run: scripts/check_protocol.sh "${{ github.event.pull_request.head.sha || 'HEAD' }}"
# The gate into master refuses an unsigned build (#174; Captain Bob, 2026-11-12: "Yes, reject
# unsigned builds"). It warned and went on. scripts/test_acceptance_signing.sh runs this step.
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
@@ -46,7 +56,8 @@ jobs:
(umask 077; printf '%s\n' "$KEY" > "$f")
echo "SIGN_KEY=$f" >> "$GITHUB_ENV"; echo "The capsules will be signed."
else
echo "::warning::No CAPSULE_SIGN_KEY secret: the capsules are built unsigned."
echo "::error::No CAPSULE_SIGN_KEY secret: the gate into master does not accept an unsigned build."
exit 1
fi
- name: Acceptance amd64
+10 -2
View File
@@ -9,14 +9,22 @@ name: Build
on:
push:
branches: [StarForth-v4.0.0] # not master: what reaches it has just passed acceptance (#119)
paths-ignore: ['site/**'] # the websites (site/) build nothing here; each run is ~17 min on
# the server the wikis share (Captain Bob, 2026-11-07)
workflow_dispatch:
# No concurrency group (Captain Bob, 2026-11-11, #140: "It should be global"). The one runner
# (starshipos-vps) has capacity 1, so every job of every workflow waits its turn in Gitea's queue
# and none is cancelled; a runner-image rebuild still blocks the rest (2026-11-07). A shared
# concurrency group kept only one waiting run, and each run that joined cancelled it.
# The capacity is explicit in the runner's config.yaml: runner.capacity: 1 (FABRIC-3, 2026-11-11).
jobs:
image:
name: Image ${{ matrix.board }}
runs-on: ubuntu-latest
container:
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:72b6cf370db1 # ci/runner-image (#120)
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:4f675c8b75b2 # ci/runner-image (#120)
credentials: # the registry refuses anonymous pulls
username: rajames
password: ${{ secrets.PACKAGES_TOKEN }}
@@ -64,7 +72,7 @@ jobs:
name: v4 tests (32- and 64-bit cells)
runs-on: ubuntu-latest
container:
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:72b6cf370db1 # ci/runner-image (#120)
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:4f675c8b75b2 # ci/runner-image (#120)
credentials: # the registry refuses anonymous pulls
username: rajames
password: ${{ secrets.PACKAGES_TOKEN }}
+7 -1
View File
@@ -14,12 +14,18 @@ on:
- cron: '0 4 * * *' # 04:00 UTC, after the images (nightly.yml, 03:00)
workflow_dispatch:
# No concurrency group (Captain Bob, 2026-11-11, #140: "It should be global"). The one runner
# (starshipos-vps) has capacity 1, so every job of every workflow waits its turn in Gitea's queue
# and none is cancelled; a runner-image rebuild still blocks the rest (2026-11-07). A shared
# concurrency group kept only one waiting run, and each run that joined cancelled it.
# The capacity is explicit in the runner's config.yaml: runner.capacity: 1 (FABRIC-3, 2026-11-11).
jobs:
docs:
name: Book, volumes, API reference
runs-on: ubuntu-latest
container:
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:72b6cf370db1 # ci/runner-image (#120)
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:4f675c8b75b2 # ci/runner-image (#120)
credentials: # the registry refuses anonymous pulls
username: rajames
password: ${{ secrets.PACKAGES_TOKEN }}
+19 -6
View File
@@ -1,11 +1,13 @@
# Nightly snapshot of the kernel images: the acceptance protocol, the board images, Nexus, then
# the proofs. Each stage is a step of scripts/nightly.sh (its header says what each does); any
# v4 under the sanitizers with the hosted builds (#16), and the proofs. Each stage is a step of scripts/nightly.sh (its header says what each does); any
# failure stops the run, and nothing is published unless every stage before it passed. The proofs
# come last and run whatever happened before them: they check the theories, not the images, so a
# failed proof does not hold back images that passed acceptance -- it turns the run red.
# failed proof does not hold back images that passed acceptance -- it turns the run red. The v4
# checks (#16; Captain Bob, 2026-11-13: "Nightly") are the same: the engine on the host, not the images.
#
# 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
@@ -19,16 +21,18 @@ on:
- cron: '0 3 * * *' # 03:00 UTC; the documents are at 04:00 (nightly-docs.yml)
workflow_dispatch:
concurrency:
group: qemu # one QEMU at a time on the runner: shared with acceptance.yml
cancel-in-progress: false
# No concurrency group (Captain Bob, 2026-11-11, #140: "It should be global"). The one runner
# (starshipos-vps) has capacity 1, so every job of every workflow waits its turn in Gitea's queue
# and none is cancelled; a runner-image rebuild still blocks the rest (2026-11-07). A shared
# concurrency group kept only one waiting run, and each run that joined cancelled it.
# The capacity is explicit in the runner's config.yaml: runner.capacity: 1 (FABRIC-3, 2026-11-11).
jobs:
nightly:
name: Acceptance, images, proofs
runs-on: ubuntu-latest
container:
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:72b6cf370db1 # ci/runner-image (#120)
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:4f675c8b75b2 # ci/runner-image (#120)
credentials: # the registry refuses anonymous pulls
username: rajames
password: ${{ secrets.PACKAGES_TOKEN }}
@@ -77,6 +81,15 @@ jobs:
name: kernel-images-${{ github.run_number }}
path: build/nightly/
- name: v4 under the sanitizers, and the hosted builds alike
if: always()
run: | # hosted-check runs aarch64 and riscv64 under qemu-user (#16)
if ! command -v qemu-aarch64 >/dev/null || ! command -v qemu-riscv64 >/dev/null; then
S=$([ "$(id -u)" = 0 ] || echo sudo)
$S apt-get update -qq && $S env DEBIAN_FRONTEND=noninteractive apt-get install -y -qq qemu-user
fi
scripts/nightly.sh v4-checks
- name: Isabelle/HOL proofs
if: always()
run: scripts/nightly.sh proofs
+26 -7
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
@@ -13,16 +18,18 @@ on:
push:
tags: ['v*']
concurrency:
group: qemu # one QEMU at a time on the runner: shared with acceptance.yml
cancel-in-progress: false
# No concurrency group (Captain Bob, 2026-11-11, #140: "It should be global"). The one runner
# (starshipos-vps) has capacity 1, so every job of every workflow waits its turn in Gitea's queue
# and none is cancelled; a runner-image rebuild still blocks the rest (2026-11-07). A shared
# concurrency group kept only one waiting run, and each run that joined cancelled it.
# The capacity is explicit in the runner's config.yaml: runner.capacity: 1 (FABRIC-3, 2026-11-11).
jobs:
release:
name: Release ${{ github.ref_name }}
runs-on: ubuntu-latest
container:
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:72b6cf370db1 # ci/runner-image (#120)
image: gitea.starshipos-f18.org/rajames/lithosananke-runner:4f675c8b75b2 # ci/runner-image (#120)
credentials: # the registry refuses anonymous pulls
username: rajames
password: ${{ secrets.PACKAGES_TOKEN }}
@@ -33,6 +40,9 @@ jobs:
fetch-depth: 0
lfs: false
# A release refuses an unsigned build (Captain Bob, 2026-11-12: "release MUST refuse unsigned
# builds"), as the gate into master does (#174). It warned and went on.
# scripts/test_acceptance_signing.sh runs this step.
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
@@ -42,7 +52,8 @@ jobs:
(umask 077; printf '%s\n' "$KEY" > "$f")
echo "SIGN_KEY=$f" >> "$GITHUB_ENV"; echo "The capsules will be signed."
else
echo "::warning::No CAPSULE_SIGN_KEY secret: the capsules are built unsigned."
echo "::error::No CAPSULE_SIGN_KEY secret: a release is not built unsigned."
exit 1
fi
- name: The tag names the tree's version
@@ -53,7 +64,10 @@ jobs:
echo "NIGHTLY_VERSION=${tree#v}" >> "$GITHUB_ENV"
- name: Install the dependencies
run: make ARCH=amd64,aarch64,riscv64 init # the image has all but the documents' packages
# INIT_PROOFS=0: the image's Isabelle has HOL-Library prebuilt; a full init would fetch a fresh
# Isabelle into the workspace and point isabelle at it, and the proofs would build HOL-Library
# from scratch -- killed (release run 196, v4.0.0-alpha.1)
run: make ARCH=amd64,aarch64,riscv64 init INIT_PROOFS=0 # the image has all but the documents' packages
- name: Acceptance amd64
run: scripts/nightly.sh accept amd64
@@ -80,6 +94,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:
+9 -1
View File
@@ -17,6 +17,12 @@ on:
paths: ['ci/runner-image/**', 'Makefile']
workflow_dispatch:
# No concurrency group (Captain Bob, 2026-11-11, #140: "It should be global"). The one runner
# (starshipos-vps) has capacity 1, so every job of every workflow waits its turn in Gitea's queue
# and none is cancelled; a runner-image rebuild still blocks the rest (2026-11-07). A shared
# concurrency group kept only one waiting run, and each run that joined cancelled it.
# The capacity is explicit in the runner's config.yaml: runner.capacity: 1 (FABRIC-3, 2026-11-11).
jobs:
image:
name: Build and publish the runner image
@@ -44,7 +50,9 @@ jobs:
tag=$(git rev-parse --short=12 HEAD)
ctx=$(mktemp -d) # not the repository: 7 GB of context
cp -r Makefile boards ci/runner-image/Dockerfile "$ctx/"
docker build -t "$img:$tag" "$ctx"
tok=$(mktemp); printf '%s' "$TOKEN" > "$tok" # the HOL-Library heap's download (Dockerfile)
docker build --secret id=pkgtoken,src="$tok" -t "$img:$tag" "$ctx"
rm -f "$tok"
echo "$TOKEN" | docker login gitea.starshipos-f18.org -u rajames --password-stdin
docker push "$img:$tag"
echo "Published $img:$tag"
+2 -1
View File
@@ -16,7 +16,8 @@ docs/api/
*.iml
# generated headers
include/version.h
# v3/include/version.h is written by every build (kernel/Makefile, v3/Makefile): untracked 2026-11-11
v3/include/version.h
# bundles / archives
*.bundle
+6
View File
File diff suppressed because one or more lines are too long
+33
View File
@@ -1,5 +1,38 @@
# Changelog
## 2026-11-10 — LithosAnanke v4.0.0-alpha.4: the plug-and-play stick
The plug-and-play stick (#92), the BAM flush (#155), the Book of Fabric (#138), the Dictionary of v4 (#157), and the .com’s Downloads and Documents pages (#126, #161).
## 2026-11-07 — LithosAnanke v4.0.0-alpha.3: the first published alpha
`v4.0.0-alpha.2` (`2d43db25`) used the image's HOL-Library as intended, but its release run (200) ran
the proofs with Isabelle's defaults -- Java's heap up to 4 GiB, a thread per CPU -- and they were
killed in the StarForth session. Nothing was published; the tag stays where it is. The proofs now run
capped (`scripts/nightly.sh proofs`: one thread, Java 512 MiB, Poly/ML 900 MiB; 47 s, ~1.8 GiB), and
`v4.0.0-alpha.3` is the first alpha published. `docs/fabric/FABRIC-3.md` XLVII.6.
## 2026-11-07 — LithosAnanke v4.0.0-alpha.2: not published
`v4.0.0-alpha.1` (`233025da`) was accepted and tagged, but its release run (196) built HOL-Library
from scratch in the proofs step and was killed: `release.yml`'s full `make init` replaced the
image's Isabelle, the one with HOL-Library prebuilt. Nothing was published; the tag stays where it is
(Captain Bob, 2026-11-07). `release.yml` now runs `init INIT_PROOFS=0`, and `v4.0.0-alpha.2` is the
first alpha published -- the same system as below. `docs/fabric/FABRIC-3.md` XLVII.5.
## 2026-11-07 — LithosAnanke v4.0.0-alpha.1: the first alpha release
The first alpha of the kernel, `v4.0.0-alpha.1`: v4, StarForth's F18 engine, is the system every
board boots by default, with v3 a boot argument away. The kernel's version goes from 2.1.0 to the
4.x working line (Captain Bob, 2026-11-07); the engine stays 3.2.0. Accepted in full before the tag:
amd64, aarch64 and riscv64 to `[zuse@Hera] ok>` with POST 538/538 and one `dict_hash`
(`0xfec8c47cfc6f437f`), the PC stick loaded high, `test-32` (39 programs, 0 failures), and the
Isabelle/HOL proofs. An alpha: the v4.0.0 milestone's own definition -- parity with v3's vocabulary,
K=1.0 measured on v4, the hosted mesh, Verilator -- is still open, and the capsules are unsigned until
the StarshipOS CA is made (FABRIC-3.md XLVI). Also today: CI in a prebuilt runner image, the
nightly's proofs no longer able to hold back its images, and the .com and .org websites. Full record:
`docs/fabric/FABRIC-3.md` XLVII.
## 2026-11-07 — CI jobs start ready: the runner image
The CI jobs now run in `lithosananke-runner` (`ci/runner-image`, #120), an image with everything
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
mainmenu "StarForth Configuration"
source "Kconfig.arch"
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
menu "Target architecture"
choice
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
menu "Heartbeat / adaptive tick coordinator"
config HEARTBEAT_THREAD_ENABLED
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
menu "Kernel-only options"
if STARFORTH_VARIANT_KERNEL
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
menu "Physics engine tuning"
config STRICT_PTR
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
menu "Build variant"
choice
+15 -2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
# ==============================================================================
# LithosAnanke / StarForth -- top-level Makefile
#
@@ -76,7 +78,7 @@ BOARD_DIR := $(if $(TARGET),$(BOARD_DIR_$(TARGET)))
SUBMAKE := $(MAKE) --no-print-directory
.DEFAULT_GOAL := all
.PHONY: all boot_image boot_images write_stick docs clean clean-docs kernel boards help help-hosted sbom sbom-board \
.PHONY: all boot_image boot_images write_stick docs fabric dictionary clean clean-docs kernel boards help help-hosted sbom sbom-board \
qemu qemu-esp qemu-gdb init
# ARCH given on the command line and no TARGET: `clean` is the kernel's for that
@@ -201,6 +203,14 @@ docs:
fi
@$(SUBMAKE) -f docs/book/Makefile BOARD=$(BOARD_DIR) BOARD_NAME=$(TARGET)
# fabric -- The Book of Fabric (#138): build/docs/BookOfFabric.pdf
fabric:
@$(SUBMAKE) -f docs/book/Makefile fabric
# dictionary -- The Dictionary of v4 (#157): build/docs/Dictionary.pdf
dictionary:
@$(SUBMAKE) -f docs/book/Makefile dictionary
clean-docs:
rm -rf build/docs
@@ -263,8 +273,11 @@ write_stick:
# first, the nightly documents the second (scripts/nightly.sh).
INIT_DOCS ?= 1
INIT_PROOFS ?= 1
# qemu-user: `make -C v4 hosted-check` runs the aarch64 and riscv64 hosted builds under it
# (qemu-aarch64, qemu-riscv64; Captain Bob, 2026-11-12: "Add to make init now").
INIT_COMMON := build-essential make git git-lfs python3 curl ca-certificates xz-utils \
xorriso mtools gdisk dosfstools fdisk
xorriso mtools gdisk dosfstools fdisk \
qemu-user
INIT_DOCPKGS := pandoc latexmk texlive-xetex texlive-latex-base texlive-latex-recommended \
texlive-latex-extra texlive-pictures texlive-fonts-recommended lmodern \
fonts-dejavu fonts-dejavu-extra doxygen graphviz
-3
View File
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ab5bc3622387e7740c914c587156ac15411cbc30f2f66e68c2025710a7207e43
size 33126
+32 -6
View File
@@ -1,10 +1,15 @@
# LithosAnanke v2.1.0
# LithosAnanke v4.0.0-alpha.4
**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.4](https://gitea.starshipos-f18.org/rajames/LithosAnanke/releases),
the kernel `4.0.0-alpha.4` 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 |
+27 -4
View File
@@ -144,8 +144,8 @@ make boot_image TARGET=MILKV EMERGENCY_CONSOLE_ENABLED=1
thumbdrive attached. After a clean build it does (tried on `MILKV`).
- [ ] The Pi 5 build fetches the board's DTB once from the pinned firmware release; with no
network, pass `RPI5_DTB=/path/to/bcm2712-rpi-5-b.dtb`.
- [ ] Put back `v3/include/version.h` and `capsules/BLOCK_MAP.md` afterwards: the build
rewrites both.
- [ ] Put back `capsules/BLOCK_MAP.md` afterwards if the build was signed: a signed build rewrites
its Signed column. (`v3/include/version.h` is untracked since 2026-11-11, #145.)
### 3.2 Rehearse each image as its own disk
@@ -156,8 +156,9 @@ One QEMU at a time. Use a copy of the image: the kernel writes to its disk.
2026-10-27 the PC image is the StarshipOS stick (`docs/v4.0.0/STICK.md` §4: ESP,
identity, Artemis) and `make -f kernel/Makefile ARCH=amd64 qemu-stick` does exactly
this: a copy of the stick as a USB stick on the xHCI controller (`bootindex=0`), OVMF
booting its ESP, logs under `logs/<TS>/amd64/`. The stick's identity partition is
blank until first-boot genesis (stick increment 5), so today it boots headless.
booting its ESP, logs under `logs/<TS>/amd64/`. Since 2026-11-08 (stick increment 5,
`plans/2026-10-29-stick-5`) its first boot mints the stick's own Zuse and reaches
`[zuse@Hera] ok>` with nothing set up; `qemu_session.py stick_genesis` checks it.
- [ ] **MILKV:** the command in `boards/milkv/README.md` (OpenSBI, U-Boot, `bootefi`).
- [ ] **RASPI:** there is no QEMU model of the Pi 5, but its native path -- raw image, entry
at EL2 with the MMU off, devicetree in x0 -- is rehearsed on QEMU virt:
@@ -207,6 +208,28 @@ the one QEMU exercises most closely, and the Pi 5's can be rehearsed only in par
on until login (screen=boot)"). Secure Boot off. Watch for `Boot disk: a StarshipOS stick`, `Artemis: the stick's partition
attached`, then `[zuse@Hera] ok>`. The same image boots in QEMU first:
`make -f kernel/Makefile ARCH=amd64 qemu-stick STICK_PAIR=disk/zuse-scratch`.
- [ ] **Plug and play, and the real Zuse** (2026-11-10, after the stick's increments 5 and 5a,
`docs/v4.0.0/plans/2026-10-29-stick-5-proxy-zuse-and-real-zuse.md`, Task 5 step 6). Two USB
sticks: the system stick, written from `make boot_image TARGET=PC` (no `STICK_PAIR`) with
`make write_stick DEVICE=/dev/sdX`, and a second stick of 64 MiB or more that may be erased.
Each step rehearsed first in QEMU by the session named:
- [ ] **First boot** (`stick_genesis`, `stick_grow`): the system stick alone. Watch for
`Artemis: grown to fill the stick` (a stick of 8 GB or more) or `Artemis: the stick is
under 8 GB -- not grown`, then `Zuse: genesis minted onto attached thumbdrive`, then
`[zuse@Hera] ok>`. Nothing typed before it. Write down the time from power-on to the
prompt.
- [ ] **The second boot of the same stick:** `Zuse: identity confirmed from attached
thumbdrive`, no genesis line, no growth line.
- [ ] **`MINT-ZUSE`** (`mint_zuse`): type it, plug in the second stick when asked; check the
size it names is that stick's; type `YES`. Watch for `Zuse: real Zuse minted onto the
second stick`, then `identity confirmed`, then the prompt.
- [ ] **The system stick alone** (`fallback`): power off, take the second stick out, boot. The
fixed screen's four lines (`Zuse's stick is not here.` ...), no prompt; keys typed there
do nothing. Plug the second stick in: the prompt. Pull it: the screen comes back.
- [ ] **Both sticks at power-on** (`zuse_stick_first`): her stick in the lower port if the
PC's ports are numbered; she is logged in once.
- [ ] Not done on the bench unless a spare stick is to hand: `R` and a replacement
(`replace`) -- the second stick stops working for good.
- [ ] The timer lines differ from QEMU's by design: no hypervisor, so the HPET path runs for
the first time. S1 is the finding to remember if it stops there.
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
# boards/milkv/board.mk -- Milk-V Mars (StarFive JH7110, SiFive U74, RV64GC).
#
# The board's own SPI-flash U-Boot (OpenSBI underneath) runs the EFI
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
# boards/pc/board.mk -- a generic PC: x86-64, UEFI firmware, ACPI.
#
# Not one machine: the standards-compliant UEFI path (FABRIC-3.md §III), so
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
# boards/raspi/board.mk -- Raspberry Pi 5 (BCM2712, Cortex-A76, aarch64).
#
# Native firmware boot, no UEFI (FABRIC-3.md §IV): the Pi 5 bootloader

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