docs(v4.0.0): step 6b -- POST is the kernel's: design, acceptance and plan

NUCLEUS.md 6.3 and section 7 as approved 2026-10-07: the kernel holds the
cases as a table and feeds them to the node; a runner judges from outside;
what the cases define stays, as in v3; a PARITY:V4_SYSTEM line after POST.
The capsule harness and its two nucleus variables are withdrawn (6.3a
keeps what they were).  MESH.md step 6b has the acceptance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-07 10:27:47 -04:00
co-authored by Claude Opus 5.5
parent 9bfd5071d2
commit b04ae55ec5
3 changed files with 215 additions and 22 deletions
+55 -17
View File
@@ -156,31 +156,64 @@ departure is reported.
### 6.3 Form
`post79.4th` defines a small harness in FORTH and a tally. The harness
needs two things from the nucleus that FORTH-79 does not provide. Both are
variables an assembled word consults, and both have FORTH names:
**Ruled 2026-10-07 (`MESH.md` step 6b): POST is the kernel's, as in v3.**
The kernel holds the cases and feeds them to the node; nothing of POST's
harness is loaded into the node's dictionary. What this section said
before — a harness in FORTH in `post79.4th`, and two variables in the
nucleus for it, `(CATCH)` and `(EMIT-HOOK)` — is withdrawn; 6.3a keeps it
for the record.
| Variable | Consulted by | Effect while not zero |
|---|---|---|
| `(CATCH)` | the prompt loop (`quit.v4`) | A line that ends in an error does not say `ERROR`: `(CATCH)` is set to −1 and the line ends ` ok`. POST can then go on to its next case, and can check a case that must fail. |
| `(EMIT-HOOK)` | `EMIT` (`core.v4`) | It holds the xt of a word ( c -- ) that is given each character instead of the console. POST uses it to compare what a case prints, and it keeps the messages of expected errors out of the boot log. |
**v3, as built.** The cases are C tables compiled into the kernel
(`v3/src/test_runner/modules/*.c`). For each, the kernel hands the line to
the interpreter, reads the VM's error flag, and puts the VM's stack
pointers, error and mode back (`test_common.c`, `run_single_test`). It
runs once at boot on the first VM, against block RAM of POST's own, and
the parity line is taken afterwards. Whatever the cases define stays in
the dictionary.
The prompt loop sets `(EMIT-HOOK)` to 0 at the end of every line, so the
console cannot be left silent. (This section first said one nucleus word
would do; reading `quit.v4` and `core.v4` showed it takes these two.
Amended 2026-10-05.)
**v4.**
An error always ends the line it is on, so a case is several short lines
and the harness words work across them.
- *The cases* are a table in C, `v4/system/post_cases.c`, generated by
`v4/tools/mkpost.py` (6.4) and linked into the hosted program and the
kernel. Each is a name, its lines of FORTH, whether an error is
expected, and what it must leave: the data stack, or only how many
values for an address-dependent case (6.5), and the text it prints.
- *The runner*, `v4/system/post.c`, is the kernel's and is shared by the
hosted program, the bare-metal kernel and the tests. For each case it
empties the node's data stack from outside; sends `DECIMAL FORTH
DEFINITIONS`, the state every expected value was generated from (6.4);
sends the case's lines one at a time, as the boot sends any line,
keeping what the node prints and showing none of it; and judges. A case
passes when it ended in an error exactly if one was expected and, if
none was, its stack and its printed text are what the table has. An
error ends the line it is on, so a case is several short lines; it has
ended in an error if any of its lines did.
- *What it prints.* For a failing case, `POST FAIL: name out<...>
stack<...>`. Then `PARITY:V4_POST tests=N pass=N fail=N`.
- *What is left.* What the cases define stays in the dictionary, as in
v3 (ruled 2026-10-07, on being told that the capsule had ended with
`FORGET` and left nothing). The system is sealed after POST, so `COLD`
comes back to those words and `FORGET` will not go below them. Measured
2026-10-07: they take about 1,290 cells of the 5,632 in the dictionary
space.
- *Gone:* `capsules/v4/post79.4th` and its blocks 7000 up; the harness
words; `(CATCH)` and `(EMIT-HOOK)`, with what `EMIT` and the prompt
loop did for them.
After the last case POST prints the number of cases, passes and failures,
and names each failing case.
### 6.3a As it was until step 6b
`post79.4th` defined a small harness in FORTH and a tally, and needed two
variables from the nucleus: `(CATCH)`, so that a line ending in an error
ended ` ok` and POST could go on; and `(EMIT-HOOK)`, the xt of a word given
each character in place of the console, so that POST could compare what a
case printed. Its last block was `T-REPORT` and `FORGET T#`: the harness
and everything the cases had defined were forgotten.
### 6.4 Generating the expected values
`v4/tools/mkpost.py` reads the v3 test modules, keeps the cases for
Required Word Set words, runs them in one session of the hosted v3 binary,
and writes `capsules/v4/post79.4th`. It is a development tool
and writes `v4/system/post_cases.c` (until step 6b, `capsules/v4/post79.4th`). It is a development tool
(`make -C v4 post79`), run when the cases or the rules change; its output
is committed and reviewed like any source. Every case starts from the same
state on both machines: empty stack, `DECIMAL`, `FORTH DEFINITIONS`.
@@ -221,13 +254,18 @@ The boot prints, in order:
```
PARITY:V4_NUCLEUS words=N image_hash=0x...
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x...
PARITY:V4_CAPSULE name=v4:post79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x...
PARITY:V4_POST tests=N pass=N fail=N
PARITY:V4_SYSTEM word_count=N dict_hash=0x...
PARITY:OK
POST: PASSED
ok>
```
`PARITY:V4_SYSTEM` (step 6b) is the parity of the system as it is sealed,
after POST, as v3's `PARITY:M7.1a` is taken after POST: how many words
FORTH holds and the dictionary hash. Until step 6b the POST capsule had a
`PARITY:V4_CAPSULE` line of its own in that place.
On any failure it prints `PARITY:FAIL` and `POST: FAILED` in place of the
last three lines and does not give a prompt.