Author SHA1 Message Date
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
Claude 6f14d8d6bc site/org: the .org pages in the starshipos-f18.com look
Build / v4 tests (32- and 64-bit cells) (push) Successful in 13m44s
Build / Image RASPI (push) Successful in 2m43s
Build / Image PC (push) Successful in 2m55s
Build / Image MILKV (push) Successful in 2m55s
Captain Bob, 2026-11-07: style .org like the StarshipOS.com design canvas.
build.py makes the three pages from one source, as {{html}} blocks in the
canvas's look (navy, orange accent, JetBrains Mono and Exo 2), and the same
pages as the canvas's .org artboards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 11:36:09 +00:00
Claude 51dd4a8391 site/org: the .org wiki's landing page and its two dashboards
Build / Image RASPI (push) Successful in 2m18s
Build / Image PC (push) Successful in 2m54s
Build / Image MILKV (push) Successful in 2m29s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 10m23s
Ruled by Captain Bob, 2026-11-07: a generic landing page for anonymous
visitors, a login-protected admin dashboard for him, and a protected
contributors' dashboard. Main.WebHome (everyone), Admin.WebHome
(XWiki.rajames alone), Contributors.WebHome (XWiki.StarshipContributors
and the administrator); CI shown as Gitea's live workflow badges.
install.sh puts them on the wiki through XWiki's REST API, with the group
and the space rights, and checks a guest's view. Not yet run: the .org
XWiki answers 503.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 11:29:10 +00:00
Claude 03027f9769 pki: the StarshipOS CA, made on the CI box; capsules signed in CI
Build / Image RASPI (push) Successful in 2m17s
Build / Image PC (push) Successful in 2m31s
Build / Image MILKV (push) Successful in 2m20s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 8m51s
Ruled by Captain Bob, 2026-11-07: "New root CA on the CI box. Valid
StarshipOS rather than snake oil intermediate."

- ci/pki/make-ca.sh makes the StarshipOS Root CA (its key stays on the CI
  box) and the StarshipOS Capsule Signing intermediate it issues, and
  stores the signing key as the secret CAPSULE_SIGN_KEY.
- The kernel finds the signing certificate by one name,
  CAPSULE_SIGNING_CERT_NAME = pki:starshipos-intermediate.der. The
  certificate itself lands once make-ca.sh has run; until then the
  snakeoil intermediate is in the tree under its old name and the
  capsules check as "no root key" (a warning, as "missing" was).
- mkcapsule refuses a signing key that is not that certificate's.
- SIGN_KEY has no default; acceptance, build, nightly and release set it
  from the secret.

FABRIC-3.md XLVI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 04:15:29 +00:00
Claude 4ae1f759d5 ci: HOL-Library built into the runner image
Build / Image RASPI (push) Successful in 2m12s
Build / Image PC (push) Successful in 2m34s
Build / Image MILKV (push) Successful in 2m25s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 8m58s
Measured here (Isabelle2025-2, one thread): HOL-Library from scratch takes
~11 minutes and peaks at ~5.3 GiB -- what nightly 174 was killed doing; the
StarForth session on a built HOL-Library takes under a minute and ~2.2 GiB.
The image builds HOL-Library once into Isabelle's own heaps, so every job
finds it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-07 03:41:34 +00:00
Claude 5690d2980b ci: the nightly's proofs run last, and cannot hold back the images
Build / Image RASPI (push) Successful in 3m46s
Build / Image PC (push) Successful in 3m4s
Build / Image MILKV (push) Successful in 2m21s
Build / v4 tests (32- and 64-bit cells) (push) Successful in 8m51s
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 03:38:39 +00:00
53 changed files with 2343 additions and 22 deletions
+12
View File
@@ -37,6 +37,18 @@ 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
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(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."
fi
- name: Acceptance amd64
run: scripts/nightly.sh accept amd64
- name: Acceptance aarch64
+26
View File
@@ -9,6 +9,8 @@ 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:
jobs:
@@ -34,6 +36,18 @@ 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
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(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."
fi
- name: Boot image
run: make boot_image TARGET=${{ matrix.board }}
@@ -62,5 +76,17 @@ jobs:
with:
lfs: false
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(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."
fi
- name: make -C v4 test
run: make -C v4 test
+12
View File
@@ -39,6 +39,18 @@ 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
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(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."
fi
- name: Acceptance amd64
run: scripts/nightly.sh accept amd64
- name: Acceptance aarch64
+12
View File
@@ -33,6 +33,18 @@ jobs:
fetch-depth: 0
lfs: false
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(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."
fi
- name: The tag names the tree's version
run: |
tree="v$(sed -n 's/^LITHOS_VERSION *?= *//p' kernel/Makefile)"
+13
View File
@@ -1,5 +1,18 @@
# Changelog
## 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
+81
View File
@@ -0,0 +1,81 @@
#!/bin/bash
# make-ca.sh -- the StarshipOS capsule-signing PKI, made once, on the CI box (Captain Bob,
# 2026-11-07: "New root CA on the CI box. Valid StarshipOS rather than snake oil intermediate").
#
# StarshipOS Root CA Ed25519, 20 years, self-signed. Its key never leaves this box:
# not in the repository, not in Gitea, not in any image.
# StarshipOS Capsule Signing Ed25519, 10 years, signed by the root; CA:TRUE, pathlen:0.
# Its certificate is built into every image (capsules/pki/
# starshipos-intermediate.der) and checks each capsule at boot;
# its key signs the capsules (mkcapsule --sign-key), in CI from
# the repository secret CAPSULE_SIGN_KEY.
#
# Replaces the offline LithosAnanke Root CA and its snakeoil intermediate (FABRIC-2.md,
# Milestone 6) for every build. Run as root:
#
# sudo ci/pki/make-ca.sh [dir] # dir defaults to /var/lib/starshipos-ca
#
# It refuses to overwrite an existing CA. When it is done it prints the two certificates (public:
# paste them where they are wanted) and says how to put the signing key into Gitea. With
# GITEA_TOKEN set (a token that may administer the repository), it stores the secret itself.
set -euo pipefail
umask 077
dir=${1:-/var/lib/starshipos-ca}
repo=${GITEA_REPO:-rajames/LithosAnanke}
api=${GITEA_API:-https://gitea.starshipos-f18.org/api/v1}
command -v openssl >/dev/null || { echo "make-ca: needs openssl" >&2; exit 1; }
[ -e "$dir/root/root.key" ] && { echo "make-ca: $dir already holds a CA; not overwriting it" >&2; exit 1; }
mkdir -p "$dir/root" "$dir/signing"
cd "$dir"
cat > ca.cnf <<'CNF'
[ req ]
distinguished_name = dn
prompt = no
[ dn ]
[ root_ext ]
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
[ signing_ext ]
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, keyCertSign, cRLSign, digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
CNF
# the root
openssl genpkey -algorithm ed25519 -out root/root.key
openssl req -new -x509 -key root/root.key -days 7305 -config ca.cnf -extensions root_ext \
-subj "/O=StarshipOS/CN=StarshipOS Root CA" -out root/root.pem
# the capsule-signing intermediate, signed by the root
openssl genpkey -algorithm ed25519 -out signing/signing.key
openssl req -new -key signing/signing.key -config ca.cnf \
-subj "/O=StarshipOS/CN=StarshipOS Capsule Signing" -out signing/signing.csr
openssl x509 -req -in signing/signing.csr -CA root/root.pem -CAkey root/root.key \
-CAcreateserial -days 3652 -extfile ca.cnf -extensions signing_ext -out signing/signing.pem
openssl x509 -in signing/signing.pem -outform DER -out signing/starshipos-intermediate.der
openssl verify -CAfile root/root.pem signing/signing.pem
chmod 700 root signing; chmod 600 root/* signing/*
if [ -n "${GITEA_TOKEN:-}" ]; then
python3 -c 'import json,sys; print(json.dumps({"data": open(sys.argv[1]).read()}))' signing/signing.key |
curl -fsS -o /dev/null -X PUT -H "Authorization: token $GITEA_TOKEN" -H 'Content-Type: application/json' \
"$api/repos/$repo/actions/secrets/CAPSULE_SIGN_KEY" -d @- &&
echo "make-ca: stored the signing key as $repo's secret CAPSULE_SIGN_KEY"
else
echo "make-ca: put $dir/signing/signing.key, whole, into $repo's Actions secret CAPSULE_SIGN_KEY"
echo " (Settings -> Actions -> Secrets), or run again with GITEA_TOKEN set -- after"
echo " removing $dir, since it refuses to overwrite a CA."
fi
echo
echo "=== The root certificate (public) -- $dir/root/root.pem"
cat root/root.pem
echo "=== The capsule-signing certificate (public) -- $dir/signing/signing.pem"
cat signing/signing.pem
echo "=== Fingerprints"
openssl x509 -in root/root.pem -noout -fingerprint -sha256 -subject -enddate
openssl x509 -in signing/signing.pem -noout -fingerprint -sha256 -subject -issuer -enddate
+6 -1
View File
@@ -1,7 +1,8 @@
# The CI runner image (#120): gitea/runner-images' Ubuntu 24.04 with Node -- which
# actions/checkout and upload-artifact run on -- plus everything the jobs install at their start:
# what `make ARCH=amd64,aarch64,riscv64 init INIT_DOCS=0` installs (taken from the Makefile
# itself, not copied, so the two cannot drift), and Maven and a JRE for the publish steps.
# itself, not copied, so the two cannot drift), Maven and a JRE for the publish steps, and
# Isabelle's HOL-Library already built, for the proofs.
#
# Built by .gitea/workflows/runner-image.yml, from a context of the Makefile, boards/ and this file.
FROM gitea/runner-images:ubuntu-24.04-v26.11.03
@@ -11,4 +12,8 @@ WORKDIR /opt/starship-init
RUN make --no-print-directory ARCH=amd64,aarch64,riscv64 init INIT_DOCS=0 \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y -qq maven default-jre-headless \
&& rm -rf /var/lib/apt/lists/* /opt/starship-init/build/cache/downloads
# HOL-Library, built once here, into Isabelle's own heaps (system_heaps), so the nightly's proofs
# build only the StarForth session: ~2.2 GiB and under a minute, where HOL-Library from scratch
# takes ~5.3 GiB and ~11 minutes -- more than the runner had (nightly 174, killed).
RUN isabelle build -b -o system_heaps -o threads=1 HOL-Library
WORKDIR /
+78
View File
@@ -6061,3 +6061,81 @@ four conflicts resolved to the branch's files (`92ca805e`).
- The first scheduled nightly's publish to Nexus (#17).
- The Pi 5 and Mars images booted on their boards (#27, #28); a Pi 4 port (#26).
- Revoke the access token `claude-session-20261106` (Settings, Applications).
## XLVI. The StarshipOS CA: capsules signed in CI, by a root on the CI box (2026-11-07)
### 1. Found
Every image built anywhere but Captain Bob's machine carried unsigned capsules: CI, the
acceptance runs, the nightly bound for Nexus, a release, the demo. The capsule-signing key -- the
snakeoil intermediate of the offline LithosAnanke Root CA (FABRIC-2.md, Milestone 6) -- lived only
there, `kernel/Makefile`'s `SIGN_KEY` named its path, and a missing signature is a warning by
design (2026-08-26), so they booted: `V4: capsule v4:sys:core.f18 signature: missing (unsigned)`
in every accepted log (`logs/20261106-004933`). And `mkcapsule` signed with whatever key it was
given: a key that is not the embedded certificate's makes every signature INVALID, which refuses
Mama.
### 2. Ruled
Captain Bob, 2026-11-07: "New root CA on the CI box. Valid StarshipOS rather than snake oil
intermediate."
### 3. Built
- `ci/pki/make-ca.sh`, run once on the CI box: **StarshipOS Root CA** (Ed25519, 20 years,
self-signed; its key stays on that box, in `/var/lib/starshipos-ca`) and **StarshipOS Capsule
Signing** (Ed25519, 10 years, issued by the root, `CA:TRUE, pathlen:0`). It refuses to
overwrite a CA, prints both certificates, and stores the signing key as the repository secret
`CAPSULE_SIGN_KEY` (or says how).
- The image carries `capsules/pki/starshipos-intermediate.der` in place of the snakeoil
intermediate; the kernel finds it by one name, `CAPSULE_SIGNING_CERT_NAME` (`capsule_sig.h`).
- `mkcapsule` checks the signing key against that certificate before it writes anything, and
refuses a key that is not its, or a key with no certificate to check.
- `SIGN_KEY` has no default (`kernel/Makefile`, `v4/Makefile`): CI sets it from the secret (a step
in `acceptance.yml`, `build.yml`, `nightly.yml`, `release.yml`); unset, the capsules are built
unsigned, as before.
What it is not: the kernel still does not check the intermediate against a root at boot
(`x509_ed25519.h`; `ACL.4th`'s `ACL-CA-KEY` is still 0). A signature proves a capsule matches the
certificate in the same image. That is unchanged by this, and a ruling of its own.
### 4. Verified
With a CA made by `make-ca.sh` in a scratch directory (not the real one): `openssl verify` of the
chain OK; `make-ca.sh` refuses a second run; `mkcapsule` with the signing key -- "signing key
matches"; with the root's key -- refused; with a key and no certificate -- refused; with no key --
unsigned, as before. The acceptance with the real certificate is the PR's.
## XLVII. LithosAnanke v4.0.0-alpha.1: the first alpha release (2026-11-07)
### 1. Ruled
Captain Bob, 2026-11-07: "next on the list is do a tag/release of v4.0.0" -- then, on what the number
names: "StarForth version stays the same ... Kernel is 4.0.0. This is our first alpha release." The
tag names the kernel (`release.yml`: `v<LITHOS_VERSION>`), so:
- `LITHOS_VERSION` 2.1.0 -> **4.0.0-alpha.1**; the tag is `v4.0.0-alpha.1`; Nexus takes
`org.starship:kernelImage:4.0.0-alpha.1` and `org.starship:documentation:4.0.0-alpha.1`.
- The engine's `VERSION` stays **3.2.0**.
- The versioning policy (`kernel/Makefile`, FABRIC-3.5.md XXX): 4.x is a working line (even major).
v3.0.0, the first LTS, is no longer the next number; an LTS line takes the next odd major when
XXX.5's criteria are met. Alphas are numbered: a release repository takes each version once.
- The v4.0.0 milestone is unchanged: its definition (v4 equivalent to v3, K=1.0 on all three host
ISAs, a hosted mesh, Verilator co-simulation) is what 4.0.0 itself will be; nine of its issues
are open. This is an alpha of it.
- The release is built and proved here first (this session, 15 GiB), its logs committed; the
server's release run follows once it can pass -- the proofs need HOL-Library in the runner image.
The capsules are unsigned for this release.
### 2. Verified (this session, `b7534107`, before the tag)
- amd64 (`logs/20261107-150809`), aarch64 (`-151023`), riscv64 (`-151359`): `LithosAnanke
v4.0.0-alpha.1 <arch>`, `[zuse@Hera] ok>`, `PARITY:V4_POST tests=538 pass=538 fail=0`,
`POST: PASSED`, Zuse identity confirmed, `PARITY:V4_SYSTEM word_count=317
dict_hash=0xfec8c47cfc6f437f` on all three.
- The PC stick loaded high (`logs/20261107-151539`): the same, from the stick, no fault.
- `make -C v4 test-32`: 39 programs, 0 failures.
- The Isabelle/HOL proofs (`logs/20261107-152312/isabelle`).
- Each v4 capsule logs `signature: no root key (cert not found/parseable)`: the kernel looks for the
StarshipOS Capsule Signing certificate (XLVI), which is not in the tree until `ci/pki/make-ca.sh`
has run. A warning, as "missing (unsigned)" was before; nothing is refused.
+14 -8
View File
@@ -89,6 +89,12 @@ endif
# v2.2.0 — amd64 bare-metal bring-up (Beelink SER5)
# v2.x — further working releases; riscv64 / aarch64 board bring-up
# v3.0.0 — FIRST LTS, when and only when FABRIC-3.5.md §XXX.5's 5 criteria are met
# v4.0.0-alpha.1 — the first alpha release (Captain Bob, 2026-11-07: "Kernel is 4.0.0. This is
# our first alpha release"): v4, the F18 engine, the default system. The kernel goes
# from v2.1.0 straight to the 4.x working line (even: breaking changes land here);
# v3.0.0, the first LTS, is no longer the next number -- an LTS line takes the next
# odd major when §XXX.5's criteria are met. The engine stays 3.2.0. Alphas are
# numbered (-alpha.N); a release repository takes each version once.
# LITHOS_VERSION (kernel) and VERSION (embedded StarForth engine) are independent
# and do not auto-sync (§XXX.4) — do not infer a relationship if they ever coincide.
# Engine VERSION bumps at tag time by what actually changed (§XXX.6): major = any
@@ -97,7 +103,7 @@ endif
# the messaging layer was replaced by kernel-Hermes, PLOT/FB-* relocated to Hestia —
# all dictionary-visible, no FORTH-79 word semantics changed.
VERSION ?= 3.2.0
LITHOS_VERSION ?= 2.1.0
LITHOS_VERSION ?= 4.0.0-alpha.1
# ==============================================================================
# BUILD PATHS
@@ -207,7 +213,8 @@ MKCAPSULE_SRC = tools/mkcapsule.c tools/pkcs8_ed25519.c \
kernel/src/crypto/ed25519.c \
kernel/src/crypto/fe25519.c \
kernel/src/crypto/scalar25519.c \
kernel/src/crypto/sha512.c
kernel/src/crypto/sha512.c \
kernel/src/crypto/x509_ed25519.c
MKCAPSULE_BIN = $(BUILD_DIR)/tools/mkcapsule
# mkartemis: formats and signs an Artemis partition at build with the kernel's own
# block-subsystem and artemis_sig code (tools/mkartemis.c), built as v4/Makefile builds them.
@@ -215,12 +222,11 @@ MKARTEMIS_SRC = tools/mkartemis.c kernel/src/artemis_sig.c \
$(addprefix v3/src/,block_subsystem.c blkio_ram.c blkio_file.c log.c \
platform/platform_init.c platform/linux/time.c)
MKARTEMIS_BIN = $(BUILD_DIR)/tools/mkartemis
# Milestone 6 (Phase 8): the snakeoil intermediate's private key, generated
# offline outside this repo entirely (see FABRIC-2.md's Phase 8 §Milestone 6
# writeup) -- not present in CI or a fresh checkout, so signing is skipped
# gracefully ($(wildcard ...) below) rather than failing the build. Override
# with `make SIGN_KEY=/path/to/key.pem ...` on a machine that holds it.
SIGN_KEY ?= /home/rajames/CLionProjects/lithosananke-ca/intermediate/snakeoil-intermediate.key
# The capsule-signing key: "StarshipOS Capsule Signing"'s private key (ci/pki/make-ca.sh,
# FABRIC-3.md XLVI). CI sets SIGN_KEY from the secret CAPSULE_SIGN_KEY; elsewhere set it by hand
# (`make SIGN_KEY=/path/to/signing.key ...`). Unset or absent, the capsules are built unsigned,
# which boots with a warning per capsule. mkcapsule refuses a key that is not the certificate's.
SIGN_KEY ?=
SIGN_KEY_ARGS = $(if $(wildcard $(SIGN_KEY)),--sign-key $(SIGN_KEY),)
CAPSULE_GENERATED = $(BUILD_DIR)/capsule_generated.c
CAPSULE_GENERATED_OBJ = $(BUILD_DIR)/capsule_generated.o
+2 -1
View File
@@ -171,7 +171,8 @@ typedef struct {
*
* Milestone 6 (Phase 8): each capsule's payload bytes (the same bytes
* content_hash already covers), signed by mkcapsule at build time with
* the snakeoil intermediate's private key. has_sig=0 for a capsule built
* the capsule-signing key (StarshipOS Capsule Signing, capsule_sig.h;
* the snakeoil intermediate's until 2026-11-07). has_sig=0 for a capsule built
* before this feature existed or otherwise unsigned -- a real, distinct
* state, not "signature is all-zero bytes" (which sig[64] full of 0x00
* would otherwise look ambiguous with). Indexed 1:1 with
+9 -3
View File
@@ -22,6 +22,12 @@
#include "starkernel/capsule.h"
/* The certificate whose key the capsules are signed with: "StarshipOS
* Capsule Signing", issued by the StarshipOS Root CA (ci/pki/make-ca.sh;
* FABRIC-3.md XLVI), replacing the snakeoil intermediate of Milestone 6.
* mkcapsule refuses to sign with a key that is not this certificate's. */
#define CAPSULE_SIGNING_CERT_NAME "pki:starshipos-intermediate.der"
typedef enum {
CAPSULE_SIG_OK = 0, /* has_sig=1, and it verifies */
CAPSULE_SIG_MISSING, /* has_sig=0 -- not signed at all */
@@ -31,9 +37,9 @@ typedef enum {
/*
* Verify capsule descs[index]'s Ed25519 signature against the embedded
* snakeoil intermediate cert's public key (capsule name
* "pki:snakeoil-intermediate.der", found and parsed once, cached for
* every later call this boot -- the cert doesn't change mid-boot).
* capsule-signing certificate's public key (CAPSULE_SIGNING_CERT_NAME,
* found and parsed once, cached for every later call this boot -- the
* cert doesn't change mid-boot).
*
* descs/names/sigs must be the same three parallel arrays
* (capsule_get_descriptors()/capsule_get_names()/capsule_get_signatures()),
+4 -3
View File
@@ -6,9 +6,10 @@
*
* x509_extract_ed25519_pubkey() only ever reads SubjectPublicKeyInfo --
* no signature verification, no chain validation, no extension parsing.
* That's the capsule-PKI use case (Milestone 6): the embedded snakeoil
* intermediate cert is trusted because it's baked into the trusted build,
* never re-verified against the offline root CA at boot.
* That's the capsule-PKI use case (Milestone 6): the embedded capsule-
* signing cert (StarshipOS Capsule Signing since 2026-11-07, the snakeoil
* intermediate before it) is trusted because it's baked into the trusted
* build, never re-verified against its root CA at boot.
*
* x509_verify_signature()/x509_extract_serial() (added 2026-08-28,
* FABRIC-2.md §F.7/§F.17) are for CERTVERIFY -- a regular user's cert,
+1 -3
View File
@@ -4,8 +4,6 @@
#include "starkernel/ed25519.h"
#include <string.h>
#define SNAKEOIL_CERT_NAME "pki:snakeoil-intermediate.der"
/* Cached once per boot: the cert doesn't change mid-boot, and every
* capsule birth (Mama, then every child VM) would otherwise re-find and
* re-parse the same cert. -1 = not yet attempted, 0 = failed, 1 = ready. */
@@ -20,7 +18,7 @@ static int find_and_cache_pubkey(const CapsuleDesc *descs,
pubkey_state = 0; /* assume failure unless every step below succeeds */
for (uint32_t i = 0; i < desc_count; i++) {
if (strcmp(names[i].name, SNAKEOIL_CERT_NAME) == 0) {
if (strcmp(names[i].name, CAPSULE_SIGNING_CERT_NAME) == 0) {
const CapsuleDesc *cert_desc = &descs[i];
if (x509_extract_ed25519_pubkey(arena_base + cert_desc->offset,
(size_t)cert_desc->length,
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -1
View File
@@ -17,7 +17,8 @@
# make -C v4 test-32: v4 with 32-bit cells, every test (the acceptance's last part).
# scripts/nightly.sh proofs
# isabelle build -c -D proof/: the StarForth session checked afresh every run, whatever is
# cached (HOL-Library is reused); its log is logs/<TS>/isabelle/, as a boot's is.
# cached (HOL-Library is reused: the CI image has it built, ci/runner-image); its log is
# logs/<TS>/isabelle/, as a boot's is.
# scripts/nightly.sh images
# The board images, into build/nightly/:
# raspi5.img.xz Raspberry Pi 5 (make boot_image TARGET=RASPI), for Raspberry Pi Imager
+1
View File
@@ -0,0 +1 @@
__pycache__/
+14
View File
@@ -0,0 +1,14 @@
# site/brand -- the wikis' banner
The top bar of both XWikis shows the starshipOS wordmark, not XWiki's logo, and the browser tab's
title ends "- StarshipOS" (Captain Bob, 2026-11-07). `starshipos-com.png` and `starshipos-org.png`
are the wordmark (Exo 2, white with an orange "OS", transparent), rendered at 2x.
```
XWIKI_USER=rajames XWIKI_PASSWORD=... site/brand/install.sh https://starshipos-f18.com starshipos-com.png
XWIKI_USER=rajames XWIKI_PASSWORD=... site/brand/install.sh https://starshipos-f18.org starshipos-org.png
```
The logo belongs to the colour theme, so this makes one of our own, `FlamingoThemes.StarshipOS` (a
copy of the stock Iceberg with the wordmark), and makes it the wiki's. To undo: set the wiki's
colour theme back to Iceberg (Administration, Look & Feel, Themes).
+57
View File
@@ -0,0 +1,57 @@
#!/bin/bash
# install.sh -- the wiki's banner says StarshipOS, not XWiki (Captain Bob, 2026-11-07: "The banner
# XWiki should not say that").
#
# site/brand/install.sh https://starshipos-f18.com starshipos-com.png
# site/brand/install.sh https://starshipos-f18.org starshipos-org.png
#
# In XWiki 17 the top bar's logo is the colour theme's. This makes a colour theme of our own,
# FlamingoThemes.StarshipOS -- a copy of the stock Iceberg with our wordmark as its logo -- and
# makes it the wiki's; the stock theme is not touched (set colorTheme back to
# FlamingoThemes.Iceberg to undo). It also makes the browser tab's title "<page> - StarshipOS".
# Run again after changing the wordmark: the logo is replaced. XWIKI_USER and XWIKI_PASSWORD as for
# site/*/install.sh. Everything goes as XML: XWiki refuses form and plain-text writes without its
# form token.
set -euo pipefail
cd "$(dirname "$0")"
base=${1:?usage: install.sh <wiki URL> <logo.png>}
logo=${2:?usage: install.sh <wiki URL> <logo.png>}
rest="$base/rest/wikis/xwiki/spaces"
auth=(-u "${XWIKI_USER:?set XWIKI_USER}:${XWIKI_PASSWORD:?set XWIKI_PASSWORD}")
theme="$rest/FlamingoThemes/pages/StarshipOS"
x() { curl -fsS -m 60 "${auth[@]}" "$@"; }
prop() { # prop <object URL> <name> <value>: set one property
x -o /dev/null -w " $2: %{http_code}\n" -X PUT -H 'Content-Type: application/xml' \
--data-binary "$(python3 -c '
import sys
from xml.sax.saxutils import escape
print("<property xmlns=\"http://www.xwiki.org\" name=\"%s\"><value>%s</value></property>" % (escape(sys.argv[1]), escape(sys.argv[2])))' "$2" "$3")" \
"$1/properties/$2"
}
echo "=== $base: the colour theme FlamingoThemes.StarshipOS"
x -o /dev/null -w " page: %{http_code}\n" -X PUT -H 'Content-Type: application/xml' --data-binary \
'<page xmlns="http://www.xwiki.org"><title>StarshipOS</title><syntax>xwiki/2.1</syntax><content>{{include reference="FlamingoThemesCode.ThemeSheet"/}}</content></page>' \
"$theme"
x -o /dev/null -w " logo $logo: %{http_code}\n" -X PUT -H 'Content-Type: image/png' --data-binary "@$logo" \
"$theme/attachments/$logo"
have=$(x -H 'Accept: application/json' "$theme/objects/FlamingoThemesCode.ThemeClass" |
python3 -c 'import json,sys; print(len(json.load(sys.stdin).get("objectSummaries") or []))')
if [ "$have" = 0 ]; then
# Iceberg's theme object, every property as it is, posted to our page
x -H 'Accept: application/xml' "$rest/FlamingoThemes/pages/Iceberg/objects/FlamingoThemesCode.ThemeClass/0" |
x -o /dev/null -w " theme object, from Iceberg: %{http_code}\n" -X POST -H 'Content-Type: application/xml' \
--data-binary @- "$theme/objects"
fi
prop "$theme/objects/FlamingoThemesCode.ThemeClass/0" logo "$logo"
prop "$theme/objects/FlamingoThemesCode.ThemeClass/0" logo-description "StarshipOS"
echo "=== the wiki's preferences"
prefs="$rest/XWiki/pages/XWikiPreferences/objects/XWiki.XWikiPreferences/0"
prop "$prefs" colorTheme "FlamingoThemes.StarshipOS"
prop "$prefs" title "\$tdoc.getRenderedTitle('plain/1.0') - StarshipOS"
echo "=== check, as a guest"
page=$(curl -sS -m 60 "$base/bin/login/XWiki/XWikiLogin") # a page that shows the chrome to a guest
case "$page" in *"FlamingoThemes/StarshipOS/$logo"*) echo " the banner's logo: ours";; *) echo " the banner's logo: NOT ours" >&2; exit 1;; esac
case "$page" in *"- StarshipOS</title>"*) echo " the tab's title: ends - StarshipOS";; *) echo " the tab's title: NOT ours" >&2; exit 1;; esac
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+64
View File
@@ -0,0 +1,64 @@
"""colorlock.py -- keep a page's own colours inside a wiki whose theme forces its own.
Both XWikis carry a high-contrast theme (skins/flamingo/cssVariablesInit.css on the server) that sets
every element black on white with !important. On our pages the design's colours win instead
(Captain Bob, 2026-11-07), and on those pages only; the rest of the wiki keeps the theme:
- every colour an element states in its style="" is made !important -- an inline !important beats
any stylesheet's;
- a stylesheet scoped to the page's root (class "ssos") covers the elements that state no colour:
".ssos *" outranks the theme's "*" (both !important, the more specific wins).
"""
import re
ROOT_CLASS = "ssos"
STYLE = """<style>
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
.ssos a, .ssos a * { color: #F5891F !important; }
.ssos a:hover { color: #FFB061 !important; }
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
.ssos img { background-color: transparent !important; }
</style>"""
COLOUR_PROPS = re.compile(r"^\s*(color|background|background-color|border|border-(top|right|bottom|left)|"
r"border-color|border-(top|right|bottom|left)-color|accent-color|fill)\s*:", re.I)
def _lock_style(m):
decls = []
for d in m.group(1).split(";"):
if d.strip() and COLOUR_PROPS.match(d) and "!important" not in d:
d = d.rstrip() + " !important"
decls.append(d)
return 'style="%s"' % ";".join(decls)
def lock(html, root_marker):
"""root_marker: the opening text of the page's root element, e.g. '<div style="background: #0A1222'."""
assert html.count(root_marker) >= 1, root_marker
html = html.replace(root_marker, root_marker.replace("<div ", '<div class="%s" ' % ROOT_CLASS, 1), 1)
html = re.sub(r'style="([^"]*)"', _lock_style, html)
return STYLE + "\n" + html
# For visitors (guests) only, the page is the design alone: XWiki's own chrome -- the top bar with
# Register and Log-in, the breadcrumb, the title and "Last modified", the page menu, the side panels,
# the footer and the welcome tour -- is hidden, and the design runs the full width. Logged in, the
# wiki is all there, to edit with. (Captain Bob, 2026-11-07: "Menu bar".)
GUEST_CHROME = """{{velocity}}
#if ($isGuest)
#[[{{html clean="false"}}<style>
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
#xwikimaincontainerinner > a.btn { display: none !important; }
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
#xwikicontent > .ssos { border: 0 !important; }
#xwikimaincontainer { padding: 0 !important; }
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
</style>{{/html}}]]#
#end
{{/velocity}}
"""
+120
View File
@@ -0,0 +1,120 @@
{{velocity}}
#if ($isGuest)
#[[{{html clean="false"}}<style>
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
#xwikimaincontainerinner > a.btn { display: none !important; }
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
#xwikicontent > .ssos { border: 0 !important; }
#xwikimaincontainer { padding: 0 !important; }
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
</style>{{/html}}]]#
#end
{{/velocity}}
{{html clean="false"}}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">
<style>
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
.ssos a, .ssos a * { color: #F5891F !important; }
.ssos a:hover { color: #FFB061 !important; }
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
.ssos img { background-color: transparent !important; }
</style>
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 0">
<header style="border-bottom: 1px solid #22324D !important">
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span></a>
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
<a href="/bin/view/Main/" style="color: #C8D1DE !important; text-decoration: none">Home</a>
<a href="/bin/view/Inquiries/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Inquiries</a>
<a href="https://starshipos-f18.org/" style="color: #F5891F !important; text-decoration: none">Contributors →</a>
</div>
</nav>
</header>
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Inquiries</p>
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">Talk to the bridge.</h1>
<p style="margin: 0; max-width: 640px; font-size: 18px; color: #C8D1DE !important">Licensing, research collaboration, press or plain curiosity — every message is read by a human. Want to contribute code? Head to <a href="https://starshipos-f18.org/">starshipos-f18.org</a>.</p>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 32px 24px 96px; display: flex; flex-wrap: wrap; gap: 48px; align-items: flex-start">
<form action="https://starshipos-f18.org/bin/view/PublicInquiry/" method="post" aria-label="Inquiry form" style="flex: 999 1 520px; min-width: 0; background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 32px; display: flex; flex-direction: column; gap: 20px">
<div aria-hidden="true" style="position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden"><label for="q-website">Leave this empty</label><input id="q-website" name="website" type="text" tabindex="-1" autocomplete="off"></div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px">
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-name" style="font-size: 14px; color: #C8D1DE !important">Name</label>
<input id="q-name" name="name" type="text" autocomplete="name" style="min-height: 48px; padding: 0 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
</div>
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-email" style="font-size: 14px; color: #C8D1DE !important">Email</label>
<input id="q-email" name="email" type="email" autocomplete="email" style="min-height: 48px; padding: 0 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
</div>
</div>
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-org" style="font-size: 14px; color: #C8D1DE !important">Organization <span style="color: #A3AEC2 !important">(optional)</span></label>
<input id="q-org" name="organization" type="text" autocomplete="organization" style="min-height: 48px; padding: 0 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
</div>
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-topic" style="font-size: 14px; color: #C8D1DE !important">Topic</label>
<select id="q-topic" name="topic" style="min-height: 48px; padding: 0 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
<option>General question</option>
<option>Licensing</option>
<option>Research collaboration</option>
<option>Hardware / FPGA</option>
<option>Press &amp; media</option>
</select>
</div>
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-msg" style="font-size: 14px; color: #C8D1DE !important">Message</label>
<textarea id="q-msg" name="message" rows="7" style="padding: 12px 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px; resize: vertical"></textarea>
</div>
<div style="display: flex; align-items: flex-start; gap: 12px">
<input id="q-list" name="announcements" type="checkbox" style="width: 20px; height: 20px; margin: 3px 0 0; accent-color: #F5891F !important">
<label for="q-list" style="font-size: 14px; color: #C8D1DE !important">Also add me to launch announcements (low volume, unsubscribe anytime).</label>
</div>
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 16px">
<button type="submit" style="min-height: 48px; padding: 0 28px; background: #F5891F !important; color: #0A1222 !important; border: 0 !important; border-radius: 4px; font-family: inherit; font-weight: 700; font-size: 15px; cursor: pointer">Send inquiry</button>
<span style="font-size: 13px; color: #A3AEC2 !important">Replies usually within a few days.</span>
</div>
</form>
<aside aria-label="Direct addresses" style="flex: 1 1 300px; display: flex; flex-direction: column; gap: 24px">
<h2 style="margin: 0; font-family: 'Exo 2', sans-serif; font-size: 24px">Or write directly</h2>
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
<div style="font-size: 13px; color: #A3AEC2 !important">General</div>
<a href="mailto:info@starshipos.com" style="font-size: 16px">info@starshipos.com</a>
</div>
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
<div style="font-size: 13px; color: #A3AEC2 !important">Licensing &amp; partnerships</div>
<a href="mailto:licensing@starshipos.com" style="font-size: 16px">licensing@starshipos.com</a>
</div>
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
<div style="font-size: 13px; color: #A3AEC2 !important">Press &amp; media</div>
<a href="mailto:press@starshipos.com" style="font-size: 16px">press@starshipos.com</a>
</div>
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
<div style="font-size: 13px; color: #A3AEC2 !important">Security reports</div>
<a href="mailto:security@starshipos.org" style="font-size: 16px">security@starshipos.org</a>
</div>
<p style="margin: 0; padding-top: 16px; border-top: 1px solid #22324D !important; font-size: 13px; color: #A3AEC2 !important">StarshipOS is developed in Ashland, Ohio.</p>
</aside>
</section>
<footer style="border-top: 1px solid #22324D !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="/bin/view/Main/" style="color: #C8D1DE !important">Home</a><a href="https://starshipos-f18.org/" style="color: #C8D1DE !important">starshipos-f18.org</a></span>
</div>
</footer>
</div>
{{/html}}
+152
View File
@@ -0,0 +1,152 @@
{{velocity}}
#if ($isGuest)
#[[{{html clean="false"}}<style>
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
#xwikimaincontainerinner > a.btn { display: none !important; }
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
#xwikicontent > .ssos { border: 0 !important; }
#xwikimaincontainer { padding: 0 !important; }
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
</style>{{/html}}]]#
#end
{{/velocity}}
{{html clean="false"}}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">
<style>
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
.ssos a, .ssos a * { color: #F5891F !important; }
.ssos a:hover { color: #FFB061 !important; }
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
.ssos img { background-color: transparent !important; }
</style>
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 0">
<header style="border-bottom: 1px solid #22324D !important">
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span></a>
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
<a href="#system" style="color: #C8D1DE !important; text-decoration: none">System</a>
<a href="#research" style="color: #C8D1DE !important; text-decoration: none">Research</a>
<a href="#silicon" style="color: #C8D1DE !important; text-decoration: none">Silicon</a>
<a href="/bin/view/Inquiries/" style="color: #C8D1DE !important; text-decoration: none">Inquiries</a>
<a href="https://starshipos-f18.org/" style="color: #F5891F !important; text-decoration: none">Contributors →</a>
</div>
</nav>
</header>
<section style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 72px; display: flex; flex-wrap: wrap; align-items: center; gap: 56px">
<div style="flex: 999 1 520px; min-width: 0">
<p style="margin: 0 0 20px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">ok&gt; bare metal · FORTH · C99</p>
<h1 style="margin: 0 0 24px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(40px, 6vw, 68px); line-height: 1.05; letter-spacing: -0.01em">An operating system that obeys a conservation law.</h1>
<p style="margin: 0 0 36px; max-width: 620px; font-size: 18px; color: #C8D1DE !important">StarshipOS is a bare-metal operating system built from the ground up in StarForth and C99. One compudynamic engine governs every word, message, block and virtual machine — and holds K≡1.0 on every architecture it runs on.</p>
<div style="display: flex; flex-wrap: wrap; gap: 16px">
<a href="#system" style="display: inline-block; padding: 14px 24px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px">See how it works</a>
<a href="/bin/view/Inquiries/" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px">Make an inquiry</a>
</div>
</div>
<div style="flex: 1 1 400px; display: flex; justify-content: center">
<img src="/bin/download/Main/WebHome/badge.jpg" alt="StarshipOS badge: Santino the mascot inside a ring on a starfield" style="width: 100%; max-width: 540px; height: auto; display: block; border-radius: 8px; border: 1px solid #22324D !important">
</div>
</section>
<section aria-label="At a glance" style="border-top: 1px solid #22324D !important; border-bottom: 1px solid #22324D !important; background: #0E182B !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">38,400+</div><div style="font-size: 14px; color: #A3AEC2 !important">experimental runs validating K≡1.0</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">3 ISAs</div><div style="font-size: 14px; color: #A3AEC2 !important">amd64 · aarch64 · riscv64</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">FORTH-79</div><div style="font-size: 14px; color: #A3AEC2 !important">compliant core, live at the ok&gt; prompt</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">Patent pending</div><div style="font-size: 14px; color: #A3AEC2 !important">LithosAnanke kernel architecture</div></div>
</div>
</section>
<section id="system" style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">The system</p>
<h2 style="margin: 0 0 48px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">One engine. One fabric. Everything in it obeys the same physics.</h2>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">StarForth</h3>
<p style="margin: 0 0 16px; font-size: 13px; color: #F5891F !important">the language and the VM</p>
<p style="margin: 0; color: #C8D1DE !important">A FORTH-79 compliant adaptive virtual machine written in C99. Words execute by heat: what the system uses, it keeps close. Everything a user touches is StarForth — there is no compiler inside the box.</p>
</article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">LithosAnanke</h3>
<p style="margin: 0 0 16px; font-size: 13px; color: #F5891F !important">the microkernel</p>
<p style="margin: 0; color: #C8D1DE !important">A bare-metal microkernel built around the Stadium — a single fabric where words, messages, blocks and VMs live side by side, all governed by one compudynamic engine.</p>
</article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">The fleet</h3>
<p style="margin: 0 0 16px; font-size: 13px; color: #F5891F !important">VMs that are born, not spawned</p>
<p style="margin: 0; color: #C8D1DE !important">Hera births and governs the fleet. Artemis keeps the blocks. Console draws a vector framebuffer. Hermes, in the kernel, carries every message — and every message is checked against its ACL.</p>
</article>
</div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px; border-top: 1px solid #22324D !important; padding-top: 48px">
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Phenomenon first</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Observe the behaviour, then write the mathematics. Document before code.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Parity first</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">The same machine on every ISA, proven by reproducible dictionary hashes.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Identity on a key</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Your certificate lives on a thumb drive. No key, no session.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Minimal by design</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">A small core of primitives; everything else composed in FORTH.</p></div>
</div>
</section>
<section id="research" style="max-width: 1120px; margin: 0 auto; padding: 72px 24px">
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 40px; display: flex; flex-wrap: wrap; gap: 40px; align-items: center">
<div style="flex: 999 1 480px; min-width: 0">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Research</p>
<h2 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 32px; line-height: 1.2">James Law: K≡1.0</h2>
<p style="margin: 0; color: #C8D1DE !important">A conservation invariant that holds regardless of instruction set. Validated across 38,400+ runs in 128 configurations under QEMU on amd64, aarch64 and riscv64, and published on SSRN.</p>
</div>
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
<a href="https://starshipos-f18.org/" style="display: inline-block; padding: 14px 20px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">Read the paper</a>
<a href="https://starshipos-f18.org/" style="display: inline-block; padding: 14px 20px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px; text-align: center">Design docs on the .org</a>
</div>
</div>
</section>
<section id="silicon" style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Next: silicon</p>
<h2 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">From virtual machine to fabric.</h2>
<p style="margin: 0; max-width: 720px; color: #C8D1DE !important">StarForth V4 is being brought up as a mesh of tiny stack-machine cores on FPGA — words as instructions, messaging in hardware, and the compudynamic engine steering what runs and when. Same machine, same parity, now in logic.</p>
</section>
<section aria-labelledby="bridge-h" style="max-width: 1120px; margin: 0 auto; padding: 0 24px 96px">
<div style="display: flex; flex-wrap: wrap; gap: 48px; align-items: center; background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 8px; padding: 32px">
<img src="/bin/download/Main/WebHome/captain-bob.jpg" alt="Painted portrait of Captain Bob at a keyboard with a mug of coffee, wearing a StarshipOS jacket" style="flex: 1 1 260px; width: 100%; max-width: 340px; aspect-ratio: 2 / 3; height: auto; object-fit: cover; border-radius: 6px; display: block">
<div style="flex: 999 1 420px; min-width: 0">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">From the bridge</p>
<h2 id="bridge-h" style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 36px; line-height: 1.15">Built by one engineer, in the open.</h2>
<p style="margin: 0 0 24px; color: #C8D1DE !important">StarshipOS is designed and built by Captain Bob — Robert Allan James — drawing on roughly fifty years of embedded-systems work. Development happens in Ashland, Ohio, and in public on starshipos-f18.org.</p>
<a href="/bin/view/Inquiries/" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px">Get in touch</a>
</div>
</div>
</section>
<section aria-labelledby="signup-h" style="border-top: 1px solid #22324D !important; background: #0E182B !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 64px 24px; display: flex; flex-wrap: wrap; gap: 32px; align-items: center; justify-content: space-between">
<div style="flex: 1 1 360px; min-width: 0">
<h2 id="signup-h" style="margin: 0 0 8px; font-family: 'Exo 2', sans-serif; font-size: 28px">Launch announcements</h2>
<p style="margin: 0; color: #A3AEC2 !important; font-size: 14px">Milestones, releases and papers. Low volume. Unsubscribe anytime.</p>
</div>
<form action="mailto:info@starshipos.com?subject=Subscribe%20to%20launch%20announcements" method="post" enctype="text/plain" style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">
<label for="sub-email" style="position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0)">Email address</label>
<input id="sub-email" name="email" type="email" required placeholder="you@example.com" style="flex: 1 1 240px; min-height: 48px; padding: 0 16px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
<button type="submit" style="min-height: 48px; padding: 0 24px; background: #F5891F !important; color: #0A1222 !important; border: 0 !important; border-radius: 4px; font-family: inherit; font-weight: 700; font-size: 15px; cursor: pointer">Subscribe</button>
</form>
</div>
</section>
<footer style="border-top: 1px solid #22324D !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="/bin/view/Inquiries/" style="color: #C8D1DE !important">Inquiries</a><a href="mailto:info@starshipos.com" style="color: #C8D1DE !important">info@starshipos.com</a><a href="https://starshipos-f18.org/" style="color: #C8D1DE !important">starshipos-f18.org</a></span>
</div>
</footer>
</div>
{{/html}}
+18
View File
@@ -0,0 +1,18 @@
# site/com -- the starshipos-f18.com XWiki's pages
The public face of StarshipOS, made from the "StarshipOS.com" design canvas (claude.ai), whose
artboards are copied into `canvas/` as they are: Home (`Main.WebHome`), `Inquiries.WebHome`,
`TryIt.WebHome`. `build.py` turns each into one `{{html}}` block (a page author with script rights)
and says what changes on the way: the wiki's links and domains, the images as attachments
(`badge.jpg`, `captain-bob.jpg`, web-size copies of the canvas's), the real console in Try it, the
forms by e-mail. `install.sh` puts them on the wiki and checks a guest can read them:
```
site/com/build.py
XWIKI_USER=rajames XWIKI_PASSWORD=... site/com/install.sh
```
Change the design on the canvas, copy the artboard into `canvas/`, and run both again.
Installed 2026-11-07. Try it is on the wiki but not in the navigation (#117): its console,
`try.starshipos-f18.com`, is not served yet (#115).
+128
View File
@@ -0,0 +1,128 @@
{{velocity}}
#if ($isGuest)
#[[{{html clean="false"}}<style>
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
#xwikimaincontainerinner > a.btn { display: none !important; }
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
#xwikicontent > .ssos { border: 0 !important; }
#xwikimaincontainer { padding: 0 !important; }
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
</style>{{/html}}]]#
#end
{{/velocity}}
{{html clean="false"}}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">
<style>
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
.ssos a, .ssos a * { color: #F5891F !important; }
.ssos a:hover { color: #FFB061 !important; }
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
.ssos img { background-color: transparent !important; }
</style>
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 0">
<header style="border-bottom: 1px solid #22324D !important">
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span></a>
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
<a href="/bin/view/Main/" style="color: #C8D1DE !important; text-decoration: none">Home</a>
<a href="/bin/view/TryIt/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Try it</a>
<a href="/bin/view/Inquiries/" style="color: #C8D1DE !important; text-decoration: none">Inquiries</a>
<a href="https://starshipos-f18.org/" style="color: #F5891F !important; text-decoration: none">Contributors →</a>
</div>
</nav>
</header>
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">ok&gt; try it</p>
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">A StarshipOS machine of your own.</h1>
<p style="margin: 0; max-width: 680px; font-size: 18px; color: #C8D1DE !important">Not a recording, not a simulation of StarshipOS: the console below is a real machine, started just for you and already at its prompt. You are Zuse, the superuser — of a machine that exists only for your session. There is nothing to break, and nothing you do is kept.</p>
</section>
<section aria-label="The console" style="max-width: 1120px; margin: 0 auto; padding: 24px 24px 48px">
<div style="background: #050A14 !important; border: 1px solid #34486A !important; border-radius: 8px; overflow: hidden">
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 20px; border-bottom: 1px solid #22324D !important; background: #0E182B !important; font-size: 13px; color: #A3AEC2 !important">
<span style="display: flex; align-items: center; gap: 10px"><span aria-hidden="true" style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #4FD1B0 !important"></span>StarshipOS &#183; amd64 &#183; your session</span>
<span>try.starshipos-f18.com</span>
</div>
<iframe src="https://try.starshipos-f18.com/" title="StarshipOS console" style="display: block; width: 100%; height: 30em; border: 0 !important; background: #050A14 !important"></iframe>
</div>
<p style="margin: 12px 0 0; font-size: 13px; color: #A3AEC2 !important">If the console does not connect, every machine is in use: try again in a few minutes.</p>
</section>
<section aria-label="Your machine" style="border-top: 1px solid #22324D !important; border-bottom: 1px solid #22324D !important; background: #0E182B !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">Zuse</div><div style="font-size: 14px; color: #A3AEC2 !important">the superuser, of this machine only</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">amd64</div><div style="font-size: 14px; color: #A3AEC2 !important">LithosAnanke v2.1.0 · StarForth v4</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">30 min</div><div style="font-size: 14px; color: #A3AEC2 !important">then it is gone; reload for a new one</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">Offline</div><div style="font-size: 14px; color: #A3AEC2 !important">no network inside the machine</div></div>
</div>
</section>
<section aria-labelledby="try-h" style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Things to try</p>
<h2 id="try-h" style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">StarshipOS speaks FORTH.</h2>
<p style="margin: 0 0 40px; max-width: 680px; color: #C8D1DE !important">Type a line and press Enter. When the machine has done it, it answers ok.</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">You type</p>
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7 !important">3 4 + .</p>
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">It answers</p>
<p style="margin: 0 0 16px; font-size: 20px; color: #F5891F !important">7 ok</p>
<p style="margin: 0; font-size: 14px; color: #C8D1DE !important">Numbers go on a stack; + adds the top two; . prints the result.</p>
</article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">You type</p>
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7 !important">: SQUARE DUP * ;</p>
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">It answers</p>
<p style="margin: 0 0 16px; font-size: 20px; color: #F5891F !important">ok</p>
<p style="margin: 0; font-size: 14px; color: #C8D1DE !important">You have just taught the machine a new word, SQUARE.</p>
</article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">You type</p>
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7 !important">7 SQUARE .</p>
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">It answers</p>
<p style="margin: 0 0 16px; font-size: 20px; color: #F5891F !important">49 ok</p>
<p style="margin: 0; font-size: 14px; color: #C8D1DE !important">…and used it, as if it had always been there.</p>
</article>
</div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px; border-top: 1px solid #22324D !important; padding-top: 48px">
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">A machine of your own</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Resumed at its prompt from one that booted, passed its 538 power-on self-tests and logged Zuse in — so you never wait for a boot.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">The latest green build</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Always the most recent build that booted on amd64, aarch64 and riscv64 and passed every acceptance check.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">A Zuse of its own</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Zuse is whoever holds the identity drive. Here it is a demo Zuse minted for this page alone — not anyone's real identity.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Gone when you go</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Close the page, or let 30 minutes pass, and the machine is stopped and discarded. The next visitor starts clean.</p></div>
</div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 40px; display: flex; flex-wrap: wrap; gap: 40px; align-items: center">
<div style="flex: 999 1 480px; min-width: 0">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">A small server</p>
<h2 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 32px; line-height: 1.2">Emulated, so a little slower.</h2>
<p style="margin: 0; color: #C8D1DE !important">The demo runs in an emulator on a modest server: slower than StarshipOS on real hardware, and only a few machines at once. The real thing boots straight from firmware, with nothing beneath it.</p>
</div>
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
<a href="/bin/view/Main/" style="display: inline-block; padding: 14px 20px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">How it works</a>
<a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="display: inline-block; padding: 14px 20px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px; text-align: center">Read the source</a>
</div>
</div>
</section>
<footer style="border-top: 1px solid #22324D !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="/bin/view/Main/" style="color: #C8D1DE !important">Home</a><a href="/bin/view/Inquiries/" style="color: #C8D1DE !important">Inquiries</a><a href="https://starshipos-f18.org/" style="color: #C8D1DE !important">starshipos-f18.org</a></span>
</div>
</footer>
</div>
{{/html}}
Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

+103
View File
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
"""build.py -- the starshipos-f18.com XWiki pages, made from the "StarshipOS.com" design canvas.
site/com/build.py canvas/{Main,Inquiries,TryIt}.dc.html -> {Main,Inquiries,TryIt}.WebHome.xwiki
The canvas is the source: its artboards are copied into canvas/ as they are, and this turns each into
one {{html}} block (which needs a page author with script rights). What changes on the way:
- the accent hole becomes its default colour, and the canvas's links become the wiki's pages
(Main.dc.html -> /bin/view/Main/, ...) and the real domains (starshipos.org -> starshipos-f18.org);
- the two images become attachments of Main.WebHome (badge.jpg, captain-bob.jpg -- web-size copies
of the canvas's uploads);
- Try it: the drawn console becomes the real one, an iframe of try.starshipos-f18.com;
- the inquiry form posts to the .org's PublicInquiry, which files it under Inquiries there
(admin-only, site/org/inquiries); the announcements form, which has no server, sends by e-mail;
- a link the canvas left as a placeholder ([SSRN PAPER URL]) points at the .org until it is given.
install.sh puts the pages and the images on the wiki.
"""
import os
import re
import sys
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
import colorlock # noqa: E402 the design's colours over the wiki's high-contrast theme
ACCENT = "#F5891F"
FONTS = ('<link rel="preconnect" href="https://fonts.googleapis.com">\n'
'<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700'
'&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">')
ORG = "https://starshipos-f18.org/"
PAGES = ["Main", "Inquiries", "TryIt"]
IMAGES = {"/_blob/5b564d54d98e02ad600c913a9a1888f2": "badge.jpg",
"/_blob/5483451f292782a8b366e437181c4bcf": "captain-bob.jpg"}
CONSOLE = '''<div style="background: #050A14; border: 1px solid #34486A; border-radius: 8px; overflow: hidden">
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 20px; border-bottom: 1px solid #22324D; background: #0E182B; font-size: 13px; color: #A3AEC2">
<span style="display: flex; align-items: center; gap: 10px"><span aria-hidden="true" style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #4FD1B0"></span>StarshipOS &#183; amd64 &#183; your session</span>
<span>try.starshipos-f18.com</span>
</div>
<iframe src="https://try.starshipos-f18.com/" title="StarshipOS console" style="display: block; width: 100%; height: 30em; border: 0; background: #050A14"></iframe>
</div>
<p style="margin: 12px 0 0; font-size: 13px; color: #A3AEC2">If the console does not connect, every machine is in use: try again in a few minutes.</p>'''
def body(src):
m = re.search(r"<x-dc>(.*)</x-dc>", src, re.S)
html = re.sub(r"<helmet>.*?</helmet>", "", m.group(1), flags=re.S).strip()
html = html.replace("{{accent}}", ACCENT)
for p in PAGES:
html = html.replace('href="%s.dc.html"' % p, 'href="/bin/view/%s/"' % p)
html = html.replace('href="https://starshipos.org"', 'href="%s"' % ORG)
html = html.replace(">starshipos.org</a>", ">starshipos-f18.org</a>")
html = html.replace("on starshipos.org.", "on starshipos-f18.org.")
html = html.replace('href="[SSRN PAPER URL]"', 'href="%s"' % ORG)
for blob, name in IMAGES.items():
html = html.replace('src="%s"' % blob, 'src="/bin/download/Main/WebHome/%s"' % name)
html = html.replace("min-height: 100vh", "min-height: 0") # inside the wiki's page, not a screen
return html
def try_it(html):
start = html.index('<div style="background: #050A14')
end = html.index("</p>", html.index("[LIVE CONSOLE]")) + len("</p>")
return html[:start] + CONSOLE + html[end:]
def forms(html, page):
if page == "Main":
html = html.replace('<form style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">',
'<form action="mailto:info@starshipos.com?subject=Subscribe%20to%20launch%20announcements" method="post" enctype="text/plain" style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">')
html = html.replace('<input id="sub-email" type="email"', '<input id="sub-email" name="email" type="email" required')
html = html.replace('<button type="button" style="min-height: 48px; padding: 0 24px',
'<button type="submit" style="min-height: 48px; padding: 0 24px')
if page == "Inquiries":
html = html.replace('<form aria-label="Inquiry form"',
'<form action="https://starshipos-f18.org/bin/view/PublicInquiry/" method="post" aria-label="Inquiry form"')
# a field people cannot see; a robot fills it, and PublicInquiry keeps nothing it sends
html = html.replace('<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px">',
'<div aria-hidden="true" style="position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden">'
'<label for="q-website">Leave this empty</label><input id="q-website" name="website" type="text" tabindex="-1" autocomplete="off"></div>\n'
'<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px">', 1)
for i, n in (("q-name", "name"), ("q-email", "email"), ("q-org", "organization"), ("q-topic", "topic"),
("q-msg", "message"), ("q-list", "announcements")):
html = html.replace('id="%s"' % i, 'id="%s" name="%s"' % (i, n), 1)
html = html.replace('<button type="button" style="min-height: 48px; padding: 0 28px',
'<button type="submit" style="min-height: 48px; padding: 0 28px')
html = html.replace("Replies usually within a few days.",
"Replies usually within a few days.")
return html
if __name__ == "__main__":
os.chdir(os.path.dirname(os.path.abspath(__file__)))
for p in PAGES:
html = forms(body(open("canvas/%s.dc.html" % p).read()), p)
if p == "TryIt":
html = try_it(html)
html = colorlock.lock(html, '<div style="background: #0A1222')
assert "{{" not in html.replace(colorlock.STYLE, "") and "[SSRN" not in html and ".dc.html" not in html and "_blob" not in html, p
with open("%s.WebHome.xwiki" % p, "w") as f:
f.write(colorlock.GUEST_CHROME + '{{html clean="false"}}\n%s\n%s\n{{/html}}\n' % (FONTS, html))
print("wrote", ", ".join("%s.WebHome.xwiki" % p for p in PAGES))
+118
View File
@@ -0,0 +1,118 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>StarshipOS — Inquiries</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">
<style>
body{margin:0;background:#0A1222}
a{color:#F5891F}a:hover{color:#FFB061}
</style>
</helmet>
<div style="background: #0A1222; color: #EEF2F7; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 100vh">
<header style="border-bottom: 1px solid #22324D">
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
<a href="Main.dc.html" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {{accent}}">OS</span></a>
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
<a href="Main.dc.html" style="color: #C8D1DE; text-decoration: none">Home</a>
<a href="Inquiries.dc.html" aria-current="page" style="color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {{accent}}">Inquiries</a>
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
</div>
</nav>
</header>
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Inquiries</p>
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">Talk to the bridge.</h1>
<p style="margin: 0; max-width: 640px; font-size: 18px; color: #C8D1DE">Licensing, research collaboration, press or plain curiosity — every message is read by a human. Want to contribute code? Head to <a href="https://starshipos.org">starshipos.org</a>.</p>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 32px 24px 96px; display: flex; flex-wrap: wrap; gap: 48px; align-items: flex-start">
<form aria-label="Inquiry form" style="flex: 999 1 520px; min-width: 0; background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 32px; display: flex; flex-direction: column; gap: 20px">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px">
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-name" style="font-size: 14px; color: #C8D1DE">Name</label>
<input id="q-name" type="text" autocomplete="name" style="min-height: 48px; padding: 0 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
</div>
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-email" style="font-size: 14px; color: #C8D1DE">Email</label>
<input id="q-email" type="email" autocomplete="email" style="min-height: 48px; padding: 0 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
</div>
</div>
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-org" style="font-size: 14px; color: #C8D1DE">Organization <span style="color: #A3AEC2">(optional)</span></label>
<input id="q-org" type="text" autocomplete="organization" style="min-height: 48px; padding: 0 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
</div>
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-topic" style="font-size: 14px; color: #C8D1DE">Topic</label>
<select id="q-topic" style="min-height: 48px; padding: 0 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
<option>General question</option>
<option>Licensing</option>
<option>Research collaboration</option>
<option>Hardware / FPGA</option>
<option>Press &amp; media</option>
</select>
</div>
<div style="display: flex; flex-direction: column; gap: 8px">
<label for="q-msg" style="font-size: 14px; color: #C8D1DE">Message</label>
<textarea id="q-msg" rows="7" style="padding: 12px 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px; resize: vertical"></textarea>
</div>
<div style="display: flex; align-items: flex-start; gap: 12px">
<input id="q-list" type="checkbox" style="width: 20px; height: 20px; margin: 3px 0 0; accent-color: {{accent}}">
<label for="q-list" style="font-size: 14px; color: #C8D1DE">Also add me to launch announcements (low volume, unsubscribe anytime).</label>
</div>
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 16px">
<button type="button" style="min-height: 48px; padding: 0 28px; background: {{accent}}; color: #0A1222; border: 0; border-radius: 4px; font-family: inherit; font-weight: 700; font-size: 15px; cursor: pointer">Send inquiry</button>
<span style="font-size: 13px; color: #A3AEC2">Replies usually within a few days.</span>
</div>
</form>
<aside aria-label="Direct addresses" style="flex: 1 1 300px; display: flex; flex-direction: column; gap: 24px">
<h2 style="margin: 0; font-family: 'Exo 2', sans-serif; font-size: 24px">Or write directly</h2>
<div style="border-top: 1px solid #22324D; padding-top: 16px">
<div style="font-size: 13px; color: #A3AEC2">General</div>
<a href="mailto:info@starshipos.com" style="font-size: 16px">info@starshipos.com</a>
</div>
<div style="border-top: 1px solid #22324D; padding-top: 16px">
<div style="font-size: 13px; color: #A3AEC2">Licensing &amp; partnerships</div>
<a href="mailto:licensing@starshipos.com" style="font-size: 16px">licensing@starshipos.com</a>
</div>
<div style="border-top: 1px solid #22324D; padding-top: 16px">
<div style="font-size: 13px; color: #A3AEC2">Press &amp; media</div>
<a href="mailto:press@starshipos.com" style="font-size: 16px">press@starshipos.com</a>
</div>
<div style="border-top: 1px solid #22324D; padding-top: 16px">
<div style="font-size: 13px; color: #A3AEC2">Security reports</div>
<a href="mailto:security@starshipos.org" style="font-size: 16px">security@starshipos.org</a>
</div>
<p style="margin: 0; padding-top: 16px; border-top: 1px solid #22324D; font-size: 13px; color: #A3AEC2">StarshipOS is developed in Ashland, Ohio.</p>
</aside>
</section>
<footer style="border-top: 1px solid #22324D">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2">
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Main.dc.html" style="color: #C8D1DE">Home</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
</div>
</footer>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":1700}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#F5891F' };
}
}
</script>
</body>
</html>
+151
View File
@@ -0,0 +1,151 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>StarshipOS — Home</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">
<style>
body{margin:0;background:#0A1222}
a{color:#F5891F}a:hover{color:#FFB061}
</style>
</helmet>
<div style="background: #0A1222; color: #EEF2F7; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 100vh">
<header style="border-bottom: 1px solid #22324D">
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
<a href="Main.dc.html" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {{accent}}">OS</span></a>
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
<a href="#system" style="color: #C8D1DE; text-decoration: none">System</a>
<a href="#research" style="color: #C8D1DE; text-decoration: none">Research</a>
<a href="#silicon" style="color: #C8D1DE; text-decoration: none">Silicon</a>
<a href="Inquiries.dc.html" style="color: #C8D1DE; text-decoration: none">Inquiries</a>
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
</div>
</nav>
</header>
<section style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 72px; display: flex; flex-wrap: wrap; align-items: center; gap: 56px">
<div style="flex: 999 1 520px; min-width: 0">
<p style="margin: 0 0 20px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0">ok&gt; bare metal · FORTH · C99</p>
<h1 style="margin: 0 0 24px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(40px, 6vw, 68px); line-height: 1.05; letter-spacing: -0.01em">An operating system that obeys a conservation law.</h1>
<p style="margin: 0 0 36px; max-width: 620px; font-size: 18px; color: #C8D1DE">StarshipOS is a bare-metal operating system built from the ground up in StarForth and C99. One compudynamic engine governs every word, message, block and virtual machine — and holds K≡1.0 on every architecture it runs on.</p>
<div style="display: flex; flex-wrap: wrap; gap: 16px">
<a href="#system" style="display: inline-block; padding: 14px 24px; background: {{accent}}; color: #0A1222; font-weight: 700; text-decoration: none; border-radius: 4px">See how it works</a>
<a href="Inquiries.dc.html" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px">Make an inquiry</a>
</div>
</div>
<div style="flex: 1 1 400px; display: flex; justify-content: center">
<img src="/_blob/5b564d54d98e02ad600c913a9a1888f2" alt="StarshipOS badge: Santino the mascot inside a ring on a starfield" style="width: 100%; max-width: 540px; height: auto; display: block; border-radius: 8px; border: 1px solid #22324D">
</div>
</section>
<section aria-label="At a glance" style="border-top: 1px solid #22324D; border-bottom: 1px solid #22324D; background: #0E182B">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">38,400+</div><div style="font-size: 14px; color: #A3AEC2">experimental runs validating K≡1.0</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">3 ISAs</div><div style="font-size: 14px; color: #A3AEC2">amd64 · aarch64 · riscv64</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">FORTH-79</div><div style="font-size: 14px; color: #A3AEC2">compliant core, live at the ok&gt; prompt</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">Patent pending</div><div style="font-size: 14px; color: #A3AEC2">LithosAnanke kernel architecture</div></div>
</div>
</section>
<section id="system" style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">The system</p>
<h2 style="margin: 0 0 48px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">One engine. One fabric. Everything in it obeys the same physics.</h2>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">StarForth</h3>
<p style="margin: 0 0 16px; font-size: 13px; color: {{accent}}">the language and the VM</p>
<p style="margin: 0; color: #C8D1DE">A FORTH-79 compliant adaptive virtual machine written in C99. Words execute by heat: what the system uses, it keeps close. Everything a user touches is StarForth — there is no compiler inside the box.</p>
</article>
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">LithosAnanke</h3>
<p style="margin: 0 0 16px; font-size: 13px; color: {{accent}}">the microkernel</p>
<p style="margin: 0; color: #C8D1DE">A bare-metal microkernel built around the Stadium — a single fabric where words, messages, blocks and VMs live side by side, all governed by one compudynamic engine.</p>
</article>
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">The fleet</h3>
<p style="margin: 0 0 16px; font-size: 13px; color: {{accent}}">VMs that are born, not spawned</p>
<p style="margin: 0; color: #C8D1DE">Hera births and governs the fleet. Artemis keeps the blocks. Console draws a vector framebuffer. Hermes, in the kernel, carries every message — and every message is checked against its ACL.</p>
</article>
</div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px; border-top: 1px solid #22324D; padding-top: 48px">
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Phenomenon first</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Observe the behaviour, then write the mathematics. Document before code.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Parity first</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">The same machine on every ISA, proven by reproducible dictionary hashes.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Identity on a key</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Your certificate lives on a thumb drive. No key, no session.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Minimal by design</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">A small core of primitives; everything else composed in FORTH.</p></div>
</div>
</section>
<section id="research" style="max-width: 1120px; margin: 0 auto; padding: 72px 24px">
<div style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 40px; display: flex; flex-wrap: wrap; gap: 40px; align-items: center">
<div style="flex: 999 1 480px; min-width: 0">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Research</p>
<h2 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 32px; line-height: 1.2">James Law: K≡1.0</h2>
<p style="margin: 0; color: #C8D1DE">A conservation invariant that holds regardless of instruction set. Validated across 38,400+ runs in 128 configurations under QEMU on amd64, aarch64 and riscv64, and published on SSRN.</p>
</div>
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
<a href="[SSRN PAPER URL]" style="display: inline-block; padding: 14px 20px; background: {{accent}}; color: #0A1222; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">Read the paper</a>
<a href="https://starshipos.org" style="display: inline-block; padding: 14px 20px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px; text-align: center">Design docs on the .org</a>
</div>
</div>
</section>
<section id="silicon" style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Next: silicon</p>
<h2 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">From virtual machine to fabric.</h2>
<p style="margin: 0; max-width: 720px; color: #C8D1DE">StarForth V4 is being brought up as a mesh of tiny stack-machine cores on FPGA — words as instructions, messaging in hardware, and the compudynamic engine steering what runs and when. Same machine, same parity, now in logic.</p>
</section>
<section aria-labelledby="bridge-h" style="max-width: 1120px; margin: 0 auto; padding: 0 24px 96px">
<div style="display: flex; flex-wrap: wrap; gap: 48px; align-items: center; background: #111C30; border: 1px solid #22324D; border-radius: 8px; padding: 32px">
<img src="/_blob/5483451f292782a8b366e437181c4bcf" alt="Painted portrait of Captain Bob at a keyboard with a mug of coffee, wearing a StarshipOS jacket" style="flex: 1 1 260px; width: 100%; max-width: 340px; aspect-ratio: 2 / 3; height: auto; object-fit: cover; border-radius: 6px; display: block">
<div style="flex: 999 1 420px; min-width: 0">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0">From the bridge</p>
<h2 id="bridge-h" style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 36px; line-height: 1.15">Built by one engineer, in the open.</h2>
<p style="margin: 0 0 24px; color: #C8D1DE">StarshipOS is designed and built by Captain Bob — Robert Allan James — drawing on roughly fifty years of embedded-systems work. Development happens in Ashland, Ohio, and in public on starshipos.org.</p>
<a href="Inquiries.dc.html" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px">Get in touch</a>
</div>
</div>
</section>
<section aria-labelledby="signup-h" style="border-top: 1px solid #22324D; background: #0E182B">
<div style="max-width: 1120px; margin: 0 auto; padding: 64px 24px; display: flex; flex-wrap: wrap; gap: 32px; align-items: center; justify-content: space-between">
<div style="flex: 1 1 360px; min-width: 0">
<h2 id="signup-h" style="margin: 0 0 8px; font-family: 'Exo 2', sans-serif; font-size: 28px">Launch announcements</h2>
<p style="margin: 0; color: #A3AEC2; font-size: 14px">Milestones, releases and papers. Low volume. Unsubscribe anytime.</p>
</div>
<form style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">
<label for="sub-email" style="position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0)">Email address</label>
<input id="sub-email" type="email" placeholder="you@example.com" style="flex: 1 1 240px; min-height: 48px; padding: 0 16px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
<button type="button" style="min-height: 48px; padding: 0 24px; background: {{accent}}; color: #0A1222; border: 0; border-radius: 4px; font-family: inherit; font-weight: 700; font-size: 15px; cursor: pointer">Subscribe</button>
</form>
</div>
</section>
<footer style="border-top: 1px solid #22324D">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2">
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Inquiries.dc.html" style="color: #C8D1DE">Inquiries</a><a href="mailto:info@starshipos.com" style="color: #C8D1DE">info@starshipos.com</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
</div>
</footer>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":3700}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#F5891F' };
}
}
</script>
</body>
</html>
+136
View File
@@ -0,0 +1,136 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>StarshipOS — Try it</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">
<style>
body{margin:0;background:#0A1222}
a{color:#F5891F}a:hover{color:#FFB061}
</style>
</helmet>
<div style="background: #0A1222; color: #EEF2F7; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 100vh">
<header style="border-bottom: 1px solid #22324D">
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
<a href="Main.dc.html" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {{accent}}">OS</span></a>
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
<a href="Main.dc.html" style="color: #C8D1DE; text-decoration: none">Home</a>
<a href="TryIt.dc.html" aria-current="page" style="color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {{accent}}">Try it</a>
<a href="Inquiries.dc.html" style="color: #C8D1DE; text-decoration: none">Inquiries</a>
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
</div>
</nav>
</header>
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0">ok&gt; try it</p>
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">A StarshipOS machine of your own.</h1>
<p style="margin: 0; max-width: 680px; font-size: 18px; color: #C8D1DE">Not a recording, not a simulation of StarshipOS: the console below is a real machine, started just for you and already at its prompt. You are Zuse, the superuser — of a machine that exists only for your session. There is nothing to break, and nothing you do is kept.</p>
</section>
<section aria-label="The console" style="max-width: 1120px; margin: 0 auto; padding: 24px 24px 48px">
<div style="background: #050A14; border: 1px solid #34486A; border-radius: 8px; overflow: hidden">
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 20px; border-bottom: 1px solid #22324D; background: #0E182B; font-size: 13px; color: #A3AEC2">
<span style="display: flex; align-items: center; gap: 10px"><span aria-hidden="true" style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #4FD1B0"></span>StarshipOS · amd64 · your session</span>
<span>try.starshipos-f18.com</span>
</div>
<div style="padding: 24px; min-height: 360px; font-size: 15px; line-height: 1.7; color: #EEF2F7; overflow-x: auto">
<div style="color: #A3AEC2">StarshipOS -- starting a throwaway machine, yours for up to 30 minutes. Nothing you do is kept.</div>
<div style="color: #A3AEC2">Try: 3 4 + . : SQUARE DUP * ; 7 SQUARE .</div>
<div style="color: #A3AEC2; margin-bottom: 12px">Ready -- type a line and press Enter.</div>
<div><span style="color: #FFA500">[zuse@Hera]</span> <span style="color: #55FFFF">ok&gt;</span> 3 4 + .</div>
<div><span style="color: #FFA500">[zuse@Hera]</span> 7 ok</div>
<div><span style="color: #FFA500">[zuse@Hera]</span> <span style="color: #55FFFF">ok&gt;</span> : SQUARE DUP * ; 7 SQUARE .</div>
<div><span style="color: #FFA500">[zuse@Hera]</span> 49 ok</div>
<div><span style="color: #FFA500">[zuse@Hera]</span> <span style="color: #55FFFF">ok&gt;</span> <span aria-hidden="true" style="display: inline-block; width: 9px; height: 18px; vertical-align: text-bottom; background: #EEF2F7"></span></div>
</div>
</div>
<p style="margin: 12px 0 0; font-size: 13px; color: #A3AEC2">[LIVE CONSOLE] On the site this panel is the machine itself — the console of try.starshipos-f18.com, embedded. If it does not connect, every machine is in use; try again in a few minutes.</p>
</section>
<section aria-label="Your machine" style="border-top: 1px solid #22324D; border-bottom: 1px solid #22324D; background: #0E182B">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">Zuse</div><div style="font-size: 14px; color: #A3AEC2">the superuser, of this machine only</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">amd64</div><div style="font-size: 14px; color: #A3AEC2">LithosAnanke v2.1.0 · StarForth v4</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">30 min</div><div style="font-size: 14px; color: #A3AEC2">then it is gone; reload for a new one</div></div>
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">Offline</div><div style="font-size: 14px; color: #A3AEC2">no network inside the machine</div></div>
</div>
</section>
<section aria-labelledby="try-h" style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Things to try</p>
<h2 id="try-h" style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">StarshipOS speaks FORTH.</h2>
<p style="margin: 0 0 40px; max-width: 680px; color: #C8D1DE">Type a line and press Enter. When the machine has done it, it answers ok.</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">You type</p>
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7">3 4 + .</p>
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">It answers</p>
<p style="margin: 0 0 16px; font-size: 20px; color: {{accent}}">7 ok</p>
<p style="margin: 0; font-size: 14px; color: #C8D1DE">Numbers go on a stack; + adds the top two; . prints the result.</p>
</article>
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">You type</p>
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7">: SQUARE DUP * ;</p>
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">It answers</p>
<p style="margin: 0 0 16px; font-size: 20px; color: {{accent}}">ok</p>
<p style="margin: 0; font-size: 14px; color: #C8D1DE">You have just taught the machine a new word, SQUARE.</p>
</article>
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">You type</p>
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7">7 SQUARE .</p>
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">It answers</p>
<p style="margin: 0 0 16px; font-size: 20px; color: {{accent}}">49 ok</p>
<p style="margin: 0; font-size: 14px; color: #C8D1DE">…and used it, as if it had always been there.</p>
</article>
</div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px; border-top: 1px solid #22324D; padding-top: 48px">
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">A machine of your own</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Resumed at its prompt from one that booted, passed its 538 power-on self-tests and logged Zuse in — so you never wait for a boot.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">The latest green build</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Always the most recent build that booted on amd64, aarch64 and riscv64 and passed every acceptance check.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">A Zuse of its own</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Zuse is whoever holds the identity drive. Here it is a demo Zuse minted for this page alone — not anyone's real identity.</p></div>
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Gone when you go</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Close the page, or let 30 minutes pass, and the machine is stopped and discarded. The next visitor starts clean.</p></div>
</div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
<div style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 40px; display: flex; flex-wrap: wrap; gap: 40px; align-items: center">
<div style="flex: 999 1 480px; min-width: 0">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">A small server</p>
<h2 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 32px; line-height: 1.2">Emulated, so a little slower.</h2>
<p style="margin: 0; color: #C8D1DE">The demo runs in an emulator on a modest server: slower than StarshipOS on real hardware, and only a few machines at once. The real thing boots straight from firmware, with nothing beneath it.</p>
</div>
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
<a href="Main.dc.html" style="display: inline-block; padding: 14px 20px; background: {{accent}}; color: #0A1222; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">How it works</a>
<a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="display: inline-block; padding: 14px 20px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px; text-align: center">Read the source</a>
</div>
</div>
</section>
<footer style="border-top: 1px solid #22324D">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2">
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Main.dc.html" style="color: #C8D1DE">Home</a><a href="Inquiries.dc.html" style="color: #C8D1DE">Inquiries</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
</div>
</footer>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":2900}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#F5891F' };
}
}
</script>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

+49
View File
@@ -0,0 +1,49 @@
#!/bin/bash
# install.sh -- the starshipos-f18.com XWiki's pages, from the "StarshipOS.com" design canvas
# (build.py makes them): Main.WebHome (Home), Inquiries.WebHome, TryIt.WebHome, and the two
# images, attachments of Main.WebHome. All readable by everyone; the wiki's own rights decide the
# rest. Through XWiki's REST API:
#
# XWIKI_USER=rajames XWIKI_PASSWORD=... site/com/install.sh [https://starshipos-f18.com]
#
# Run it again after build.py: pages and images are replaced. It ends by checking, without
# logging in, that every page and image is there.
set -euo pipefail
cd "$(dirname "$0")"
base=${1:-https://starshipos-f18.com}
rest="$base/rest/wikis/xwiki"
user=${XWIKI_USER:?set XWIKI_USER}
pass=${XWIKI_PASSWORD:?set XWIKI_PASSWORD}
auth=(-u "$user:$pass")
page() { # page <space> <title> <file>: create or replace <space>.WebHome
local body
body=$(python3 -c '
import sys
from xml.sax.saxutils import escape
print("<page xmlns=\"http://www.xwiki.org\"><title>%s</title><syntax>xwiki/2.1</syntax>"
"<content>%s</content></page>" % (escape(sys.argv[1]), escape(open(sys.argv[2]).read())))' "$2" "$3")
curl -fsS -o /dev/null -w " page $1.WebHome: %{http_code}\n" "${auth[@]}" -X PUT \
-H 'Content-Type: application/xml' --data-binary "$body" "$rest/spaces/$1/pages/WebHome"
}
attach() { # attach <space> <file>: create or replace an attachment of <space>.WebHome
curl -fsS -o /dev/null -w " attachment $1.WebHome/$2: %{http_code}\n" "${auth[@]}" -X PUT \
-H 'Content-Type: image/jpeg' --data-binary "@$2" "$rest/spaces/$1/pages/WebHome/attachments/$2"
}
echo "=== $base, as $user"
page Main "StarshipOS" Main.WebHome.xwiki
attach Main badge.jpg
attach Main captain-bob.jpg
page Inquiries "Inquiries" Inquiries.WebHome.xwiki
page TryIt "Try StarshipOS" TryIt.WebHome.xwiki
echo "=== as a guest"
bad=
for u in /bin/view/Main/ /bin/view/Inquiries/ /bin/view/TryIt/ \
/bin/download/Main/WebHome/badge.jpg /bin/download/Main/WebHome/captain-bob.jpg; do
code=$(curl -s -o /dev/null -w '%{http_code}' "$base$u")
if [ "$code" = 200 ]; then echo " $u: 200"; else echo " $u: $code -- NOT readable"; bad=1; fi
done
[ -z "$bad" ] || { echo "install: a guest cannot read everything; see above" >&2; exit 1; }
echo "=== done: $base/bin/view/Main/"
+62
View File
@@ -0,0 +1,62 @@
{{html clean="false"}}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">
<style>
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
.ssos a, .ssos a * { color: #F5891F !important; }
.ssos a:hover { color: #FFB061 !important; }
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
.ssos img { background-color: transparent !important; }
</style>
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6">
<header style="border-bottom: 1px solid #22324D !important">
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span><span style="font-size: 14px; color: #A3AEC2 !important; margin-left: 6px">.org</span></a>
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px"><a href="/bin/view/Main/" style="color: #C8D1DE !important; text-decoration: none">Home</a><a href="/bin/view/Contributors/" style="color: #C8D1DE !important; text-decoration: none">Contributors</a><a href="/bin/view/Admin/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Admin</a><a href="https://starshipos-f18.com/" style="color: #F5891F !important; text-decoration: none">starshipos-f18.com &#8594;</a></div>
</nav>
</header>
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">Administrator only</p>
<h1 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(36px, 5vw, 56px); line-height: 1.08">Admin dashboard.</h1>
<p style="margin: 0 0 32px; max-width: 680px; font-size: 18px; color: #C8D1DE !important">Seen by <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">XWiki.rajames</code> alone: the Admin space allows view and edit to that account and nobody else.</p>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 0 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">CI</p>
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">Every workflow, live.</h2>
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Acceptance -- the gate on every PR into master</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/acceptance.yml/badge.svg" alt="acceptance.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=acceptance.yml" style="font-size: 13px">runs</a></span></div>
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Build -- the quick check on StarForth-v4.0.0</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/build.yml/badge.svg?branch=StarForth-v4.0.0" alt="build.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=build.yml" style="font-size: 13px">runs</a></span></div>
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly -- acceptance, images to Nexus, proofs (03:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly.yml/badge.svg?branch=master" alt="nightly.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=nightly.yml" style="font-size: 13px">runs</a></span></div>
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly documents (04:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly-docs.yml/badge.svg?branch=master" alt="nightly-docs.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=nightly-docs.yml" style="font-size: 13px">runs</a></span></div>
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Runner image</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/runner-image.yml/badge.svg?branch=master" alt="runner-image.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=runner-image.yml" style="font-size: 13px">runs</a></span></div>
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Release -- a v&lt;version&gt; tag</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/release.yml/badge.svg" alt="release.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=release.yml" style="font-size: 13px">runs</a></span></div></div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 0 24px 96px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Run the project</p>
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">Work, artifacts, sites.</h2>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px">
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Work</h3>
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">Gitea</p>
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/pulls?state=open">Open pull requests</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open">Open issues</a> &#8212; <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=23">in progress</a>, <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=20">blocked</a>, <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=21">needs acceptance</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/milestones">Milestones</a> and <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/projects">the project board</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/settings/branches">Branch protection</a> &#8212; master: no pushes, merges only after Acceptance</li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/settings/actions/secrets">Actions secrets</a> &#8212; <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">NEXUS_CI_PASSWORD</code>, <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">PACKAGES_TOKEN</code>, <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">CAPSULE_SIGN_KEY</code></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/settings/actions/runners">Runners</a></li><li><a href="https://gitea.starshipos-f18.org/user/settings/applications">Access tokens</a> &#8212; revoke what a session no longer needs</li></ul>
</article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Artifacts</h3>
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">Nexus and packages</p>
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li><a href="https://nexus.starshipos-f18.org/#browse/browse:starshipos-snapshots:org%2Fstarship">Snapshots</a> &#8212; <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">kernelImage</code> (pc, raspi5, milkv, logs), <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">documentation</code> (book, vol1&#8211;vol3, api)</li><li><a href="https://nexus.starshipos-f18.org/#browse/browse:starshipos-releases:org%2Fstarship">Releases</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/-/packages">Container images</a> &#8212; <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">lithosananke-runner</code></li></ul>
</article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Sites</h3>
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">and the wiki itself</p>
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li><a href="https://starshipos-f18.com/">starshipos-f18.com</a> and <a href="https://starshipos-f18.com/bin/view/TryIt/">Try it</a></li><li><a href="/bin/view/Contributors/">Contributors' dashboard</a></li><li><a href="/bin/admin/XWiki/XWikiPreferences">Wiki administration</a> &#8212; users, the group <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">XWiki.StarshipContributors</code>, rights</li></ul>
</article>
</div>
</section>
<footer style="border-top: 1px solid #22324D !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
<span>&#169; 2026 Robert Allan James &#183; A Starship Foundation project (in formation)</span>
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="color: #C8D1DE !important">Source</a><a href="https://starshipos-f18.com/" style="color: #C8D1DE !important">starshipos-f18.com</a></span>
</div>
</footer>
</div>
{{/html}}
+72
View File
@@ -0,0 +1,72 @@
{{html clean="false"}}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">
<style>
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
.ssos a, .ssos a * { color: #F5891F !important; }
.ssos a:hover { color: #FFB061 !important; }
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
.ssos img { background-color: transparent !important; }
</style>
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6">
<header style="border-bottom: 1px solid #22324D !important">
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span><span style="font-size: 14px; color: #A3AEC2 !important; margin-left: 6px">.org</span></a>
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px"><a href="/bin/view/Main/" style="color: #C8D1DE !important; text-decoration: none">Home</a><a href="/bin/view/Contributors/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Contributors</a><a href="https://starshipos-f18.com/" style="color: #F5891F !important; text-decoration: none">starshipos-f18.com &#8594;</a></div>
</nav>
</header>
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">Contributors</p>
<h1 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(36px, 5vw, 56px); line-height: 1.08">Contributors' dashboard.</h1>
<p style="margin: 0 0 32px; max-width: 680px; font-size: 18px; color: #C8D1DE !important">For the members of <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">XWiki.StarshipContributors</code> and the administrator. Ask Captain Bob to be added.</p>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 0 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">How we work</p>
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">The Captain Bob method.</h2>
<p style="margin: 0 0 32px; max-width: 720px; color: #C8D1DE !important">Neither agile nor waterfall: one process from the developer's desk to master.</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 24px">
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">1</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Found</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">An issue says what is wrong or missing, with the evidence: a log, a line of code.</p></article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">2</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Ruled</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">Captain Bob decides what is to be done. Nothing is built without a ruling, and no fix nobody asked for.</p></article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">3</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Built</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">On the working branch, <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">StarForth-v4.0.0</code>. C99, no GNU extensions; compose in FORTH before adding a C word.</p></article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">4</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Verified</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">The acceptance protocol, below; its logs are committed under <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">logs/</code>.</p></article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">5</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Merged</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">A pull request into <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">master</code>, which runs acceptance by itself. master takes nothing else.</p></article>
</div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">The acceptance protocol</p>
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">In this order, one QEMU at a time, in the foreground.</h2>
<pre style="margin: 0 0 24px; background: #0E182B !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 24px; overflow-x: auto; font-size: 14px; color: #EEF2F7 !important">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</pre>
<p style="margin: 0 0 24px; max-width: 760px; color: #C8D1DE !important">Each boot reaches <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">[zuse@Hera] ok&gt;</code> with <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">POST: PASSED</code> and every POST check passing, and the three architectures report the same <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">dict_hash</code>. <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">make ARCH=amd64,aarch64,riscv64 init</code> installs everything this needs.</p>
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Acceptance -- the gate on every PR into master</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/acceptance.yml/badge.svg" alt="acceptance.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=acceptance.yml" style="font-size: 13px">runs</a></span></div>
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Build -- the quick check on StarForth-v4.0.0</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/build.yml/badge.svg?branch=StarForth-v4.0.0" alt="build.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=build.yml" style="font-size: 13px">runs</a></span></div>
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly -- acceptance, images to Nexus, proofs (03:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly.yml/badge.svg?branch=master" alt="nightly.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=nightly.yml" style="font-size: 13px">runs</a></span></div></div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 0 24px 96px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Reference</p>
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">Where things are, and what not to do.</h2>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); gap: 24px">
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Where things are</h3>
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">start here</p>
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke">The repository</a> &#8212; <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">README.md</code>, <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">docs/README.md</code>; the design record is <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">docs/fabric/FABRIC-3.md</code></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues/new/choose">New issue</a> &#8212; the forms: bug, work, ruling, board</li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=2">Open features</a> and <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=1">bugs</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&milestone=2">Board bring-up</a> &#8212; <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">boards/BRINGUP.md</code></li><li>Before touching a capsule: read <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">experiments/bare_metal/README.md</code> &#8212; the block ranges are shared by every capsule</li></ul>
</article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Rules that bite</h3>
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">learned the hard way</p>
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li>No new branch, no <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">git stash</code>, without Captain Bob's say-so.</li><li>Never modify a registered, tested FORTH word to fix it: the problem is in the caller.</li><li>ACL policy lives in <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">ACL.4th</code>, not in C.</li><li>Tags are sacred: each has the logs proving its state.</li></ul>
</article>
</div>
</section>
<footer style="border-top: 1px solid #22324D !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
<span>&#169; 2026 Robert Allan James &#183; A Starship Foundation project (in formation)</span>
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="color: #C8D1DE !important">Source</a><a href="https://starshipos-f18.com/" style="color: #C8D1DE !important">starshipos-f18.com</a></span>
</div>
</footer>
</div>
{{/html}}
+93
View File
@@ -0,0 +1,93 @@
{{velocity}}
#if ($isGuest)
#[[{{html clean="false"}}<style>
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
#xwikimaincontainerinner > a.btn { display: none !important; }
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
#xwikicontent > .ssos { border: 0 !important; }
#xwikimaincontainer { padding: 0 !important; }
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
</style>{{/html}}]]#
#end
{{/velocity}}
{{html clean="false"}}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">
<style>
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
.ssos a, .ssos a * { color: #F5891F !important; }
.ssos a:hover { color: #FFB061 !important; }
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
.ssos img { background-color: transparent !important; }
</style>
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6">
<header style="border-bottom: 1px solid #22324D !important">
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span><span style="font-size: 14px; color: #A3AEC2 !important; margin-left: 6px">.org</span></a>
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px"><a href="/bin/view/Main/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Home</a><a href="/bin/view/Contributors/" style="color: #C8D1DE !important; text-decoration: none">Contributors</a><a href="https://starshipos-f18.com/" style="color: #F5891F !important; text-decoration: none">starshipos-f18.com &#8594;</a></div>
</nav>
</header>
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">ok&gt; the working home</p>
<h1 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(36px, 5vw, 56px); line-height: 1.08">Where StarshipOS is built.</h1>
<p style="margin: 0 0 32px; max-width: 680px; font-size: 18px; color: #C8D1DE !important">StarshipOS is an operating system with no other operating system underneath it. LithosAnanke, a UEFI microkernel, boots straight from the firmware and runs StarForth, a FORTH virtual machine, as its only runtime. This wiki holds its design, its record and its dashboards; the public face is <a href="https://starshipos-f18.com/">starshipos-f18.com</a>.</p>
<div style="display: flex; flex-wrap: wrap; gap: 16px"><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="display: inline-block; padding: 14px 24px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px">Browse the source</a><a href="https://starshipos-f18.com/bin/view/TryIt/" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px">Try it in a browser</a></div>
</section>
<section aria-label="At a glance" style="border-top: 1px solid #22324D !important; border-bottom: 1px solid #22324D !important; background: #0E182B !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px"><div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">v2.1.0</div><div style="font-size: 14px; color: #A3AEC2 !important">LithosAnanke, the UEFI microkernel</div></div><div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">v4</div><div style="font-size: 14px; color: #A3AEC2 !important">StarForth, the F18 engine</div></div><div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">3 ISAs</div><div style="font-size: 14px; color: #A3AEC2 !important">amd64 &#183; aarch64 &#183; riscv64</div></div><div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">538</div><div style="font-size: 14px; color: #A3AEC2 !important">POST checks on every boot</div></div></div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">The project</p>
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">One repository, one process, one line to master.</h2>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">The source</h3>
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">kernel, StarForth, proofs, documents</p>
<p style="margin: 0 0 16px; color: #C8D1DE !important">Everything in one repository: LithosAnanke, StarForth v3 and v4, the Isabelle/HOL proofs and the books.</p><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke">Browse it &#8594;</a>
</article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Issues</h3>
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">found, ruled, built, verified</p>
<p style="margin: 0 0 16px; color: #C8D1DE !important">Every piece of work starts as an issue with its evidence, and is ruled before it is built.</p><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues">Open issues &#8594;</a>
</article>
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Pull requests</h3>
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">the only way into master</p>
<p style="margin: 0 0 16px; color: #C8D1DE !important">master takes nothing but a pull request that passed the acceptance protocol.</p><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/pulls">Pull requests &#8594;</a>
</article>
</div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">How a change is accepted</p>
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">Booted on three architectures, every time.</h2>
<p style="margin: 0 0 24px; max-width: 760px; color: #C8D1DE !important">The kernel boots in QEMU on amd64, aarch64 and riscv64 to its prompt, its power-on self-test passing every check; the PC stick boots loaded the way a PC loads it; the 32-bit build passes its tests. A developer runs it by hand, a pull request runs it by itself, and the nightly runs it again before it publishes.</p>
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Acceptance -- the gate on every PR into master</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/acceptance.yml/badge.svg" alt="acceptance.yml status" style="display: block; height: 20px"></span></div>
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly -- acceptance, images to Nexus, proofs (03:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly.yml/badge.svg?branch=master" alt="nightly.yml status" style="display: block; height: 20px"></span></div>
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly documents (04:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly-docs.yml/badge.svg?branch=master" alt="nightly-docs.yml status" style="display: block; height: 20px"></span></div></div>
</section>
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px; padding: 40px; display: flex; flex-wrap: wrap; gap: 32px; align-items: center">
<div style="flex: 999 1 480px; min-width: 0">
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Contributors</p>
<h2 style="margin: 0 0 12px; font-family: 'Exo 2', sans-serif; font-size: 30px">Working on StarshipOS?</h2>
<p style="margin: 0; color: #C8D1DE !important">Contributors have a dashboard of their own: the method, the acceptance commands, the open work. Log in to see it.</p>
</div>
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
<a href="/bin/login/XWiki/XWikiLogin?xredirect=/bin/view/Contributors/" style="display: inline-block; padding: 14px 24px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">Log in</a>
<a href="/bin/view/Contributors/" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px; text-align: center">Contributors' dashboard</a>
</div>
</div>
</section>
<footer style="border-top: 1px solid #22324D !important">
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
<span>&#169; 2026 Robert Allan James &#183; A Starship Foundation project (in formation)</span>
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="color: #C8D1DE !important">Source</a><a href="https://starshipos-f18.com/" style="color: #C8D1DE !important">starshipos-f18.com</a></span>
</div>
</footer>
</div>
{{/html}}
+27
View File
@@ -0,0 +1,27 @@
# site/org -- the .org XWiki's pages
The project's working wiki at `starshipos-f18.org` (the public face is the `.com`; `demo/` has its
"Try it" page). Three pages, ruled by Captain Bob on 2026-11-07:
| Page | File | Who sees it |
|---|---|---|
| `Main.WebHome` -- the landing page | `Main.WebHome.xwiki` | everyone, guests included |
| `Admin.WebHome` -- the admin dashboard | `Admin.WebHome.xwiki` | the administrator (`XWiki.rajames`) alone |
| `Contributors.WebHome` -- the contributors' dashboard | `Contributors.WebHome.xwiki` | the group `XWiki.StarshipContributors`, and the administrator |
They are in the starshipos-f18.com look -- the "StarshipOS.com" design canvas (navy `#0A1222`, accent
`#F5891F`, JetBrains Mono with Exo 2 headings), where they are also drawn as the `.org` artboards.
`build.py` writes the three `.xwiki` files (and, with `--canvas <dir>`, the artboards) from one
source: edit it, not the `.xwiki` files. Each page is one `{{html}}` block, which needs a page author
with script rights (the administrator has them). CI is shown as Gitea's live workflow badges, which
need no login.
`install.sh` puts them on the wiki through its REST API, makes the group and the rights, and checks
as a guest that the landing page is readable and the dashboards are not:
```
XWIKI_USER=rajames XWIKI_PASSWORD=... site/org/install.sh
```
Contributors are added to `XWiki.StarshipContributors` in the wiki's administration (Users and
Groups). The wiki-wide rights -- what guests may do anywhere else -- are the wiki's own, not this.
+337
View File
@@ -0,0 +1,337 @@
#!/usr/bin/env python3
"""build.py -- the .org XWiki's three pages in the starshipos-f18.com look (the "StarshipOS.com"
design canvas: navy #0A1222, accent #F5891F, JetBrains Mono, Exo 2 headings), from one source.
site/org/build.py writes Main.WebHome.xwiki, Admin.WebHome.xwiki,
Contributors.WebHome.xwiki (each one {{html}} block)
site/org/build.py --canvas <dir>
also writes <dir>/project/Org*.dc.html, the same pages as
design-canvas artboards (status badges drawn as placeholders:
a canvas loads nothing from Gitea)
The {{html}} macro needs a page author with script rights. install.sh puts the pages on the wiki.
"""
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
import colorlock # noqa: E402 the design's colours over the wiki's high-contrast theme
GITEA = "https://gitea.starshipos-f18.org/rajames/LithosAnanke"
COM = "https://starshipos-f18.com/"
ISSUES = GITEA + "/issues?state=open"
ACCENT = "#F5891F"
TEAL = "#4FD1B0"
FONTS = ('<link rel="preconnect" href="https://fonts.googleapis.com">\n'
'<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700'
'&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">')
H = "font-family: 'Exo 2', sans-serif"
CARD = "background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px"
EYEBROW = ("margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; "
"color: {accent}")
BTN = ("display: inline-block; padding: 14px 24px; background: {accent}; color: #0A1222; "
"font-weight: 700; text-decoration: none; border-radius: 4px")
BTN2 = ("display: inline-block; padding: 14px 24px; border: 1px solid #34486A; color: #EEF2F7; "
"text-decoration: none; border-radius: 4px")
WRAP = "max-width: 1120px; margin: 0 auto"
WORKFLOWS = { # file -> (branch for the badge, what it is)
"acceptance.yml": (None, "Acceptance -- the gate on every PR into master"),
"build.yml": ("StarForth-v4.0.0", "Build -- the quick check on StarForth-v4.0.0"),
"nightly.yml": ("master", "Nightly -- acceptance, images to Nexus, proofs (03:00 UTC)"),
"nightly-docs.yml": ("master", "Nightly documents (04:00 UTC)"),
"runner-image.yml": ("master", "Runner image"),
"release.yml": (None, "Release -- a v&lt;version&gt; tag"),
}
def badge(wf, canvas):
branch = WORKFLOWS[wf][0]
if canvas:
return ('<span style="display: inline-block; padding: 2px 10px; border: 1px dashed #34486A; '
'border-radius: 4px; font-size: 12px; color: #A3AEC2">[LIVE STATUS]</span>')
q = "?branch=" + branch if branch else ""
return ('<img src="%s/actions/workflows/%s/badge.svg%s" alt="%s status" '
'style="display: block; height: 20px">' % (GITEA, wf, q, wf))
def status_rows(wfs, canvas, runs=True):
rows = []
for wf in wfs:
link = (' <a href="%s/actions?workflow=%s" style="font-size: 13px">runs</a>' % (GITEA, wf)
if runs else "")
rows.append('<div style="display: flex; flex-wrap: wrap; align-items: center; '
'justify-content: space-between; gap: 12px; padding: 14px 0; '
'border-top: 1px solid #22324D">'
'<span style="color: #C8D1DE; font-size: 14px">%s</span>'
'<span style="display: flex; align-items: center; gap: 16px">%s%s</span></div>'
% (WORKFLOWS[wf][1], badge(wf, canvas), link))
return "\n".join(rows)
def nav(here, links):
items = []
for label, href, key in links:
cur = ' aria-current="page"' if key == here else ""
style = ("color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {accent}"
if key == here else "color: #C8D1DE; text-decoration: none")
items.append('<a href="%s"%s style="%s">%s</a>' % (href, cur, style, label))
items.append('<a href="%s" style="color: {accent}; text-decoration: none">starshipos-f18.com &#8594;</a>'
% COM)
return ('<header style="border-bottom: 1px solid #22324D">\n'
'<nav aria-label="Main" style="%s; padding: 20px 24px; display: flex; flex-wrap: wrap; '
'align-items: center; justify-content: space-between; gap: 16px">\n'
'<a href="%s" style="%s; font-weight: 700; font-size: 22px; color: #EEF2F7; '
'text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {accent}">OS</span>'
'<span style="font-size: 14px; color: #A3AEC2; margin-left: 6px">.org</span></a>\n'
'<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">%s</div>\n'
'</nav>\n</header>' % (WRAP, links[0][1], H, "".join(items)))
FOOTER = ('<footer style="border-top: 1px solid #22324D">\n'
'<div style="%s; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; '
'justify-content: space-between; font-size: 13px; color: #A3AEC2">\n'
'<span>&#169; 2026 Robert Allan James &#183; A Starship Foundation project (in formation)</span>\n'
'<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="%s" style="color: #C8D1DE">Source</a>'
'<a href="%s" style="color: #C8D1DE">starshipos-f18.com</a></span>\n</div>\n</footer>' % (WRAP, GITEA, COM))
def hero(eyebrow, title, text, buttons=""):
return ('<section style="%s; padding: 80px 24px 48px">\n'
'<p style="%s">%s</p>\n'
'<h1 style="margin: 0 0 20px; %s; font-weight: 700; font-size: clamp(36px, 5vw, 56px); '
'line-height: 1.08">%s</h1>\n'
'<p style="margin: 0 0 32px; max-width: 680px; font-size: 18px; color: #C8D1DE">%s</p>\n%s'
'</section>' % (WRAP, EYEBROW.replace("{accent}", TEAL), eyebrow, H, title, text,
('<div style="display: flex; flex-wrap: wrap; gap: 16px">%s</div>\n' % buttons)
if buttons else ""))
def section(eyebrow, title, body, pad="48px 24px"):
return ('<section style="%s; padding: %s">\n<p style="%s">%s</p>\n'
'<h2 style="margin: 0 0 32px; %s; font-size: 34px; line-height: 1.15; max-width: 760px">%s</h2>\n'
'%s\n</section>' % (WRAP, pad, EYEBROW, eyebrow, H, title, body))
def card(title, sub, body):
return ('<article style="%s">\n<h3 style="margin: 0 0 4px; %s; font-size: 22px">%s</h3>\n'
'<p style="margin: 0 0 14px; font-size: 13px; color: {accent}">%s</p>\n%s\n</article>'
% (CARD, H, title, sub, body))
def grid(items, min_w=280):
return ('<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(%dpx, 1fr)); '
'gap: 24px">\n%s\n</div>' % (min_w, "\n".join(items)))
def links(items):
return ('<ul style="margin: 0; padding-left: 20px; color: #C8D1DE; font-size: 15px; '
'display: flex; flex-direction: column; gap: 8px">%s</ul>'
% "".join("<li>%s</li>" % i for i in items))
def a(href, text):
return '<a href="%s">%s</a>' % (href, text)
def code(s):
return '<code style="color: #EEF2F7; background: #0A1222; padding: 1px 6px; border-radius: 3px">%s</code>' % s
def page_main(canvas, url):
links_ = [("Home", url("Main"), "Main"), ("Contributors", url("Contributors"), "Contributors")]
glance = [("v2.1.0", "LithosAnanke, the UEFI microkernel"), ("v4", "StarForth, the F18 engine"),
("3 ISAs", "amd64 &#183; aarch64 &#183; riscv64"), ("538", "POST checks on every boot")]
strip = ('<section aria-label="At a glance" style="border-top: 1px solid #22324D; border-bottom: 1px solid '
'#22324D; background: #0E182B">\n<div style="%s; padding: 32px 24px; display: grid; '
'grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">%s</div>\n</section>'
% (WRAP, "".join('<div><div style="%s; font-size: 32px; font-weight: 700; color: {accent}">%s</div>'
'<div style="font-size: 14px; color: #A3AEC2">%s</div></div>' % (H, n, t)
for n, t in glance)))
project = section("The project", "One repository, one process, one line to master.", grid([
card("The source", "kernel, StarForth, proofs, documents",
'<p style="margin: 0 0 16px; color: #C8D1DE">Everything in one repository: LithosAnanke, '
'StarForth v3 and v4, the Isabelle/HOL proofs and the books.</p>' + a(GITEA, "Browse it &#8594;")),
card("Issues", "found, ruled, built, verified",
'<p style="margin: 0 0 16px; color: #C8D1DE">Every piece of work starts as an issue with its '
'evidence, and is ruled before it is built.</p>' + a(GITEA + "/issues", "Open issues &#8594;")),
card("Pull requests", "the only way into master",
'<p style="margin: 0 0 16px; color: #C8D1DE">master takes nothing but a pull request that '
'passed the acceptance protocol.</p>' + a(GITEA + "/pulls", "Pull requests &#8594;")),
]), pad="96px 24px 48px")
accept = section("How a change is accepted", "Booted on three architectures, every time.",
'<p style="margin: 0 0 24px; max-width: 760px; color: #C8D1DE">The kernel boots in QEMU '
'on amd64, aarch64 and riscv64 to its prompt, its power-on self-test passing every check; '
'the PC stick boots loaded the way a PC loads it; the 32-bit build passes its tests. A '
'developer runs it by hand, a pull request runs it by itself, and the nightly runs it '
'again before it publishes.</p>\n<div style="%s">%s</div>'
% (CARD, status_rows(["acceptance.yml", "nightly.yml", "nightly-docs.yml"], canvas, False)))
contrib = ('<section style="%s; padding: 48px 24px 96px">\n<div style="%s; padding: 40px; display: flex; '
'flex-wrap: wrap; gap: 32px; align-items: center">\n<div style="flex: 999 1 480px; min-width: 0">\n'
'<p style="%s">Contributors</p>\n<h2 style="margin: 0 0 12px; %s; font-size: 30px">'
'Working on StarshipOS?</h2>\n<p style="margin: 0; color: #C8D1DE">Contributors have a dashboard '
'of their own: the method, the acceptance commands, the open work. Log in to see it.</p>\n</div>\n'
'<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">\n'
'<a href="%s" style="%s; text-align: center">Log in</a>\n'
'<a href="%s" style="%s; text-align: center">Contributors\' dashboard</a>\n</div>\n</div>\n</section>'
% (WRAP, CARD, EYEBROW, H, url("login"), BTN, url("Contributors"), BTN2))
return "\n".join([
nav("Main", links_),
hero("ok&gt; the working home", "Where StarshipOS is built.",
"StarshipOS is an operating system with no other operating system underneath it. LithosAnanke, a "
"UEFI microkernel, boots straight from the firmware and runs StarForth, a FORTH virtual machine, "
"as its only runtime. This wiki holds its design, its record and its dashboards; the public face "
"is " + a(COM, "starshipos-f18.com") + ".",
'<a href="%s" style="%s">Browse the source</a><a href="%s" style="%s">Try it in a browser</a>'
% (GITEA, BTN, COM + "bin/view/TryIt/", BTN2)),
strip, project, accept, contrib, FOOTER])
def page_admin(canvas, url):
links_ = [("Home", url("Main"), "Main"), ("Contributors", url("Contributors"), "Contributors"),
("Admin", url("Admin"), "Admin")]
ci = section("CI", "Every workflow, live.", '<div style="%s">%s</div>' % (CARD, status_rows(list(WORKFLOWS), canvas)),
pad="0 24px 48px")
work = card("Work", "Gitea", links([
a(GITEA + "/pulls?state=open", "Open pull requests"),
a(ISSUES, "Open issues") + " &#8212; " + a(ISSUES + "&labels=23", "in progress") + ", "
+ a(ISSUES + "&labels=20", "blocked") + ", " + a(ISSUES + "&labels=21", "needs acceptance"),
a(GITEA + "/milestones", "Milestones") + " and " + a(GITEA + "/projects", "the project board"),
a(GITEA + "/settings/branches", "Branch protection") + " &#8212; master: no pushes, merges only after Acceptance",
a(GITEA + "/settings/actions/secrets", "Actions secrets") + " &#8212; " + code("NEXUS_CI_PASSWORD") + ", "
+ code("PACKAGES_TOKEN") + ", " + code("CAPSULE_SIGN_KEY"),
a(GITEA + "/settings/actions/runners", "Runners"),
a("https://gitea.starshipos-f18.org/user/settings/applications", "Access tokens")
+ " &#8212; revoke what a session no longer needs"]))
arts = card("Artifacts", "Nexus and packages", links([
a("https://nexus.starshipos-f18.org/#browse/browse:starshipos-snapshots:org%2Fstarship", "Snapshots")
+ " &#8212; " + code("kernelImage") + " (pc, raspi5, milkv, logs), " + code("documentation")
+ " (book, vol1&#8211;vol3, api)",
a("https://nexus.starshipos-f18.org/#browse/browse:starshipos-releases:org%2Fstarship", "Releases"),
a("https://gitea.starshipos-f18.org/rajames/-/packages", "Container images") + " &#8212; "
+ code("lithosananke-runner"), ]))
sites = card("Sites", "and the wiki itself", links([
a(COM, "starshipos-f18.com") + " and " + a(COM + "bin/view/TryIt/", "Try it"),
a(url("Contributors"), "Contributors' dashboard"),
a(url("admin"), "Wiki administration") + " &#8212; users, the group " + code("XWiki.StarshipContributors")
+ ", rights"]))
return "\n".join([
nav("Admin", links_),
hero("Administrator only", "Admin dashboard.",
"Seen by " + code("XWiki.rajames") + " alone: the Admin space allows view and edit to that "
"account and nobody else."),
ci, section("Run the project", "Work, artifacts, sites.", grid([work, arts, sites], 300), pad="0 24px 96px"),
FOOTER])
def page_contrib(canvas, url):
links_ = [("Home", url("Main"), "Main"), ("Contributors", url("Contributors"), "Contributors")]
steps = [("Found", "An issue says what is wrong or missing, with the evidence: a log, a line of code."),
("Ruled", "Captain Bob decides what is to be done. Nothing is built without a ruling, and no fix "
"nobody asked for."),
("Built", "On the working branch, " + code("StarForth-v4.0.0") + ". C99, no GNU extensions; compose "
"in FORTH before adding a C word."),
("Verified", "The acceptance protocol, below; its logs are committed under " + code("logs/") + "."),
("Merged", "A pull request into " + code("master") + ", which runs acceptance by itself. master takes "
"nothing else.")]
method = section("How we work", "The Captain Bob method.",
'<p style="margin: 0 0 32px; max-width: 720px; color: #C8D1DE">Neither agile nor waterfall: '
'one process from the developer\'s desk to master.</p>\n' + grid(
['<article style="%s"><div style="%s; font-size: 28px; font-weight: 700; color: {accent}">'
'%d</div><h3 style="margin: 4px 0 8px; %s; font-size: 22px">%s</h3>'
'<p style="margin: 0; color: #C8D1DE; font-size: 14px">%s</p></article>'
% (CARD, H, i + 1, H, t, d) for i, (t, d) in enumerate(steps)], 190), pad="0 24px 48px")
cmds = ("make -f kernel/Makefile ARCH=amd64 clean qemu\n"
"make -f kernel/Makefile ARCH=aarch64 clean qemu\n"
"make -f kernel/Makefile ARCH=riscv64 clean qemu\n"
"make -f kernel/Makefile ARCH=amd64 clean qemu-stick-high\n"
"make -C v4 test-32")
accept = section("The acceptance protocol", "In this order, one QEMU at a time, in the foreground.",
'<pre style="margin: 0 0 24px; background: #0E182B; border: 1px solid #22324D; '
'border-radius: 6px; padding: 24px; overflow-x: auto; font-size: 14px; color: #EEF2F7">'
'%s</pre>\n<p style="margin: 0 0 24px; max-width: 760px; color: #C8D1DE">Each boot reaches '
'%s with %s and every POST check passing, and the three architectures report the same '
'%s. %s installs everything this needs.</p>\n<div style="%s">%s</div>'
% (cmds, code("[zuse@Hera] ok&gt;"), code("POST: PASSED"), code("dict_hash"),
code("make ARCH=amd64,aarch64,riscv64 init"), CARD,
status_rows(["acceptance.yml", "build.yml", "nightly.yml"], canvas)))
where = card("Where things are", "start here", links([
a(GITEA, "The repository") + " &#8212; " + code("README.md") + ", " + code("docs/README.md")
+ "; the design record is " + code("docs/fabric/FABRIC-3.md"),
a(GITEA + "/issues/new/choose", "New issue") + " &#8212; the forms: bug, work, ruling, board",
a(ISSUES + "&labels=2", "Open features") + " and " + a(ISSUES + "&labels=1", "bugs"),
a(ISSUES + "&milestone=2", "Board bring-up") + " &#8212; " + code("boards/BRINGUP.md"),
"Before touching a capsule: read " + code("experiments/bare_metal/README.md")
+ " &#8212; the block ranges are shared by every capsule"]))
rules = card("Rules that bite", "learned the hard way", links([
"No new branch, no " + code("git stash") + ", without Captain Bob's say-so.",
"Never modify a registered, tested FORTH word to fix it: the problem is in the caller.",
"ACL policy lives in " + code("ACL.4th") + ", not in C.",
"Tags are sacred: each has the logs proving its state."]))
return "\n".join([
nav("Contributors", links_),
hero("Contributors", "Contributors' dashboard.",
"For the members of " + code("XWiki.StarshipContributors") + " and the administrator. "
"Ask Captain Bob to be added."),
method, accept, section("Reference", "Where things are, and what not to do.",
grid([where, rules], 360), pad="0 24px 96px"),
FOOTER])
PAGES = { # name -> (builder, title, canvas file, canvas height)
"Main": (page_main, "StarshipOS", "OrgHome.dc.html", 2300),
"Admin": (page_admin, "Admin Dashboard", "OrgAdmin.dc.html", 1900),
"Contributors": (page_contrib, "Contributors' Dashboard", "OrgContributors.dc.html", 2500),
}
def wiki_url(key):
return {"login": "/bin/login/XWiki/XWikiLogin?xredirect=/bin/view/Contributors/",
"admin": "/bin/admin/XWiki/XWikiPreferences"}.get(key, "/bin/view/%s/" % key)
def canvas_url(key):
files = {k: v[2] for k, v in PAGES.items()}
return files.get(key, "https://starshipos-f18.org" + wiki_url(key))
def body(name, canvas):
html = PAGES[name][0](canvas, canvas_url if canvas else wiki_url)
return ('<div style="background: #0A1222; color: #EEF2F7; font-family: \'JetBrains Mono\', ui-monospace, '
'monospace; font-size: 16px; line-height: 1.6">\n%s\n</div>' % html)
def write_wiki(name):
html = colorlock.lock(body(name, False).replace("{accent}", ACCENT), "<div style=\"background: #0A1222")
with open("%s.WebHome.xwiki" % name, "w") as f:
# the landing page is the public one: the design alone for visitors, as on the .com
chrome = colorlock.GUEST_CHROME if name == "Main" else ""
f.write(chrome + '{{html clean="false"}}\n%s\n%s\n{{/html}}\n' % (FONTS, html))
def write_canvas(name, root):
title, file, h = PAGES[name][1], PAGES[name][2], PAGES[name][3]
html = body(name, True).replace("{accent}", "{{accent}}")
doc = ('<!doctype html>\n<html lang="en">\n<head>\n<meta charset="utf-8">\n<title>StarshipOS.org &#8212; %s'
'</title>\n<script src="./support.js"></script>\n</head>\n<body>\n<x-dc>\n<helmet>\n%s\n<style>\n'
'body{margin:0;background:#0A1222}\na{color:#F5891F}a:hover{color:#FFB061}\n</style>\n</helmet>\n%s\n'
'</x-dc>\n<script type="text/x-dc" data-dc-script data-props=\'{"accent":{"editor":"color","default":'
'"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":%d}}\'>\n'
'class Component extends DCLogic {\n renderVals() {\n return { accent: this.props.accent ?? '
'\'#F5891F\' };\n }\n}\n</script>\n</body>\n</html>\n' % (title, FONTS, html, h))
os.makedirs(os.path.join(root, "project"), exist_ok=True)
with open(os.path.join(root, "project", file), "w") as f:
f.write(doc)
if __name__ == "__main__":
os.chdir(os.path.dirname(os.path.abspath(__file__)))
canvas_root = sys.argv[2] if len(sys.argv) > 2 and sys.argv[1] == "--canvas" else None
for n in PAGES:
write_wiki(n)
if canvas_root:
write_canvas(n, canvas_root)
print("wrote", ", ".join("%s.WebHome.xwiki" % n for n in PAGES),
"and the canvas artboards" if canvas_root else "")
+26
View File
@@ -0,0 +1,26 @@
{{velocity}}
## Makes the inquiry class's fields, once. Run it by viewing this page as an administrator
## (programming right); install.sh does. Viewing it again changes nothing.
#if (!$hasProgramming)
Needs the programming right.
#else
#set ($xdoc = $xwiki.getDocument('Inquiries.Code.InquiryClass').getDocument().clone())
#set ($c = $xdoc.getXClass())
#set ($changed = false)
#if (!$c.get('name'))#set ($d = $c.addTextField('name', 'Name', 60))#set ($changed = true)#end
#if (!$c.get('email'))#set ($d = $c.addTextField('email', 'Email', 60))#set ($changed = true)#end
#if (!$c.get('organization'))#set ($d = $c.addTextField('organization', 'Organization', 60))#set ($changed = true)#end
#if (!$c.get('topic'))#set ($d = $c.addTextField('topic', 'Topic', 60))#set ($changed = true)#end
#if (!$c.get('message'))#set ($d = $c.addTextAreaField('message', 'Message', 80, 12))#set ($d = $c.get('message').setStringValue('contenttype', 'PureText'))#set ($changed = true)#end
#if (!$c.get('announcements'))#set ($d = $c.addBooleanField('announcements', 'Wants announcements', 'yesno'))#set ($changed = true)#end
#if (!$c.get('source'))#set ($d = $c.addTextField('source', 'Source', 60))#set ($changed = true)#end
#if (!$c.get('status'))#set ($d = $c.addStaticListField('status', 'Status', 1, false, 'new|read|answered|closed'))#set ($changed = true)#end
#if ($changed)
#set ($d = $xdoc.setTitle('Inquiry class'))
#set ($d = $xwiki.getXWiki().saveDocument($xdoc, 'The inquiry fields', $xcontext.getContext()))
CLASS-SAVED
#else
CLASS-UNCHANGED
#end
#end
{{/velocity}}
@@ -0,0 +1,3 @@
Every inquiry sent from the form on [[starshipos-f18.com>>https://starshipos-f18.com/bin/view/Inquiries/]], newest first. Open one for the whole message and to set its status. Only the administrator can see this space.
{{liveData id="inquiries" source="liveTable" sourceParameters="className=Inquiries.Code.InquiryClass&translationPrefix=" properties="doc.title,doc.creationDate,name,email,topic,status" sort="doc.creationDate:desc" limit="25"}}{{/liveData}}
+26
View File
@@ -0,0 +1,26 @@
{{velocity}}
#set ($o = $doc.getObject('Inquiries.Code.InquiryClass'))
#if (!$o)
This page holds no inquiry.
#else
[[&#8592; All inquiries>>Inquiries.WebHome]]
|=Received|$escapetool.xml($xwiki.formatDate($doc.creationDate))
|=Status|$doc.display('status', $o)
|=Name|$doc.display('name', $o)
|=Email|$doc.display('email', $o)
|=Organization|$doc.display('organization', $o)
|=Topic|$doc.display('topic', $o)
|=Announcements|$doc.display('announcements', $o)
|=Source|$doc.display('source', $o)
== Message ==
$doc.display('message', $o)
#if ($xcontext.action == 'view')
## the e-mail is checked as plain characters when it arrives (PublicInquiry), and escaped here too
{{html}}<p><a href="$escapetool.xml($doc.getURL('edit', 'editor=inline'))">Set its status</a>#if ("$!o.getProperty('email').value" != '') &#183; <a href="mailto:$escapetool.xml($escapetool.url($o.getProperty('email').value).replace('%40','@'))">Reply by e-mail</a>#end</p>{{/html}}
#end
#end
{{/velocity}}
@@ -0,0 +1,41 @@
{{velocity}}
## Receives the inquiry form on starshipos-f18.com (POST) and files it as a page under
## Inquiries.Entries, which only the administrator can read. It runs with this page's author's
## rights (getDocumentAsAuthor, saveAsAuthor): a guest can reach nothing but this. Nothing a visitor
## sends is ever written into this page's output or an entry's title: with this author's rights,
## text that reached the wiki markup could run a macro.
#macro (field $n $max)#set ($v = "$!request.getParameter($n)")#set ($v = $v.trim())#if ($v.length() > $max)#set ($v = $v.substring(0, $max))#end#end
#if ($request.method != 'POST')
This page receives the inquiry form on [[starshipos-f18.com>>https://starshipos-f18.com/bin/view/Inquiries/]].
#else
#field('website' 200)#set ($trap = $v)
#field('name' 200)#set ($name = $v)
#field('email' 200)#set ($email = $v)
#field('organization' 200)#set ($org = $v)
#field('topic' 100)#set ($topic = $v)
#field('message' 10000)#set ($message = $v)
#set ($wants = "$!request.getParameter('announcements')" != '')
#if ($trap != '')
## a robot filled the field people cannot see: say thanks, keep nothing
{{html}}<p>Thank you. Your inquiry has been received.</p>{{/html}}
#elseif ($name == '' || $message == '' || !$email.matches('^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'))
{{html}}<p>Your inquiry was not sent: a name, a valid e-mail address and a message are needed. <a href="https://starshipos-f18.com/bin/view/Inquiries/">Back to the form</a>.</p>{{/html}}
#else
#set ($stamp = $datetool.format('yyyyMMdd-HHmmss', $datetool.date))
#set ($ref = "Inquiries.Entries.I${stamp}-$mathtool.random(1000, 9999)")
#set ($entry = $xwiki.getDocumentAsAuthor($ref))
#set ($d = $entry.setTitle("Inquiry $stamp"))
#set ($o = $entry.newObject('Inquiries.Code.InquiryClass'))
#set ($d = $o.set('name', $name))
#set ($d = $o.set('email', $email))
#set ($d = $o.set('organization', $org))
#set ($d = $o.set('topic', $topic))
#set ($d = $o.set('message', $message))
#if ($wants)#set ($d = $o.set('announcements', 1))#else#set ($d = $o.set('announcements', 0))#end
#set ($d = $o.set('source', 'starshipos-f18.com'))
#set ($d = $o.set('status', 'new'))
#set ($d = $entry.saveAsAuthor('An inquiry from the .com form'))
{{html}}<p>Thank you. Your inquiry has been received; every message is read by a human, and replies usually come within a few days.</p><p><a href="https://starshipos-f18.com/">Back to starshipos-f18.com</a></p>{{/html}}
#end
#end
{{/velocity}}
+115
View File
@@ -0,0 +1,115 @@
#!/bin/bash
# install.sh -- inquiries on the .org XWiki (Captain Bob, 2026-11-07: the .com's inquiries go to an
# admin-only page on the .org, master/detail):
#
# Inquiries.WebPreferences view, edit, comment, delete: $ADMIN_USER alone -- made first
# Inquiries.Code.InquiryClass the fields (made by Inquiries.Code.ClassSetup, viewed once as the
# administrator: the class has no REST API), bound to the sheet
# Inquiries.Code.InquirySheet the detail: one inquiry, its status set by editing the page
# Inquiries.WebHome the master: every inquiry, newest first (a Live Data table)
# Inquiries.Entries.I<time> one page per inquiry, made by PublicInquiry
# PublicInquiry.WebHome public: the .com's form posts here; it files the inquiry with its
# author's rights and thanks the visitor, echoing nothing they sent
#
# XWIKI_USER=rajames XWIKI_PASSWORD=... site/org/inquiries/install.sh [https://starshipos-f18.org]
#
# It ends by checking a guest's view, then sends one test inquiry as a guest, finds it as the
# administrator, and deletes it.
set -euo pipefail
cd "$(dirname "$0")"
base=${1:-https://starshipos-f18.org}
rest="$base/rest/wikis/xwiki"
user=${XWIKI_USER:?set XWIKI_USER}
pass=${XWIKI_PASSWORD:?set XWIKI_PASSWORD}
admin=${ADMIN_USER:-XWiki.$user}
auth=(-u "$user:$pass")
xml_page() { # xml_page <title> <file>
python3 -c '
import sys
from xml.sax.saxutils import escape
print("<page xmlns=\"http://www.xwiki.org\"><title>%s</title><syntax>xwiki/2.1</syntax>"
"<content>%s</content></page>" % (escape(sys.argv[1]), escape(open(sys.argv[2]).read())))' "$1" "$2"
}
page() { # page <space path, a/b> <name> <title> <file>
local spaces=${1//\//\/spaces\/}
curl -fsS -o /dev/null -w " page ${1//\//.}.$2: %{http_code}\n" "${auth[@]}" -X PUT \
-H 'Content-Type: application/xml' --data-binary "$(xml_page "$3" "$4")" "$rest/spaces/$spaces/pages/$2"
}
objects() { # objects <space path> <page> <class>: how many
local spaces=${1//\//\/spaces\/}
curl -fsS "${auth[@]}" -H 'Accept: application/json' "$rest/spaces/$spaces/pages/$2/objects/$3" |
python3 -c 'import json,sys; print(len(json.load(sys.stdin).get("objectSummaries") or []))'
}
object() { # object <space path> <page> <class> <property=value>...: add one, as XML
local spaces=${1//\//\/spaces\/} s=$1 p=$2 c=$3; shift 3
local body
body=$(python3 -c '
import sys
from xml.sax.saxutils import escape
props = "".join("<property name=\"%s\"><value>%s</value></property>" % (escape(k), escape(v))
for k, v in (a.split("=", 1) for a in sys.argv[2:]))
print("<object xmlns=\"http://www.xwiki.org\"><className>%s</className>%s</object>" % (escape(sys.argv[1]), props))' "$c" "$@")
curl -fsS -o /dev/null -w " ${s//\//.}.$p: $c added (%{http_code})\n" "${auth[@]}" -X POST \
-H 'Content-Type: application/xml' --data-binary "$body" "$rest/spaces/$spaces/pages/$p/objects"
}
echo "=== $base, as $user"
echo "=== rights first: Inquiries is the administrator's alone"
page Inquiries WebPreferences "Inquiries rights" /dev/null
if [ "$(objects Inquiries WebPreferences XWiki.XWikiGlobalRights)" = 0 ]; then
object Inquiries WebPreferences XWiki.XWikiGlobalRights \
"levels=view,edit,comment,delete" "users=$admin" "groups=" "allow=1"
else
echo " rights there already, left as they are"
fi
echo "=== the class, its sheet"
page Inquiries/Code InquiryClass "Inquiry class" /dev/null
page Inquiries/Code ClassSetup "Inquiry class setup" ClassSetup.xwiki
out=$(curl -fsS "${auth[@]}" "$base/bin/view/Inquiries/Code/ClassSetup?basicauth=1")
case "$out" in
*CLASS-SAVED*) echo " the class's fields: made";;
*CLASS-UNCHANGED*) echo " the class's fields: there already";;
*) echo "install: the class setup did not run (programming right?)" >&2; exit 1;;
esac
page Inquiries/Code InquirySheet "Inquiry sheet" InquirySheet.xwiki
if [ "$(objects Inquiries/Code InquiryClass XWiki.ClassSheetBinding)" = 0 ]; then
object Inquiries/Code InquiryClass XWiki.ClassSheetBinding "sheet=Inquiries.Code.InquirySheet"
else
echo " sheet bound already"
fi
echo "=== the master, and the public intake"
page Inquiries WebHome "Inquiries" Inquiries.WebHome.xwiki
page PublicInquiry WebHome "Inquiry" PublicInquiry.WebHome.xwiki
echo "=== as a guest"
bad=
for p in Inquiries:401 PublicInquiry:200; do
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: application/json' "$rest/spaces/${p%%:*}/pages/WebHome")
if [ "$code" = "${p##*:}" ]; then echo " ${p%%:*}.WebHome: $code -- as it should be"
else echo " ${p%%:*}.WebHome: $code -- NOT as it should be"; bad=1; fi
done
[ -z "$bad" ] || { echo "install: a guest's view is wrong; see above" >&2; exit 1; }
echo "=== a test inquiry, sent as a guest"
reply=$(curl -fsS -X POST "$base/bin/view/PublicInquiry/" \
--data-urlencode "name=install.sh test" --data-urlencode "email=test@example.org" \
--data-urlencode "topic=General question" --data-urlencode "message=A test from site/org/inquiries/install.sh; it deletes this.")
case "$reply" in *"has been received"*) echo " thanked";; *) echo "install: no thanks for the test" >&2; exit 1;; esac
found=$(curl -fsS "${auth[@]}" -H 'Accept: application/json' "$rest/spaces/Inquiries/spaces/Entries/pages" |
python3 -c '
import json,sys
print(" ".join(p["name"] for p in json.load(sys.stdin)["pageSummaries"]))')
test_page=
for n in $found; do
if curl -fsS "${auth[@]}" -H 'Accept: application/json' \
"$rest/spaces/Inquiries/spaces/Entries/pages/$n/objects/Inquiries.Code.InquiryClass/0/properties/name" |
grep -q 'install.sh test'; then test_page=$n; fi
done
[ -n "$test_page" ] || { echo "install: the test inquiry was not filed" >&2; exit 1; }
echo " filed as Inquiries.Entries.$test_page"
curl -fsS -o /dev/null -w " deleted: %{http_code}\n" "${auth[@]}" -X DELETE \
"$rest/spaces/Inquiries/spaces/Entries/pages/$test_page"
echo "=== done: $base/bin/view/Inquiries/"
+105
View File
@@ -0,0 +1,105 @@
#!/bin/bash
# install.sh -- the .org XWiki's three pages (Captain Bob, 2026-11-07): a landing page anyone can
# read, an admin dashboard for the administrator alone, and a contributors' dashboard for the
# group XWiki.StarshipContributors (and the administrator). Through XWiki's REST API:
#
# Main.WebHome Main.WebHome.xwiki rights untouched: the wiki's own (guests view)
# Admin.WebHome Admin.WebHome.xwiki Admin.WebPreferences: view, edit, comment,
# delete -- $ADMIN_USER alone
# Contributors.WebHome Contributors.WebHome.xwiki Contributors.WebPreferences: view, comment --
# XWiki.StarshipContributors and $ADMIN_USER;
# edit, delete -- $ADMIN_USER
# XWiki.StarshipContributors the group, created empty; members are added in the wiki's
# administration (Users and Groups)
#
# An allow on a space denies that right there to everyone not named -- guests included.
#
# XWIKI_USER=rajames XWIKI_PASSWORD=... site/org/install.sh [https://starshipos-f18.org]
#
# Run it again after editing a page: pages are replaced, rights and the group are added once.
# It ends by checking, without logging in, that the landing page is readable and the dashboards
# are not.
set -euo pipefail
cd "$(dirname "$0")"
base=${1:-https://starshipos-f18.org}
rest="$base/rest/wikis/xwiki"
user=${XWIKI_USER:?set XWIKI_USER}
pass=${XWIKI_PASSWORD:?set XWIKI_PASSWORD}
admin=${ADMIN_USER:-XWiki.$user}
group=XWiki.StarshipContributors
auth=(-u "$user:$pass")
page() { # page <space> <name> <title> [file]: create or replace
local body
body=$(python3 -c '
import sys
from xml.sax.saxutils import escape
title, path = sys.argv[1], sys.argv[2]
content = open(path).read() if path else ""
print("<page xmlns=\"http://www.xwiki.org\"><title>%s</title><syntax>xwiki/2.1</syntax>"
"<content>%s</content></page>" % (escape(title), escape(content)))' "$3" "${4:-}")
curl -fsS -o /dev/null -w " page $1.$2: %{http_code}\n" "${auth[@]}" -X PUT \
-H 'Content-Type: application/xml' --data-binary "$body" "$rest/spaces/$1/pages/$2"
}
objects() { # objects <space> <page> <class>: how many the page has
curl -fsS "${auth[@]}" -H 'Accept: application/json' "$rest/spaces/$1/pages/$2/objects/$3" |
python3 -c 'import json,sys; print(len(json.load(sys.stdin).get("objectSummaries") or []))'
}
object() { # object <space> <page> <class> <property=value>...: add one
# as XML: XWiki refuses a form-encoded POST without its form token (CSRF), not an XML one
local s=$1 p=$2 c=$3; shift 3
local body
body=$(python3 -c '
import sys
from xml.sax.saxutils import escape
props = "".join("<property name=\"%s\"><value>%s</value></property>" % (escape(k), escape(v))
for k, v in (a.split("=", 1) for a in sys.argv[2:]))
print("<object xmlns=\"http://www.xwiki.org\"><className>%s</className>%s</object>" % (escape(sys.argv[1]), props))' "$c" "$@")
curl -fsS -o /dev/null -w " $s.$p: $c added (%{http_code})\n" "${auth[@]}" -X POST \
-H 'Content-Type: application/xml' --data-binary "$body" "$rest/spaces/$s/pages/$p/objects"
}
echo "=== $base, as $user"
echo "=== the group $group"
page XWiki StarshipContributors "Starship Contributors"
if [ "$(objects XWiki StarshipContributors XWiki.XWikiGroups)" = 0 ]; then
object XWiki StarshipContributors XWiki.XWikiGroups "member="
else
echo " already a group"
fi
echo "=== rights"
page Admin WebPreferences "Admin rights"
if [ "$(objects Admin WebPreferences XWiki.XWikiGlobalRights)" = 0 ]; then
object Admin WebPreferences XWiki.XWikiGlobalRights \
"levels=view,edit,comment,delete" "users=$admin" "groups=" "allow=1"
else
echo " Admin: rights there already, left as they are"
fi
page Contributors WebPreferences "Contributors rights"
if [ "$(objects Contributors WebPreferences XWiki.XWikiGlobalRights)" = 0 ]; then
object Contributors WebPreferences XWiki.XWikiGlobalRights \
"levels=view,comment" "users=$admin" "groups=$group" "allow=1"
object Contributors WebPreferences XWiki.XWikiGlobalRights \
"levels=edit,delete" "users=$admin" "groups=" "allow=1"
else
echo " Contributors: rights there already, left as they are"
fi
echo "=== the pages -- after their spaces' rights, so a dashboard is never readable without them"
page Main WebHome "StarshipOS" Main.WebHome.xwiki
page Admin WebHome "Admin Dashboard" Admin.WebHome.xwiki
page Contributors WebHome "Contributors' Dashboard" Contributors.WebHome.xwiki
echo "=== as a guest"
bad=
for p in Main Admin Contributors; do
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: application/json' "$rest/spaces/$p/pages/WebHome")
case "$p:$code" in
Main:200|Admin:401|Admin:403|Contributors:401|Contributors:403)
echo " $p.WebHome: $code -- as it should be";;
*) echo " $p.WebHome: $code -- NOT as it should be"; bad=1;;
esac
done
[ -z "$bad" ] || { echo "install: a guest's view is wrong; see above" >&2; exit 1; }
echo "=== done: $base/bin/view/Main/"
+34
View File
@@ -56,6 +56,8 @@
#include "pkcs8_ed25519.h"
#include "starkernel/ed25519.h"
#include "starkernel/x509_ed25519.h"
#include "starkernel/capsule_sig.h"
/*===========================================================================
* xxHash64 (embedded for build tool — no external dependency)
@@ -1575,6 +1577,34 @@ static int load_sign_key(const char *key_path) {
return 0;
}
/* The signing key must be the one whose certificate the image carries
* (CAPSULE_SIGNING_CERT_NAME): the kernel checks every signature against
* that certificate, and refuses a signature that does not verify -- Mama's
* own included. A key that is not the certificate's would build an image
* that cannot boot, so refuse to build it. Returns 0 if they match. */
static int check_sign_key_matches_cert(void) {
uint8_t key_pub[32], cert_pub[32];
ed25519_keygen(sign_seed, key_pub);
for (int i = 0; i < capsule_count; i++) {
if (strcmp(capsules[i].name, CAPSULE_SIGNING_CERT_NAME) != 0) continue;
if (x509_extract_ed25519_pubkey(capsules[i].data, capsules[i].length, cert_pub) != 0) {
fprintf(stderr, "mkcapsule: ERROR: %s is not an Ed25519 certificate\n",
CAPSULE_SIGNING_CERT_NAME);
return -1;
}
if (memcmp(key_pub, cert_pub, 32) != 0) {
fprintf(stderr, "mkcapsule: ERROR: the signing key is not %s's -- every "
"capsule would fail its check at boot\n", CAPSULE_SIGNING_CERT_NAME);
return -1;
}
fprintf(stderr, "mkcapsule: signing key matches %s\n", CAPSULE_SIGNING_CERT_NAME);
return 0;
}
fprintf(stderr, "mkcapsule: ERROR: --sign-key given, but no %s to check it against\n",
CAPSULE_SIGNING_CERT_NAME);
return -1;
}
int main(int argc, char **argv) {
/* --manifest mode: generate block ownership markdown. Optional
* --sign-key <keyfile> prefix: mkcapsule --manifest [--sign-key
@@ -1717,6 +1747,10 @@ int main(int argc, char **argv) {
fprintf(stderr, "mkcapsule: %d capsule(s) collected\n", capsule_count);
if (have_sign_seed && check_sign_key_matches_cert() != 0) {
return 1;
}
FILE *out = fopen(output_path, "w");
if (!out) {
fprintf(stderr, "mkcapsule: ERROR: cannot create '%s'\n", output_path);
+4 -2
View File
@@ -173,10 +173,12 @@ RUN_amd64 ?=
RUN_aarch64 ?= qemu-aarch64
RUN_riscv64 ?= qemu-riscv64
SIGN_KEY ?= /home/rajames/CLionProjects/lithosananke-ca/intermediate/snakeoil-intermediate.key
# as kernel/Makefile: CI sets SIGN_KEY; unset, the capsules are built unsigned
SIGN_KEY ?=
SIGN_KEY_ARGS = $(if $(wildcard $(SIGN_KEY)),--sign-key $(SIGN_KEY),)
CRYPTO_SRCS := $(addprefix $(ROOT)/kernel/src/crypto/,ed25519.c fe25519.c scalar25519.c sha512.c)
MKCAPSULE_SRCS := $(ROOT)/tools/mkcapsule.c $(ROOT)/tools/pkcs8_ed25519.c $(CRYPTO_SRCS)
MKCAPSULE_SRCS := $(ROOT)/tools/mkcapsule.c $(ROOT)/tools/pkcs8_ed25519.c $(CRYPTO_SRCS) \
$(ROOT)/kernel/src/crypto/x509_ed25519.c
CAPSULE_FILES := $(shell find $(ROOT)/capsules -type f ! -name '.*' 2>/dev/null)
CAPSULE_DIR_C := $(BINDIR)/capsule_generated.c
MACHINE_64 := $(BINDIR)/rom-64.c $(BINDIR)/v4_map_64.c