18 Commits
Author SHA1 Message Date
rajamesandClaude Opus 5.5 672d275f5c ci: no quick check on master after a merge (#119); the runner image's recipe (#120)
Captain Bob, 2026-11-06: a small server, a little sluggish. Each change
cost about an hour of runner time; the gate itself is about 15 minutes.

#119 -- build.yml runs on pushes to the working branch only. What
reaches master arrives through a PR whose content just passed
acceptance; checking it again cost ~23 minutes after every merge.

#120, first step -- ci/runner-image/Dockerfile: gitea/runner-images'
Ubuntu 24.04 (with Node, for the actions) plus what
make ARCH=amd64,aarch64,riscv64 init INIT_DOCS=0 installs -- run from
the Makefile itself, not a copied list -- and Maven for publishing.
.gitea/workflows/runner-image.yml builds it and publishes it to the
package registry as lithosananke-runner:<commit>. The workflows switch
to it in a later change, once it is published and has passed
acceptance. It needs the runner to lend jobs its Docker daemon
(container.docker_host: automount) and a PACKAGES_TOKEN secret, unless
the Actions token may publish packages.

make init does git lfs install --local only inside a checkout: the
image build is not one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-06 20:43:42 +00:00
rajamesandClaude Opus 5.5 a5a29cc857 ci: nightly images, nightly documents and tagged releases, in the tree
scripts/nightly.sh, one stage per call, a step each in the workflows:

  accept <amd64|aarch64|riscv64|stick-high>  the acceptance protocol --
        qemu_session.py zuse, and stick_zuse --target qemu-stick-high;
        after the last, dict_hash must be equal on the three
  test-32   make -C v4 test-32
  proofs    isabelle build -c -D proof/ (StarForth checked afresh each run)
  images    the Pi 5 and Mars images, xz for Raspberry Pi Imager
  publish   org.starship:kernelImage: pc (iso), raspi5, milkv (img.xz),
            logs (tar.gz: this run's serial logs, proof log, DoE CSVs)
  docs, publish-docs   book, vol1-3, api -> org.starship:documentation

.gitea/workflows/nightly.yml (03:00) and nightly-docs.yml (04:00) publish
<LITHOS_VERSION>-SNAPSHOT to starshipos-snapshots; release.yml, on a tag
v*, builds and publishes both to starshipos-releases at the tag's version,
refusing a tag that is not v<LITHOS_VERSION>. Until this branch is merged
to master, master carries copies of the two nightlies naming it.

make init: INIT_DOCS=0 leaves out TeX and Doxygen, INIT_PROOFS=0 Isabelle.

Checked here, stage by stage, in order: the four acceptance boots PASS,
dict_hash 0xfec8c47cfc6f437f on the three, test-32 0 failures, StarForth
proved (0:00:41), images built; publish to a local file:// repository,
and the images' publish to Nexus starshipos-snapshots read back byte for
byte. The docs stage and publish-docs: not yet checked when committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-06 15:21:58 +00:00
rajamesandClaude Opus 5.5 ca95567d14 build: scripts/nightly.sh -- the nightly snapshot of the board images, for Nexus
Three stages, each a step of the nightly workflow:

  boot <amd64|aarch64|riscv64>  qemu_session.py headless, one QEMU at a time,
                                in the acceptance order; amd64 keeps the ISO it
                                booted as build/nightly/StarshipOS.iso
  images                        make boot_image for RASPI (Pi 5) and MILKV
                                (Mars) -> raspi5.img.xz, MilkV.img.xz (for
                                Raspberry Pi Imager), and SHA256SUMS
  publish <url>                 mvn deploy:deploy-file (maven-deploy-plugin
                                3.1.2): org.starship:kernelImage:
                                <LITHOS_VERSION>-SNAPSHOT, classifier pc (iso),
                                raspi5 and milkv (img.xz), in one deploy

Classifier by board, not ISA: two aarch64 boards would collide. No Pi 4:
there is no BCM2711 port. QEMU boots the aarch64 and riscv64 kernels, not
the Pi 5 and Mars images, which are for hardware QEMU does not model.

make init takes INIT_DOCS=0: without the TeX and Doxygen packages and
Isabelle, which an image build does not need.

Checked here: the three boot checks pass (logs in the next commit), the
images build, and publish to a local file:// repository gives the
timestamped snapshot files, the POM and maven-metadata.xml with one
snapshotVersion per classifier. Not checked: Nexus itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-06 14:45:35 +00:00
rajamesandClaude Opus 5.5 4cef0431bf build: init downloads syft and Isabelle/HOL, checked by SHA-256
Neither is packaged. make ARCH=<arch> init now downloads both to
build/cache/downloads, checks each archive's SHA-256, unpacks it into
build/cache/tools (both kept by make clean) and links it into
/usr/local/bin:

- syft 1.52.0, the version sbom.spdx was made with (make sbom,
  boot_image); sums from the release's checksums.txt;
- Isabelle2025-2, the version proof/COVERAGE.md names (isabelle build
  -D proof/), from the release's own site (the /dist mirror answered
  503); Isabelle publishes no sums, so these are of the archives as
  downloaded on 2026-11-06.

An archive already there with the right sum is not downloaded again;
a download with the wrong sum is deleted and init stops. The host's
build is chosen by uname -m (amd64 or arm64).

Checked on Ubuntu 24.04 (x86_64): both fetched, checked and run (syft
1.52.0, Isabelle2025-2); a wrong sum is refused and deleted; isabelle
build -n -D proof/ finds the StarForth session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-06 01:25:47 +00:00
rajamesandClaude Opus 5.5 d8e3fa81eb build: make ARCH=<arch>[,...] init installs what the tree needs
One ISA or several (ARCH=amd64,aarch64,riscv64, for the full
acceptance), on Debian/Ubuntu with apt-get, sudo when not root:

- common: the build, the disk-image tools (scripts/mkdiskimage.sh;
  sfdisk is in fdisk), git-lfs for the logs and DoE CSVs, and the
  documents -- docs/book/Makefile's own list, and pdflatex, doxygen and
  graphviz for docs/formal;
- per ISA: its QEMU, its UEFI firmware at kernel/Makefile's paths, and
  its compiler (aarch64's loader also needs clang and lld-link).

Then git lfs install --local, so a log or CSV committed from this
checkout goes into LFS (the 1003 plain files fixed in 027b144e came
from a checkout without it). Not installed: syft (make sbom), which is
not packaged.

Checked on Ubuntu 24.04: init for all three ISAs, then make docs and
make -C docs/formal vols build. make -C docs/formal doxygen fails in
LaTeX on "newunicodechar Error: ASCII character requested" with every
package present -- a separate fault, not a missing dependency.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-06 01:18:07 +00:00
rajamesandClaude Opus 5.5 0a31e558be feat(build): make write_stick DEVICE=/dev/sdX -- the PC stick onto a USB stick, checked and read back
scripts/write_stick.sh refuses a device that is not a whole, removable USB disk, that holds the
running system, that is smaller than the image, or that has a mounted partition (it prints the
udisksctl lines); shows the stick and asks for its name typed back; writes with conv=fsync,
flushes, reads the stick back and compares it with the image byte for byte; powers it off. On
Windows/macOS it points to balenaEtcher or Rufus. Captain Bob, 2026-10-28, after a terminal line
break dropped dd's bs=4M conv=fsync on the first SER5 stick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 06:22:26 -04:00
rajamesandClaude Opus 5.5 d577a1db48 build: make ARCH=<arch> clean qemu boots the kernel from the top level
Top-level 'qemu' fell through to v3/Makefile, which has no such rule.
qemu, qemu-esp and qemu-gdb now go to kernel/Makefile; with ARCH given on
the command line and no TARGET, 'clean' is the kernel's for that ISA.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:20:16 -04:00
rajamesandClaude Opus 5.5 3b49cb15a2 boards: the amd64 target is PC -- a generic x86-64 UEFI PC, not the SER5
Captain Bob, 2026-10-14: "change to PC, not SER5. it's not supposed to be
specific, but PC generic."  boards/ser5 -> boards/pc, TARGET=PC,
lithos-pc.img; the image was never specific to one machine (the generic
UEFI/ACPI path, FABRIC-3 III).  The Beelink SER5 stays named where the text
means the unit on the bench (its Secure Boot, BIOS, serial header) and in
the records.  Built: lithos-pc.img, system=v4, with its SBOM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:22:32 -04:00
rajamesandClaude Opus 5.5 79db0e8d88 build: v4 is the default build -- every kernel boots v4; acceptance is v4 on three ISAs and the 32-bit build
Captain Bob, 2026-10-14: "v4 is the default build", "no, qemu to v4
too ... we are effectively trying to retire v3", "the 32 bit build needs
to go into the acceptance test too", "i don't care about v3".

- STARFORTH_V4 defaults on (Kconfig default y) and V4_DEFAULT=1
  everywhere: every kernel carries v4 and v3 and boots v4; system=v3 boots
  v3; STARFORTH_V4=0 builds v3 alone.  Board images write system=v4.
- Acceptance (CLAUDE.md): the three ISAs as built (v4, POST passed,
  V4_SYSTEM dict_hash equal) and make -C v4 test-32.  v3 is not part of
  it.

Acceptance run: amd64, aarch64, riscv64 -- PARITY:V4_POST 538/538,
dict_hash=0xe5a57f3eb72ff94a on all three, no unknown word; test-32: 30
suites, 0 failures.  The SER5 image under OVMF boots v4 as built, v3 after
the one-word edit.  README, BRINGUP, FABRIC-3 XLIII, the register updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:21:13 -04:00
rajamesandClaude Opus 5.5 fcb89b0695 build: an SPDX SBOM with every board image, and of the source tree, by syft
make boot_image now ends by writing build/boards/<board>/<image>.spdx(.json):
the image and every file copied off it, each with its SHA-256 -- the SBOM
of what is on the medium.  It also refreshes sbom.spdx(.json), the source
SBOM: the tracked files the product is built from (kernel, v3, v4,
capsules, boards, tooling, proofs), staged to build/sbom/src so nothing
untracked in the working directory is swept in.  Versioned as the kernel
version and git describe.  mk/syft.yaml turns on file cataloging with
SHA-256 (a C tree has almost no packages for syft to find: the old SBOM
held one file with a zero checksum).  No syft: the build stops.

syft 1.52.0 installed in ~/.local/bin from its GitHub release, checked
against the release's published SHA-256.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:58:10 -04:00
rajamesandClaude Opus 5.5 1a4b163861 feat(boards): both systems on every board image, chosen at boot -- system=v3 or system=v4
boards/BRINGUP.md A6, FABRIC-3 SXLIII (ruled: one image, switch at boot).
A STARFORTH_V4 kernel carries v3 too; system= in the boot arguments
chooses, else the build's default (V4_DEFAULT: 1 for plain STARFORTH_V4
builds as before, 0 for board images).  make boot_image builds both and
always writes starforth.cfg / cmdline.txt with system=v3 first, and cleans
its ISA's objects first -- that clean was removing build/<arch>/SER5, not
the kernel's objects, until fixed here.

Each ISA: v3 by default (hash unchanged), v4 with system=v4 (538/538).
The SER5 image under OVMF: v3 as built, v4 after a one-word edit on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:11:47 -04:00
rajamesandJunie a8b70e88d3 Reorganize source tree: kernel/, v3/, v4/ split and board infrastructure
Source tree reorganization:
- Move StarForth v3 engine to v3/ (src/, include/, Makefile)
- Move kernel to kernel/ (src/, include/, linker/, Makefile)
- Create v4/ skeleton for F18-ISA golden model (DECOMPOSITION.md, JUSTIFICATION.md)
- Move FABRIC-0..4.md to docs/fabric/
- Move ONTOLOGY.md and ROADMAP.md to docs/

Board infrastructure:
- Add boards/ser5/, boards/raspi/, boards/milkv/, boards/zynq7020/
- Each board has board.mk (ISA, CPU flags, boot recipe) and README.md
- Root Makefile becomes thin dispatcher: boot_image, all, clean, docs take TARGET
- make boot_image TARGET=SER5|RASPI|MILKV builds one GPT/MBR image per board
- ZYNQ7020 target exists but stops with clear error (ARMv7 port not built yet)
- scripts/mkdiskimage.sh builds disk images for all boards

Docs pipeline:
- docs/book/ with LaTeX master (main.tex) and Makefile
- pandoc converts Markdown to LaTeX at build time
- Two Lua filters: table-widths.lua (wide tables wrap), code-breaks.lua (inline code breaks)
- make docs builds single PDF (754 pages, 0 missing characters)
- make docs TARGET=<board> adds board appendix
- build/docs/<book|board>/meta.tex stamps git commit into PDF

Bug fixes:
- 42 include paths that only worked by accident now use correct relative paths
- clang-18 hardcode replaced with configurable CC variable (fixed aarch64 build)
- Pi 5: kernel_2712.img linked at 0x80000, .bss zeroed, memory reserved
- Doxyfile, .clang-tidy, README.md, Kconfig paths updated

Verified:
- Hosted v3 build passes 1012 tests, 0 failures
- SER5 image boots in QEMU (OVMF), POST passes, K exact (65536 = Q48_ONE)
- Milk-V image boots in QEMU (OpenSBI + U-Boot + bootefi), POST passes
- make clean TARGET=<board> removes only that board and its ISA objects
- make all builds all boards, hosted v3, and docs in one run

Co-authored-by: Junie <junie@jetbrains.com>
2026-10-01 15:40:09 -04:00
Robert Allan JamesandClaude Sonnet 5 2a084ba037 Phase 5 corrections: sharpen 5.1's boundary claim, fix hosted Makefile's own stale VERSION
Advisor review of the Phase 5 close-out commit caught two real issues:

- Task 5.1's write-up claimed the Isabelle pass "confirms no regression" --
  overstated. Nothing in proof/'s scope changed, so the pass isn't
  regression evidence, it's a build-completeness formality; the boundary
  argument alone already supports the real conclusion. Sharpened.

- sbom.spdx was regenerated before the 5.4 version bump, so it briefly
  understated the engine version. Root cause: the hosted Makefile carries
  its own separate hardcoded VERSION (Makefile:17, still 3.1.0), distinct
  from Makefile.starkernel's copy that 5.4 bumped -- duplication CLAUDE.md's
  own "two independently tracked version strings" note doesn't document.
  Bumped to 3.2.0 to match, regenerated (PackageVersion now correct), and
  rebuilt the hosted starforth binary so lfs/amd64/starforth reflects it.

Also recorded why 5.1-5.4 landed as one commit (deviation from this
document's per-task-commit discipline) and sharpened the riscv64 log
entry so the FAILED run and the accepted retry aren't ambiguous to a
future reader grepping logs/.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 19:49:08 -04:00
Robert Allan JamesandClaude Sonnet 5 a4ad14aec6 Phase 5 close-out: Isabelle pass, doc sweep, SBOM, version bump (FABRIC-3.6.md tasks 5.1-5.4)
5.1: Isabelle/HOL pass (52 theories, clean) -- restated the boundary rather
than just citing the green build: proof/ scope was already entirely
outside this reshuffle's footprint (src/starkernel/, capsules/*.4th),
so the boundary is unchanged, not moved.

5.2: Documentation sweep. CLAUDE.md's stale WIP banner and Tripod fleet
description updated now that Phases 0-4 have actually landed (Hera/
Artemis/Hestia, no Hermes). MANIFEST.md rides the strip -- hermes/init.4th's
block table replaced with a deletion note, init.4th/doe-campaign.4th/
hestia/init.4th entries corrected to match the post-strip live files.
Confirmed the TRIPOD.md/0.1 contradiction was already resolved (2026-08-13).
Settled the superseded-docs call explicitly: archive as-is, do not rewrite.
Fixed experiments/bare_metal/README.md's block-size framing (still said
1024-byte budget; real rule is 64 chars x 16 lines). K-qualification
checked clean against the two living documents; full retroactive sweep
of the closed archival FABRIC corpus explicitly declined as disproportionate.

5.3: make sbom. Installed syft (user-local, approved). Found and fixed a
real Makefile bug while at it -- the sbom target hardcoded
--source-name StarForth, so DocumentName was wrong even after regenerating.

5.4: LITHOS_VERSION 2.0.0 -> 2.1.0, engine VERSION 3.1.0 -> 3.2.0 (minor,
per the dictionary-visible-only rule). Replaced the stale version-comment
block in Makefile.starkernel (had the odd/even LTS rule backwards) and
docs/lithosananke/ROADMAP.md's retired versioning-policy section with the
ratified ladder. Verified on all three architectures; riscv64's first pass
hit a transient virtio_blk timeout during boot-time Zuse genesis mint,
reported and confirmed non-reproducing on an immediate clean retry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 19:46:34 -04:00
Robert Allan James 5689c397fc Bug-fix sweep: repl reentrancy, virtio/blocksys bounds, identity CRCs, LOG_LINE_MAX
Code review fixes, all compile clean (hosted gcc + aarch64/riscv64 kernel flags):

- repl.c (H1): reentrancy guards on the MSG-TICK idle pump. sk_repl_idle()
  now defers when Hera is mid-interpret (g_mama_interpreting) or when its
  own vm_interpret is on the stack (g_idle_pump_active), so a blocking
  KEY/EXPECT/QUERY inside a dispatched line can no longer re-enter the
  interpreter and clobber the in-flight input buffer.
- virtio_rng.c: clamp device-returned used_len to VRNG_BUF_SIZE before the
  caller's data_buf copy, closing a device-controlled OOB read.
- block_subsystem.c: first-write path now keys off created_time==0 instead
  of dead magic==0 so fresh blocks get a real created_time stamp; first_free/
  last_allocated fixed to absolute Forth LBNs (set in blk_compute_fresh_geometry
  from slot->start_lbn, no longer the wrong physical-BAM-index values from
  compute_totals_from_B); physical-bounds guard on blk_meta_zone_read/write
  prevents unsigned underflow on a corrupt fence >= device size.
- capsule_zuse_boot.c / capsule_wirebind.c: identity seed validated magic ->
  version -> CRC-64 (compute_crc64 over offsetof(crc)) before trusting it,
  so a corrupt/format-mismatched record is refused, never loaded.
- log.h / starkernel/log.h: unused LOG_LINE_MAX 256 renamed LOG_MSG_LINE_MAX
  to lift the include-order collision with vm.h's LOG_LINE_MAX 64; stale
  include-order comments dropped (kernel_main.c, shim.c, capsule_birth.c).
- FABRIC-3.md: three stale-doc carry-forward items closed [x] with cbe7b49
  notes.

Real KEY/?TERMINAL/QUERY/EXPECT bodies (console WIP):
- repl.h/repl.c: sk_console_getkey()/sk_console_key_available()/
  sk_console_readline() public bodies; non-destructive peek buffers the
  found byte so a following KEY returns it.
- shim.c: getchar()/fgetc()/fgets()/sf_terminal_ready() routed through the
  real console paths instead of stubs; sf_terminal_ready() in platform_io.h
  with sf_terminal_ready() implemented for the hosted build (linux/io.c,
  POSIX select on fd 0) wired into Makefile.
- io_words.c: ?TERMINAL now returns actual terminal-readiness, not constant 0.

Artifacts: minted disk/artemis.img + rebuilt lfs kernel; BLOCK_MAP.md,
doe csv + qemu log regenerated.
2026-08-28 23:28:10 -04:00
Robert Allan JamesandClaude Sonnet 5 b9e8fdc3ae repo: remove broken bump-z/bump-y targets, fix tools/README.md stale fbtest.c row
bump-z/bump-y referenced STARFORTH_VERSION_MAJOR/MINOR/PATCH/STARFORTH_VERSION_STRING
fields that never existed in the generated include/version.h, so they could never
have worked. Removed rather than fixed since CLAUDE.md already documents hand-editing
VERSION/LITHOS_VERSION in Makefile.starkernel as the real convention.

tools/README.md documented a fbtest.c that never existed in any commit; replaced with
the ttftest.c row that actually matches the tools/ directory.

Part of the pre-Artemis closeout pass (FABRIC-2.md Section C).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 05:58:14 -04:00
Robert Allan JamesandClaude Sonnet 5 d922e152aa Add riscv64-clang Makefile target; closes out 2026-07-24 punch list
Resolves item #3 of docs/working/archive/session-logs/2026-07-24-punch-list.md
("riscv64 hosted build isn't reachable via plain make"), the last open
item from that list. Decided against options (b) chasing GCC's riscv64
nanosleep-visibility failure at its root (undiagnosed, open-ended) and
(c) leaving it manual — instead wired the already-verified clang recipe
(commit 4485c38 / e287334) into the Makefile, mirroring the existing
rpi4-cross pattern.

Makefile: new riscv64-clang target. CFLAGS deliberately does not reuse
$(BASE_CFLAGS) (hardcodes -std=c99); clang needs -std=c11 -pthread here
instead. Registered in `make help` and .PHONY.

docs/lithosananke/hosted-acceptance-test/README.md: riscv64 section now
points at `make riscv64-clang` instead of the long manual invocation.
Updated Background section and commit list to reflect that all three
punch-list items touching this doc (#1 asm fix, #2 doc command, #3 make
target) are now resolved.

Verified: `make riscv64-clang` produces a binary with identical results
to the manual command it replaces (965 passed / 0 failed, "ALL
IMPLEMENTED TESTS PASSED!", "3 Goodbye!" for the piped acceptance script).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-02 07:43:01 -04:00
Robert Allan James a5ed8c3d87 Initial commit — LithosAnanke kernel 2026-08-01 07:49:56 -04:00