fix(v4.0.0): step 6d after its review -- no error in the middle of the messages waiting, no offer left standing

Ruled 2026-10-08: A, B, C, D and the guard for a half message.  Each with
a scene in test_host_mesh.c that failed first.

A. The words of a message after its first are written from the passes
   over the messages waiting by (!W): an offer and a wait for that offer
   only (a new engine address).  A reader removed in mid-message makes no
   error; the rest is let go and counted.  Before, the error left the
   messages waiting in pieces and the node going round for ever.
B. A store to the wait withdraws every offer; (GATE1) and (PAY-SET) do it
   first.  Before, text begun after a node went round without sleeping
   could go to the port of an older offer: text for one node was done by
   another.
C. What a finished text printed is put with the messages waiting, as how
   it ended is.  With no room either is let go and counted; neither is
   begun as a message from (FINISH) any more, where a stuck node on the
   way held the whole node.
D. Only what a sender is owed from an earlier text -- its output, how it
   ended -- holds that sender's next text back; a GONE does not; and what
   cannot be noted holds nothing.  A node's own messages keep the order
   they were made in.
-  A message half taken in when its writer is removed is let go
   ((MQ-MEND)), not kept as if whole.
-  Smaller: a refused line no longer ends a waiting text 'Interrupted';
   a node's own queued messages may be passed on by 16 nodes, not 15; no
   value is left on the stack when a port goes in mid-refusal.

make -C v4 test and sanitize at both widths, hosted-check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-08 06:34:15 -04:00
co-authored by Claude Opus 5.5
parent 380f1cc6ec
commit 2cf37aab4f
9 changed files with 289 additions and 62 deletions
+8
View File
@@ -45,6 +45,7 @@
#define V4_PORT_ANY V4_PORTS /* not a port: "whichever port has a neighbour writing" */
#define V4_PORT_OFFER (V4_PORTS + 4u) /* not a port: the offer on port 0; the offer on port k is k further (the wait, below) */
#define V4_PORT_WAIT (2u * V4_PORTS + 4u) /* not a port: the wait */
#define V4_PORT_WAIT1 (2u * V4_PORTS + 5u) /* not a port: the wait for an offer only */
#ifndef V4_NODE_WORDS
#define V4_NODE_WORDS 1024u
@@ -241,6 +242,13 @@ int v4_node_port_gone(v4_node *n, v4_cell code);
* base + V4_PORT_WAIT the wait: a fetch here blocks the node until a
* word comes for it on any port, or one of its
* offers is taken, whichever is first.
* base + V4_PORT_WAIT1 the wait for an offer only: as the wait, but
* a word that comes for the node does not end
* it, and a writer to the node is not served.
* It is how the words of a message after the
* first are written by a node that must not be
* faulted if its reader is removed.
* A store to the wait withdraws every offer and waits for nothing.
* A word that came is fetched as from "any port", and "which port" says
* where from. When an offer was taken the fetch gives 0 and "which port"
* gives V4_PORTS + k: the offer on port k. When there turns out to be