Stage M-A: manual messaging words -- CHANNEL, CHANNEL-CLOSE, JOIN/UNJOIN, JOIN-VM/LEAVE-VM, PUBLISH, INJECT, MAIL?, .MAIL, .CHANNELS (FABRIC-3.9.0 §7.2)

- Eleven words in repl.c over the existing kernel-Hermes C API, registered
  for every VM; `from` always derived in C. Names as ruled (M-1) except
  UNJOIN for LEAVE, which is FORTH-79's DO-loop exit (Captain Bob).
- INJECT (M-2) sends as the root, funded from Hera's reservoir, as new
  type 31; pinned STRICT in kernel_main.c beside BIRTH.
- Read-only accessors sk_hermes_pending_at() / sk_hermes_channel_member_at()
  for .MAIL / .CHANNELS.

Console evidence identical on amd64/aarch64/riscv64: PUBLISH delivers 2
(both print), LEAVE-VM then PUBLISH delivers 1, INJECT shows in MAIL?/.MAIL
as type 31 from Hera before the recipient runs, CHANNEL-CLOSE succeeds and
refuses channel 0, JOIN/UNJOIN, refusals 0/-1. dict_hash set changes by the
11 words (542 words) and is identical across ISAs; acceptance passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-09-24 19:24:07 -04:00
co-authored by Claude Opus 5.5
parent d8358a3011
commit 879d00dcf9
12 changed files with 27951 additions and 2 deletions
+69 -1
View File
@@ -1,6 +1,6 @@
# FABRIC-3.9.8.md — Observers and participants: execution plan and log
**Status: IN PROGRESS.** Done: O-A, the stack-convention fix, S-1a, S-1b, S-1c and M-0 (§2). The design and
**Status: IN PROGRESS.** Done: O-A, the stack-convention fix, S-1a, S-1b, S-1c, M-0 and M-A (§2). The design and
its rulings (O-1 to O-4, the discard, and §7/§8's M- and S- rulings) are in `FABRIC-3.9.0.md`.
Each stage:
@@ -495,3 +495,71 @@ Evidence is named **before** each stage runs.
SKIPPED (Hermes not live)` and `channel-open policy self-test: SKIPPED (Hera/Hermes not
available)`. Both gates still look for the Hermes VM, which was removed in FABRIC-3.6 Phase 4,
so two self-tests have silently never run since then.
- [x] **Stage M-A — manual messaging words (`FABRIC-3.9.0.md` §7.2, rulings M-1/M-2).**
2026-09-24. Captain Bob: *"go ahead with M-A."* The names are as ruled, with one exception
found at the start: **`LEAVE` is FORTH-79's DO-loop exit**, and registering a messaging
`LEAVE` would have shadowed it everywhere. Captain Bob: *"UNJOIN"* (§7.2's row is updated).
`JOIN-VM`/`LEAVE-VM` don't collide and stay as ruled.
**The change:**
- **`repl.c`:** eleven words beside `SEND`, registered for every VM:
| Word | Stack |
|---|---|
| `CHANNEL` | `( -- ch \| -1 )` |
| `CHANNEL-CLOSE` | `( ch -- ok? )`, refuses channel 0 |
| `JOIN` / `UNJOIN` | `( ch -- ok? )`, the calling VM |
| `JOIN-VM` / `LEAVE-VM` | `( ch name-c name-u -- ok? )` |
| `PUBLISH` | `( paddr plen ch -- n )`, n delivered, or -1 for a bad channel or an oversized payload |
| `INJECT` | `( paddr plen name-c name-u -- ok? )` |
| `MAIL?` | `( name-c name-u -- n )`, -1 if there is no such VM |
| `.MAIL` | `( name-c name-u -- )`: index, type, sender, length, first 32 characters |
| `.CHANNELS` | `( -- )`: each channel in use with its members, by name |
- `from` is always the calling VM, derived in C, never taken from the stack.
- Payloads get the same one-block bound as `SEND`: refused, never truncated.
- **`INJECT`** (ruling M-2): sender recorded as the root (Hera) and funded from her
reservoir, with a new type, `SK_HERMES_MSG_TYPE_INJECT` (31), so `.MAIL` and the log can tell
it from a `SEND`.
- **ACL-gated:** pinned STRICT in `kernel_main.c`, beside `BIRTH`. That is the sanctioned
home for kernel-only words, since `ACL.4th` must stay host-portable.
- The policy itself is `ACL-RECHECK`'s. Today that allows STRICT words and rechecks them on
every call, so the gate is in place and the policy is `ACL.4th`'s to tighten.
- The pin is on Hera's dictionary, as `BIRTH`'s is. Other VMs' copies are unpinned.
- **`kernel_hermes.c/.h`:** two read-only accessors, `sk_hermes_pending_at()` and
`sk_hermes_channel_member_at()`, for `.MAIL` and `.CHANNELS`.
**Evidence** (typed at `[zuse@Hera] ok>`; the same transcript on all three ISAs;
`logs/20260924-183922/amd64/`, `-185413/aarch64/`, `-190905/riscv64/`):
| Line typed | Result |
|---|---|
| `CHANNEL DUP . CONSTANT CH1`, then `JOIN-VM` of `wa` and `wb` | `1`, then `1 1` |
| `.CHANNELS` | `ch 0 (5 members): Hera Hestia Artemis wa wb` / `ch 1 (2 members): wa wb` |
| `S" 77 EMIT" CH1 PUBLISH . S" wa" MAIL? . S" wb" MAIL? .` | `2 1 1`, then `MM`: **both printed** |
| `CH1 S" wb" LEAVE-VM .`, then the same `PUBLISH` with 78 | `1 1 1 0`, then one `N` |
| `S" 79 EMIT" S" wa" INJECT . S" wa" MAIL? . S" wa" .MAIL` | `1 1`, then `MAIL wa: 1 pending` / `#0 type=31 from=Hera len=8 "79 EMIT"`, **before `wa` ran it**; then `O` |
| `CH1 CHANNEL-CLOSE . 0 CHANNEL-CLOSE .` | `1 0`; channel 1 is gone from `.CHANNELS` |
| `CHANNEL CONSTANT CH2 CH2 JOIN .`, then `CH2 UNJOIN . CH2 CHANNEL-CLOSE .` | `1`; `.CHANNELS` shows `ch 1 (1 members): Hera`; then `1 1` |
| `S" 1" S" nosuch" INJECT . S" nosuch" MAIL? . S" 1" 999 PUBLISH .` | `0 -1 -1` |
Boot prints `ACL: INJECT pinned STRICT`.
**Acceptance**, on the same boots, run M-A first, then O-A, then acceptance:
- **The `dict_hash` set changes by the 11 new words and is identical across ISAs.** M7.1a is
`word_count=542` (was 531), `latest_id=711`, `hash=0x719abceff4be5564`. Hera
`0xf0024c865b83190e`, Hestia `0x544d50d7a8d96893`, Artemis `0x7e40bf2675813654`.
- The G interleave is 40/40/48, byte-identical across ISAs. It differs slightly from the
fresh-worker string, because `wa`/`wb` had already run the M-A payloads.
- `HHH` precedence, and `3` mid-stream.
- The ledger line is `pulled=266240`: exactly 4 × Q_SLOT above the pre-M-A value, for the 2 + 1
`PUBLISH` copies and 1 `INJECT`. `stadium_conserved` holds.
- The relay answers `3`, idle log growth is 0, there are no faults, and QEMU exits cleanly.
- Clean builds on all three ISAs plus the hosted build.
**Found, reported, not fixed:** riscv64 logs intermittent `virtio_blk: vblk_io timed out
(write=1 …)` errors on disk writes, four during this boot's POST and one during the first
`WORKER-BIRTH`. That last one is the only difference between the riscv64 and amd64 M-A
transcripts. It is pre-existing: the same message is in riscv64 logs back to 2026-09-10,
including this morning's S-1b follow-up acceptance (`-142946`). A TCG timing issue in the
virtio-blk driver, not M-A.