12 KiB
Birthing — Work Status and Context
Branch: birthing (off lithosananke)
Last updated: 2026-05-27
Current phase: Phases 1–11 complete (kernel QEMU acceptance passed all three architectures)
Execution Model — Single Process, VM Graph
Hard constraints:
- One OS process. No threads. No fork. No shared memory between processes.
- All VMs live in the same heap, same address space.
- The C call stack IS the execution stack.
The graph:
VMs are nodes. Edges are relationships — birth (who created whom) and execution (who STARTed whom). These are distinct:
Birth graph (static, ownership): Execution stack (dynamic, runtime):
Hera C call stack:
/ \ hera_interp()
Hermes Artemis └─ vm_start("Hermes")
└─ hermes_interp()
└─ vm_start("Artemis")
└─ artemis_interp()
└─ STOP → unwind
START = push. Calling S" Hermes" START from Hera literally calls Hermes's
interpreter loop from within Hera's C execution context. Hera blocks in the vm_start()
call until Hermes returns.
STOP = pop. A VM stops itself — execution returns up the C call stack to whoever
called vm_start(). In Phase 1, STOP is always self-stop. Cross-VM STOP (via identity
assumption) is a future milestone.
BIRTH does not equal START. BIRTH allocates and initializes the VM. START runs it.
A VM can be birthed and left dormant.
USE is orthogonal. It redirects the REPL I/O independently of which VM is currently
executing. It does not affect the C call stack.
Any VM can birth sub-VMs. Hermes can call S" Companion" BIRTH — it is not Hera's
exclusive privilege. This makes the birth graph a true directed graph (rooted at Hera),
not a strict two-level tree.
What This Branch Is
We are designing and implementing the multi-VM birth system for LithosAnanke. Hera (the primary Forth VM) gains the ability to birth, name, start, stop, and kill peer VMs. All VMs run inside the same process — no threads, no OS processes.
The Three Named VMs
| VM | Role | Capsule |
|---|---|---|
| Hera | Mama VM — orchestrates all others | capsules/init.4th (root, exclusive) |
| Hermes | Messaging stratum — pub/sub | capsules/hermes/init.4th |
| Artemis | Storage and memory manager | capsules/artemis/init.4th |
Hades = kernel + HAL substrate beneath all VMs.
The Five Forth Primitives (C-level, in every VM's dictionary)
All words take a counted string ( c-addr u -- ) and leave the stack clean.
| Word | Behavior |
|---|---|
BIRTH |
Birth a VM from <name>:init.4th. Idempotent — if healthy VM exists, skip + log. |
KILL |
Destroy a named VM unconditionally. Free resources, clear registry slot. |
START |
Begin or resume a named VM. Runs synchronously (Phase 1). |
STOP |
Suspend a named VM. Any VM can STOP any other. Saves execution state. |
USE |
System-wide REPL/console redirect to the named VM. Not capsule-scoped. |
Example usage:
S" Artemis" BIRTH
S" Artemis" START
S" Artemis" USE
S" Artemis" STOP
S" Artemis" KILL
Resolved Decisions
| # | Decision | Resolution |
|---|---|---|
| D1 | BIRTH name collision | Idempotent — healthy VM: skip and log. No error, no replace. |
| D2 | Capsule production flag | All capsules get both FLAG_PRODUCTION + FLAG_EXPERIMENT. Birth not gated on flag type. |
| D3 | BIRTH return value | Nothing — stack clean. Pure side-effect word. |
| D4 | USE scope | System-wide REPL redirect. Not bound to any capsule or identity. |
| D5 | STOP authority | Any VM can STOP any other. Identity assumption (future) adds nuance. |
| D6 | Max VMs | Dynamic — Hera allocates as needed. No fixed ceiling. |
| D7 | Log prefix format | [Name] — e.g., [Hera], [Hermes], [Artemis] |
Capsule Namespace Convention
mkcapsule encodes relative paths by replacing / with :.
| File | Capsule name | Used by |
|---|---|---|
capsules/init.4th |
init.4th |
Hera only |
capsules/hermes/init.4th |
hermes:init.4th |
Hermes |
capsules/artemis/init.4th |
artemis:init.4th |
Artemis |
BIRTH maps S" Artemis" → lowercase → artemis:init.4th.
capsules/hermes/ and capsules/artemis/ currently exist but contain only .gitkeep.
Stub init.4th files must be written before the kernel build runs mkcapsule.
Implementation Checklist
Phase 0 — Design and Approval
birthingbranch created offlithosanankeHEADdocs/birthing/PLAN.mdwritten- All seven decisions resolved with Captain Bob
docs/birthing/STATUS.mdcreated (this file)- Captain Bob approves plan — gate for Phase 1
Phase 1 — VM Registry Naming
- Add
char name[VM_NAME_MAX]+VM_STATE_STOPPEDtoVMRegistryEntry(include/starkernel/capsule_run.h) - Replace static
vm_registry[64]with dynamic kmalloc linked list (src/starkernel/capsule/capsule_birth.c) - Hera (VM 0) registered as
"Hera"incapsule_vm_registry_init() - Add
capsule_vm_find_by_name()— walks linked list, copies entry on match - Add
capsule_vm_registry_set_name()— sets symbolic name by vm_id - Declare both new functions in
include/starkernel/capsule_birth.h - Kernel build (
make -f Makefile.starkernel ARCH=amd64 STARFORTH_ENABLE_VM=1) passes clean - Tests: find by name, not-found returns -1, name persists across states
Gap 1 (deferred to Phase 4): CAPSULE_MODE_VALID enforces XOR between FLAG_PRODUCTION
and FLAG_EXPERIMENT. Captain Bob's answer about D2 points at a runtime logger/mode
selector (LOG-DOE) that does not yet exist. Design of LOG-DOE and the runtime mode
selection is a separate task before Phase 4 (mkcapsule flag update) can proceed.
Phase 2 — Log Prefix [Name]
- Identify the HAL console output path (
src/starkernel/hal/console.c) - Add "active VM" context pointer to the HAL console layer
- Every
hal_console_putchar/hal_console_putsprefixes[VMName]at line start - Hera's boot output shows
[Hera]from first character - QEMU verification pending Captain Bob
Phase 3 — Capsule Stubs
- Write
capsules/hermes/init.4th(boot message + placeholder vocabulary) - Write
capsules/artemis/init.4th(boot message + placeholder vocabulary) - Verify
mkcapsulegenerates descriptors for both (requires kernel build env) - Verify capsule names resolve correctly (
hermes:init.4th,artemis:init.4th)
Phase 4 — mkcapsule Flag Update
- Update
tools/mkcapsule.cto set bothFLAG_PRODUCTIONandFLAG_EXPERIMENTon every capsule (remove the directory-prefix-based flag logic, or extend it to set both) - Rebuild and verify
capsule_generated.cshows both flags on all entries - Confirm birth eligibility check in
capsule_birth.cno longer blocks on flag type
Phase 5 — BIRTH Word
- Register
BIRTHas a C primitive inregister_mama_forth_words()(mama_forth_words.c) - Lowercase the name string from the stack
- Construct capsule name:
<name>:init.4th(special case:hera→ rejected) - Look up capsule in directory by name
- Health check: if VM with that name is alive and healthy, log and return (idempotent)
- Allocate new VM (dynamic — no fixed pool ceiling)
- Execute capsule init via
capsule_birth_babypath - Register VM under symbolic name in
VMRegistryEntry - Emit parity log via
capsule_parity_log_birth - Stack clean on exit
- Fixed caddr+1 offset bug — now reads chars directly at caddr per FORTH-79 S"
Phase 6 — KILL Word
- Register
KILLas a C primitive - Look up VM by name (case-insensitive)
- If not found: log, return (no stack effect)
- Tear down VM, free via
vm_cleanup+sf_free - Clear registry slot (state → DEAD, name cleared)
- Emit parity log via
capsule_parity_log_kill - Stack clean on exit
- Hera kill rejected
Phase 7 — START Word
- Register
STARTas a C primitive - Look up VM by name
- If EMBRYO or STOPPED: set state → LIVE
- Call
sk_repl_run(target)— blocks until target->halted - On target halt: state → STOPPED, caller resumes
- If target already LIVE: log error, return clean
- Stack clean on exit
Phase 8 — STOP Word
- Register
STOPas a C primitive - Self-stop: sets
vm->halted = 1, sk_repl_run loop exits - State updated to STOPPED by START word after REPL returns
- Stack clean (STOP takes no arguments)
Phase 9 — USE Word
- Register
USEas a C primitive - Look up VM by name
- Set active system-wide REPL VM via
sk_repl_set_active_vm - HAL console prefix changes to
[VMName]viaconsole_set_vm_name - Stack clean on exit
Phase 10 — Hera init.4th Update
S" Hermes" BIRTHincapsules/init.4thS" Artemis" BIRTHincapsules/init.4th- S" fixed to FORTH-79 ( -- c-addr u ) — stores at HERE, no count-byte prefix
- Boot sequence QEMU verified — all three architectures (amd64, aarch64, riscv64)
Phase 11 — Integration Test (kernel QEMU)
- Boot QEMU: kernel loads, Hera starts, births Hermes and Artemis — all three architectures
- Serial log shows
[Hera],[Hermes],[Artemis]prefixes ."compile-mode fixed (do-string inline approach) — "Hermes Up" / "Artimis Up" print correctly- 734 passed / 0 failed / 0 errors on amd64, aarch64, riscv64
S" Hermes" USEswitches console to Hermes — interactive test (requires Captain Bob)S" Hera" USEswitches back — interactive test (requires Captain Bob)- KILL + re-BIRTH a VM in the same session — interactive test (requires Captain Bob)
Logs: docs/birthing/acceptance-logs/ — kernel QEMU serial logs for all three architectures
Key Files
| File | Purpose |
|---|---|
docs/birthing/PLAN.md |
Full architectural plan |
docs/birthing/STATUS.md |
This file — living checklist |
tools/mkcapsule.c |
Build-time capsule packager |
capsules/init.4th |
Hera's init (root, exclusive) |
capsules/hermes/init.4th |
Hermes stub (to be written) |
capsules/artemis/init.4th |
Artemis stub (to be written) |
src/starkernel/capsule/capsule_birth.c |
C-level VM birth logic |
src/starkernel/capsule/capsule_loader.c |
Capsule load + exec |
src/starkernel/capsule/capsule_registry.c |
Capsule directory |
src/starkernel/hal/console.c |
HAL console — add [Name] prefix here |
include/starkernel/capsule.h |
CapsuleDesc, VMRegistryEntry structs |
include/starkernel/capsule_birth.h |
Birth protocol headers |
Branch and Commit History
birthing (HEAD)
d2766d6 plan: lock all seven decisions into birthing plan
ba27226 plan: overhaul birthing plan — named VMs, five Forth primitives, capsule namespacing
d258b12 plan: update birthing plan — Hera is not constrained
84e1c61 plan: add birthing plan for child VMs born of Hera
91e0b3d (lithosananke HEAD at branch point) docs: comprehensive CLAUDE.md update
Notes and Open Threads
- Identity assumption (D5 future): Cross-VM STOP requires a VM to assume another's identity. Not in scope for current phases — design separately. Phase 1 STOP is self-stop.
- Cooperative scheduling / YIELD: The single-process graph model means VMs run one at a
time (depth-first down the call stack). True cooperative interleaving (Hermes and Artemis
sharing time while Hera waits) would require an explicit
YIELDmechanism and a trampoline scheduler — future milestone, designed separately. - Graph depth — CONFIRMED unlimited: Any VM can BIRTH sub-VMs at any depth. The birth graph is a true rooted directed graph. Deep graphs consume C stack space — note for kernel stack budgeting. No enforced limit; document safe depth in practice.
- Hermes pub/sub and Artemis storage: Their full vocabularies are future work. Current
phase only needs stub
init.4thfiles. capsules/hermes/andcapsules/artemis/currently contain only.gitkeep. Stubinit.4thfiles must exist beforemake -f Makefile.starkernelcallsmkcapsule.