docs(v4.0.0): step 6e -- messages on the wire: the second attempt at the wait

MESH.md 7d: the rulings, the wire, what a node asks of the fabric, the
nucleus, the products, the limits, the acceptance, and the later step of
keeping the wires in the system's blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-08 12:47:55 -04:00
co-authored by Claude Opus 5.5
parent 8967c93241
commit 7eb545f387
+211
View File
@@ -463,6 +463,8 @@ Two types, beside text (1), output (2) and done (3):
## 7c. The wait (ruled 2026-10-07; built, found unsound, and backed out 2026-10-08)
*(The second attempt is section 7d.)*
**This section is a record, not what the code does.** The wait was built
(step 6d), two independent reviews in a row found it unsound, and Captain
Bob ruled it backed out: the engine and nucleus are as they were before
@@ -702,6 +704,212 @@ a line. POST 538 of 538, `word_count=317`,
`-120624` and `-121117` are amd64 boots of the same code in which the
typed session did not put the wait on a deep stack; they are kept.)
## 7d. Messages on the wire (ruled 2026-10-08): the second attempt at step 6d
**What it is for.** The same end as section 7c: a node that is stuck holds
up no other node. Section 7c.6 and 7c.7 say why the first attempt failed.
Three things made it unsound, and this design removes each instead of
guarding it:
1. A message could be half moved: it went a word at a time, and a fault
after the first word left both ends out of step.
2. A node kept other nodes' messages in a ring in its own memory, which
it had to turn; a fault in the middle left the ring in pieces, and a
stuck neighbour's traffic could fill it.
3. All of it ran on the stacks the node's text was using.
**v3's way** (`kernel/src/vm/kernel_hermes.c`, read again for this). A
send is one call to the kernel, `sk_hermes_send_one(from, to, ...)`: it
delivers to exactly one VM, by its id. The kernel copies the whole
message into its own pool and puts it on the target's queue; if anything
is full the send is refused at once and nothing has changed. A VM never
passes a message on for another, never holds another's, and never has
one half moved. v3 has none of the three problems.
**What is taken from v3, and what is not.** Taken: whole messages, moved
by something that is not the node's own text; a send that is accepted or
refused at once; nothing in transit held by a node. Not taken: delivery
by id from one place that knows where every node is. A node is still
wired only to its neighbours and messages still go from neighbour to
neighbour, which is what a grid of nodes needs (ruling 1).
### 7d.1 The rulings
1. **The fabric moves whole messages between neighbours.** Put to Captain
Bob with v3's way in full and with leaving step 6d undone.
2. **A message waits on the wire, in the fabric**, not in a node. Each
wire has a queue each way. A node holds nothing in transit.
3. **What a text prints waits for room; everything else is refused at
once.** `SEND`, an answer, a NACK and a GONE either go or are refused.
Printing waits, so that output is not lost.
4. **A wire holds 1,024 cells each way**, a build parameter, as the number
of ports and the sizes of the stacks are.
5. **The wires' memory is the fabric's own, for now, behind one
interface**; given only to ports that are wired. Backing it with the
system's blocks is a later step (7d.8).
The stacks stay at 32 (ruled the same day): section 7c.7 showed their
size was never the cause.
### 7d.2 The wire
- Between two nodes that are wired, the fabric keeps two queues of whole
messages, one each way, of `V4_WIRE_CELLS` cells (1,024).
- A message is what section 6 says: seven words and its text, four
characters to a word. On a wire it takes seven cells and one for each
word of text.
- **Putting a message on a wire, and taking one off, is each one step:
all of it or none.** There is no state in which part of a message has
moved.
- A wire is full when the message offered does not fit. One with 200
cells free takes a short message and refuses a long one.
- A wire to a device -- the console, the kernel -- is the same to the
node. Whatever is on the other end puts and takes whole messages
through the fabric.
- When a node is removed, or a wire cut, what was waiting on its wires is
let go.
### 7d.3 What a node asks of the fabric
Addresses after the node's ports and the two words of section 7a. None
is memory while the ports are attached. Each operation is one step of
the engine and happens whole.
| Address | What |
|---|---|
| `base + V4_PORTS + 4` | Wire: store the number of a port. What follows is about that wire. |
| `base + V4_PORTS + 5` | A: store a value an operation needs |
| `base + V4_PORTS + 6` | B: store a second |
| `base + V4_PORTS + 7` | Do: store the number of an operation |
| `base + V4_PORTS + 8` | How it went: fetch. 0 done; 1 no room; 2 nothing on that port; 3 no such message; 4 not a message |
| `base + V4_PORTS + 9` | Which wires have a message waiting: fetch, a bit to a port |
| Operation | What it does |
|---|---|
| 1, look | The seven words of the message at the front of the wire are copied to the word address in A. Nothing is taken. |
| 2, take | The message is copied out, its seven words to A and its text to B, and is off the wire. |
| 3, move | The message goes to the back of the wire of the port in A, with one fewer in its fourth word (how many more nodes may pass it on). |
| 4, drop | The message is off the wire and gone. |
| 5, put | The message whose seven words are at A and whose text is at B goes to the back of the wire. |
| 6, find | The first message on the wire that is to the node in B and of the type in A becomes the one that look, take and drop are about, wherever it is in the queue. |
| 7, next | The same, from after the one found last. |
| 8, sleep | The node is blocked until one of its wires has a message. |
| 9, sleep for room | The node is blocked until the wire has A cells free, or one of its wires has a message, whichever is first. |
- Look, take, move and drop are about the message at the front, unless
find or next has named another.
- Only 8 and 9 block. A node blocked there executes nothing.
- The ports themselves stay as they are, a word at a time, for the two
things that are not messages: a newborn node being sent its nucleus
(section 5), and a node's requests to the kernel (section 8).
- The looking words of section 7a, and their lower-number rule, are no
longer used by the nucleus.
### 7d.4 The nucleus
A node keeps no messages but the one it is doing. The ring of messages
waiting, the words that turned it, the list of NACKs owed, and
`(GATE)` go.
- *With nothing to do* it sleeps (8). Woken, it looks at the front of
each wire that has a message.
- *For another node:* it is moved to the wire that leads there. If
there is no way, or nothing is on that port, or the wire is full, or
it has been passed on 16 times, it is dropped, counted in `(LOST)`,
and a NACK is put on the wire back toward its sender. A NACK or a
GONE that cannot go is dropped and counted; nothing is owed for it.
- *For itself:* it is taken and dealt with as now: text is done; a
NACK is counted; a GONE from its centre is believed.
- *`SEND`, how text ended, a NACK, a GONE* are built in the node's own
memory and put. Refused, a `SEND` is error 19, "Message refused"; the
others are counted in `(LOST)`.
- *What text prints* is put when the output buffer fills and when the
text ends. If the wire has no room the node sleeps for room (9). Woken
by a message instead, it passes on what is for other nodes, as above,
and sleeps again; text for itself from its console ends the text it is
doing in error 21, "Interrupted"; anything else for itself stays on
the wire.
- *`AWAIT`* sleeps (8) and, woken, passes on what is for other nodes and
looks for what would end its wait with find and next: the answer, a
NACK or a believed GONE about the node waited for, or text from its
console. Other messages for itself stay on the wire, in their order.
- *Before text begins any of these* it tries the stack it will need,
as `(ROOM)` does now (7c.7). Between texts the rule of 28 values
stands.
### 7d.5 The products
The lone node on the hosted and bare-metal products is given the same
addresses by its host (`v4/system/boot.c`): its two wires are the
console and the kernel. Nothing else changes for it: the kernel's
requests stay a word at a time.
### 7d.6 What will be limits
- A burst to a node that is busy, beyond what its wire holds, is refused
where today it waits.
- An answer whose way back is full is dropped and counted, and whoever
waits for it is not told: that wait ends as any wait on a node that
does not answer does, by Hera's kill or from the console.
- A text whose printing cannot reach the console, because a stuck node
is on the way and its wire has filled, waits until that node is
killed. It holds up no one else, and passes on meanwhile.
- A message for a node sits at the front of a wire until that node
takes it. A node that is stuck never does: its wires fill, and from
then on whoever sends to it is told at once.
### 7d.7 Acceptance
1. *Whole or not at all.* At no step of the engine is part of a message
on a wire or part of one taken.
2. *Refused at once.* A put to a full wire, to a port with nothing on
it, and to a wire with room, each answers in the step it is asked.
3. *A stuck node holds up no one.* With a node stuck in a loop: every
other node goes on doing what it is sent and passing on; what is sent
to the stuck node is taken until its wire is full and refused from
then on, the sender told; a node that owes it a NACK is not held.
4. *Hera.* She can be typed to whatever any other node is doing, and
`KILL` of one stuck node is not held by another.
5. *Printing is not lost.* A text that prints more than a wire holds, to
a console's node that is slow to take it, prints all of it in order.
6. *A node removed at any step* of any message leaves every other node
at rest and answering.
7. *Every depth of both stacks.* Each message path -- printing, `SEND`,
`AWAIT` and a line typed during it, passing on, a refusal -- on the
products and on the mesh, with the data stack at every depth and from
every depth of calls: each line typed is answered and every node comes
back.
8. *Order.* What one node sends another arrives in the order it was
sent; what a text prints, and then how it ended, reach the console in
that order.
9. *Nothing else changes.* POST 538 of 538; the products give what the
commit before gives on the same input, but where 7d.6 says otherwise;
`sanitize`, `hosted-check`, lint, three boots, one hash on all six.
### 7d.8 A later step, not built: the wires in the system's blocks
Captain Bob, 2026-10-08. The system has blocks set aside for it -- the
first 32 RAM blocks, hidden from the user, and the first 32 of every
disk (`BLK_FORTH_SYS_RESERVED`, `BLK_DISK_SYS_RESERVED`,
`v3/include/block_subsystem.h`) -- and each device has at its top a
system area that starts at 128 device blocks and grows down
(`BLK_META_FENCE_INIT`). The wires' queues could be kept in the reserved
blocks, with a pool in that area for what does not fit: a kind of
virtual memory for them, and messages that outlast a restart.
- What is there today: the 32 hidden RAM blocks would hold four queues
of 1,024 cells at 64 bits; a unit of five nodes has sixteen.
- What it waits on: a device v4 may write. The virtio driver writes
(`kernel/src/virtio/virtio_blk.c`, `vblk_write`); what refuses a write
on the v4 boot is the block subsystem, which holds a disk it does not
know as provisional until its owner says it may be formatted
(`blk_subsys_confirm_format`), and in v3 that owner is Artemis. v4 has
no Artemis yet.
- To be ruled then: what a message that outlasts a restart means; and
what, if anything, already uses those blocks and that area.
- What makes it possible without touching a node: ruling 5. The fabric
reaches a queue through one interface.
## 8. Storage
**Ruled 2026-10-06 and 2026-10-07** (Captain Bob). On 2026-10-07 he found
@@ -1326,6 +1534,9 @@ Each is tested, committed and pushed before the next.
the hash of step 6c's mended code. The boots of `logs/20261008-01*`
and `-06*` are of the wait as built and are kept as its record.
**6e. Messages on the wire (section 7d).** Ruled 2026-10-08: the
second attempt at 6d. Not built.
7. **A second unit; scaling while running; sleep, wake and kill by
command.**
8. **The hosted product is the five nodes**, on three ISAs: acceptance 1