7.3 KiB
Hermes Tripod Integration Test — Executive Summary
Date: 2026-06-27
Author: Claude Code / Captain Bob (Robert Allan James)
Branch: lithosananke
Status: Design — not yet implemented
What This Addresses
The Hermes smoke test confirms the messaging substrate in isolation. What it does
not exercise is the inter-VM dispatch path: MSG-DELIVER → VM-EXEC → recipient handler.
In the hosted build VM-EXEC is a no-op stub (2DROP 2DROP). This design replaces
that stub for the duration of the test with a working dispatcher, then drives all six
directional message paths through the Tripod and confirms each one with a stdout line.
No logs are kept. No persistent state changes. The test script patches init.4th,
runs, and restores — same pattern as tools/hermes_smoke.sh.
Architectural Basis
From TRIPOD.md — dispatch is capability-based, never heat-based:
| Work type | Correct recipient |
|---|---|
| VM lifecycle | Hera |
| Event emit/drain | Hermes |
| Block I/O | Artemis |
VM-EXEC signature (from MSG-DELIVER, block 4107):
( paddr plen name-addr name-len -- )
IDX>NAME maps VM index → string:
0→"Hera"(len 4)1→"Hermes"(len 6)2→"Artemis"(len 7)
All three names have unique lengths. The hosted test dispatcher uses name length as
its discriminator — no COMPARE word is needed.
The Six Message Paths
| # | Sender | Recipient | Type | Rationale (capability-based) |
|---|---|---|---|---|
| 1 | Hera | Hermes | SPAWN-EVENT | Hera notifies Hermes: child was spawned |
| 2 | Hera | Artemis | 10 (arbitrary) | Hera requests persistence of boot record |
| 3 | Hermes | Hera | SPAWN-EVENT | Hermes confirms delivery back to Hera |
| 4 | Hermes | Artemis | 11 (arbitrary) | Hermes stores message log to Artemis |
| 5 | Artemis | Hera | 12 (arbitrary) | Artemis ACKs Hera boot record stored |
| 6 | Artemis | Hermes | 13 (arbitrary) | Artemis asks Hermes to route a result |
After all six sends, HERMES-TICK runs once. All six messages cool one step
(heat: Q.1 → Q-DECAY). Then 0 FILL heat on each and a second HERMES-TICK
reaps them. Final check: MSG-ARENA MSG-TYPE@ must be 0 (arena clean).
Exemplar: VM-EXEC Dispatcher Shim
This block replaces the no-op VM-EXEC for the duration of the test.
Name-length dispatch: 4=Hera, 6=Hermes, 7=Artemis.
( test VM-EXEC dispatcher — hosted only )
: VM-EXEC ( paddr plen name-addr name-len -- )
>R >R 2DROP R> R> ( drop payload, keep name )
DUP 4 = IF DROP ." [Hera recv]" CR EXIT THEN
DUP 6 = IF DROP ." [Hermes recv]" CR EXIT THEN
DROP ." [Artemis recv]" CR ;
Stack trace for the 4 = branch:
- Entry:
( name-addr name-len ) DUP 4 =→( name-addr name-len flag )IF DROP→( name-addr )— then." ..."andEXIT, name-addr is dead on stack
Wait — name-addr leaks. The handler must also drop it:
: VM-EXEC ( paddr plen name-addr name-len -- )
>R >R 2DROP R> R>
DUP 4 = IF 2DROP ." [Hera recv]" CR EXIT THEN
DUP 6 = IF 2DROP ." [Hermes recv]" CR EXIT THEN
2DROP ." [Artemis recv]" CR ;
2DROP consumes ( name-addr name-len ) after DUP copies len for the test.
Actually with DUP 4 = IF:
( name-addr name-len )
DUP → ( name-addr name-len name-len )
4 = → ( name-addr name-len flag )
IF → ( name-addr name-len ) ← both still on stack inside IF
2DROP ( -- )
." [Hera recv]" CR EXIT
That is correct. Remainder branch falls through with ( name-addr name-len ) still
on stack after the failed IF, so 2DROP at the end of each branch is correct.
Exemplar: Six-Path Test Sequence
( Hermes Tripod Integration Test )
CD-INIT
." >>> Tripod integration test" CR
( Path 1: Hera → Hermes )
." >>> [1] Hera->Hermes SPAWN-EVENT" CR
SPAWN-EVENT 0 1 S" boot" MSG-SEND
( Path 2: Hera → Artemis )
." >>> [2] Hera->Artemis store request" CR
10 0 2 S" boot-rec" MSG-SEND
( Path 3: Hermes → Hera )
." >>> [3] Hermes->Hera delivery confirm" CR
SPAWN-EVENT 1 0 S" ok" MSG-SEND
( Path 4: Hermes → Artemis )
." >>> [4] Hermes->Artemis log store" CR
11 1 2 S" msglog" MSG-SEND
( Path 5: Artemis → Hera )
." >>> [5] Artemis->Hera ACK" CR
12 2 0 S" stored" MSG-SEND
( Path 6: Artemis → Hermes )
." >>> [6] Artemis->Hermes route result" CR
13 2 1 S" result" MSG-SEND
." >>> HERMES-TICK (cool all 6)" CR
HERMES-TICK
." >>> HERMES-TICK ok" CR
( Zero heat on all 6 and reap )
MSG-ARENA MSG-SCAN !
6 0 DO
0 MSG-SCAN @ MSG-HEAT!
MSG-SCAN @ MSG-CELLS CELLS + MSG-SCAN !
LOOP
MSG-REAP
." >>> MSG-ARENA clean (expect 0): " MSG-ARENA MSG-TYPE@ . CR
." >>> === Tripod integration complete ===" CR
BYE
MSG-SEND calls MSG-DELIVER which calls VM-EXEC. With the test shim in place,
each send prints [Hera recv], [Hermes recv], or [Artemis recv] to stdout
immediately at send time — no async; hosted FORTH is synchronous.
Expected Output
>>> Tripod integration test
>>> [1] Hera->Hermes SPAWN-EVENT
[Hermes recv]
>>> [2] Hera->Artemis store request
[Artemis recv]
>>> [3] Hermes->Hera delivery confirm
[Hera recv]
>>> [4] Hermes->Artemis log store
[Artemis recv]
>>> [5] Artemis->Hera ACK
[Hera recv]
>>> [6] Artemis->Hermes route result
[Hermes recv]
>>> HERMES-TICK (cool all 6)
>>> HERMES-TICK ok
>>> MSG-ARENA clean (expect 0): 0
>>> === Tripod integration complete ===
The test script greps for >>> lines to confirm the sequence completed.
The [VM recv] lines confirm dispatch fired on the correct path.
Pass / Fail Criteria
| Check | Pass condition |
|---|---|
6 [VM recv] lines appear in the right order |
Hermes, Artemis, Hera, Artemis, Hera, Hermes |
HERMES-TICK completes without error |
Line >>> HERMES-TICK ok present |
| Arena clean after reap | >>> MSG-ARENA clean (expect 0): 0 |
| Script exit code 0 | grep matched at least one >>> line |
Block Size Note
The test shim + 6-path sequence shown above totals approximately 580 bytes combined. Split into two smoke blocks as with the existing test (Block 9996 = shim + CD-INIT, Block 9997 = 6 sends + tick + reap + BYE). Each well under 1024 bytes.
What This Does NOT Test
- True async inter-process delivery (hosted FORTH is single-threaded;
VM-EXECfires synchronously insideMSG-DELIVER) - K≡1.0 fleet accounting across VM boundaries (that requires the kernel Tripod with real separate VM instances and a fleet K observer)
- Channel negotiation (CH-REQUEST → CH-ACCEPT → ephemeral channel lifecycle)
- Hera lifecycle decisions driven by fleet K telemetry
Those belong to the kernel integration test (three-arch QEMU boot). This test validates the Hermes dispatch substrate — that messages reach the named VM and the thermal machinery cleans up correctly.
Implementation Vehicle
tools/hermes_tripod_smoke.sh — same structure as tools/hermes_smoke.sh:
- Back up
capsules/core/init.4th - Concatenate: core stubs + VM-EXEC shim block + Hermes capsule + 6-path test blocks
- Run
./build/amd64/standard/starforth --log-none 2>&1 | grep '^>>>' - Restore
capsules/core/init.4thon EXIT/INT/TERM
Say the word and this gets built.