Wave 1 · record #1sys.descriptor.defined
#1 · a doer that asks is described
When the engine takes it, the machine stores the doer under its name and notes whom it waits for; what it will ask is stored with it, untouched until it acts. The membrane passes it.
Came froma personThe fragment's author added it at the door, right after the listener — the second half of the template. step 3
when it came in at the door
3Record #1 enters the logLOG · append
a wave is settlingengine: next: #0membrane: waiting at #0
The log - #0a listener
- #1a doer that asksnew
- end of the log
The log What before after records in the log 1 2 #1 — a doer that asks · sys.descriptor.definedThe door adds the second record as #1: a description of a doer that will ask the world. The machine has not reacted to either yet.
Where it happens
appendEmissions()Vol. 02 §4.1 · Vol. 03 §1The only function that adds records to the log. Each new record gets the next free number, at the end.
- Specification
- Vol. 02 §4.1 · Vol. 03 §1
- Code
appendEmissions()incore/registers/append-emissions.ts, line 14: the new record gets the next free number- Journal
LOG · append· offset: 1, kind: sys.descriptor.defined · by engine- Picture
- records in the log: 1 → 2
core/registers/append-emissions.ts· build 043cc8b// The one LOG writer (Vol. 02 §4.1, Vol. 03 §1): emissions become tuples by// receiving the next dense absolute offset — `base + window.length` — and// nothing else ever grows the log. Each append is journalled under the// ambient context, so a batch born of a propagated tuple carries that// tuple's offset as its cause — the cube's provenance line (ADR-002).import type { WaveEmission, WaveTuple } from "../wave/gate";import type { RegisterFile } from "./register-file";import { recordTransition } from "./record-transition";export function appendEmissions(file: RegisterFile, emissions: readonly WaveEmission[]): void {const engine = file.registers.engine;for (const emission of emissions) {const tuple: WaveTuple = { ...emission, offset: engine.base + engine.window.length };↑ the new record gets the next free numberengine.window.push(tuple);↑ it is added at the end of the logrecordTransition(file, "engine", "LOG", "append", {↑ the change is written into the journaloffset: tuple.offset,kind: tuple.kind});}}
AGPL-3.0-onlyThe Lab's demonstration environment, as this fragment ran it (build 043cc8b). The code may change, and may differ from the code of a working machine.
Nest VM core, incubated in the CoAgnes garden · build 043cc8b (2026-09-21) · this file last changed in f36e70d (2026-08-18)
when the engine took #1
7The engine takes #1ENGINE.CURSOR · propagate
a wave is settlingengine: working on #1membrane: waiting at #0
The log - #0a listener
- #1a doer that asks
- end of the log
The engine What before after pointer — the next record to take #1 #2 The engine moves on to #1, and the machine reacts to it.
Where it happens
takeNextTuple()Vol. 02 §4.1The engine's step: take the record under its pointer and move the pointer on — or stop, if the pointer has reached the end.
- Specification
- Vol. 02 §4.1
- Code
takeNextTuple()incore/registers/take-next-tuple.ts, line 15: at the end of the log, the engine stops- Journal
- #1 ·
ENGINE.CURSOR · propagate· offset: 1 · by engine - Picture
- pointer — the next record to take: #1 → #2
core/registers/take-next-tuple.ts· build 043cc8b// ENGINE.CURSOR advance (Vol. 02 §4.1) — the machine's instruction pointer:// returns the tuple at the cursor and moves it forward exactly once, or null// at quiescence. Advancing IS the context switch: the ambient wave context// moves to the propagated tuple in the same movement, so every transition// journalled during its propagation is attributed to it — the cube's spine.// The cursor never rewinds.import type { WaveTuple } from "../wave/gate";import type { RegisterFile } from "./register-file";import { recordTransition } from "./record-transition";import { setDriver, setWaveContext } from "./set-wave-context";export function takeNextTuple(file: RegisterFile): WaveTuple | null {const engine = file.registers.engine;if (engine.cursor >= engine.base + engine.window.length) return null;↑ at the end of the log, the engine stopsconst tuple = engine.window[engine.cursor - engine.base];engine.cursor += 1;↑ the engine's pointer moves on by onesetWaveContext(file, { offset: tuple.offset, phase: "propagate" });setDriver(file, "engine");recordTransition(file, "engine", "ENGINE.CURSOR", "propagate", { offset: tuple.offset });↑ the change is written into the journalreturn tuple;}
AGPL-3.0-onlyThe Lab's demonstration environment, as this fragment ran it (build 043cc8b). The code may change, and may differ from the code of a working machine.
Nest VM core, incubated in the CoAgnes garden · build 043cc8b (2026-09-21) · this file last changed in 6730f58 (2026-09-13)
8The doer is added to the figureBIND.DEFS · register-descriptor
a wave is settlingengine: working on #1membrane: waiting at #0
The log - #0a listener
- #1a doer that asks
- end of the log
The figure What before after doer note.ask— acts on note.gate; asks the world →note.answeredwhen note.gateis ready, it wakes— note.askThe machine writes the doer's description into its list of doers, and notes that
note.askwaits fornote.gate. What it will ask the world is stored with it, and not looked at until it acts.Where it happens
registerDescriptorDefinition()Vol. 02 §4.2Stores a doer's description under its name, and lists it under every listener it waits for.
- Specification
- Vol. 02 §4.2
- Code
registerDescriptorDefinition()incore/registers/register-descriptor-definition.ts, line 19: the description is stored under its name- Journal
- #1 ·
BIND.DEFS · register-descriptor· id: note.ask, interests: ["note.gate"] · by region:root - Picture
- doer
note.ask: — → acts onnote.gate; asks the world →note.answered
core/registers/register-descriptor-definition.ts· build 043cc8b// BIND.DEFS and DISPATCH write (Vol. 02 §4.2): the registration payload// lands as data; the dispatch table indexes the descriptor id under every// declared interest (the activation knot plus every demand for an operator// bind, the one subscription for an emit descriptor). Duplicate-id rejection// is the station's verdict (ADR-011 finding 3) — this op only records an// accepted registration.import type { DescriptorDefinedPayload } from "../topology/gate";import type { TopologyRegisters } from "./topology-registers";import type { RegisterFile } from "./register-file";import { recordTransition } from "./record-transition";export function registerDescriptorDefinition(file: RegisterFile,region: TopologyRegisters,payload: DescriptorDefinedPayload,interests: readonly string[]): void {region.bindDefs.set(payload.id, payload);↑ the description is stored under its namefor (const interest of interests) {const list = region.dispatch.get(interest);if (list) list.push(payload.id);else region.dispatch.set(interest, [payload.id]);↑ listed under the listener it waits for}recordTransition(file, `topology:${region.regionId}`, "BIND.DEFS", "register-descriptor", {↑ the change is written into the journalid: payload.id,interests});}
AGPL-3.0-onlyThe Lab's demonstration environment, as this fragment ran it (build 043cc8b). The code may change, and may differ from the code of a working machine.
Nest VM core, incubated in the CoAgnes garden · build 043cc8b (2026-09-21) · this file last changed in f36e70d (2026-08-18)
when the membrane passed #1
10The membrane passes #1MEMBRANE.CURSOR · sweep
a wave is settlingengine: at the endmembrane: passing #1
The log - #0a listener
- #1a doer that asks
- end of the log
The membrane What before after pointer — the next record to pass #1 #2 The same for #1: a description asks nothing of the world. Both pointers have now reached the end of the log.
Where it happens
sweepNextTuple()Vol. 02 §4.6 · Vol. 07 §3The membrane's step: pass over the record under its pointer and move the pointer on — exactly once per record.
- Specification
- Vol. 02 §4.6 · Vol. 07 §3
- Code
sweepNextTuple()incore/registers/sweep-next-tuple.ts, line 16: the membrane's pointer moves on by one- Journal
- #1 ·
MEMBRANE.CURSOR · sweep· offset: 1 · by membrane - Picture
- pointer — the next record to pass: #1 → #2
core/registers/sweep-next-tuple.ts· build 043cc8b// MEMBRANE.CURSOR advance (Vol. 02 §4.6, Vol. 07 §3): the membrane's own// reading of the one log — the second reception of one publication, never a// second truth. The cursor advances exactly once per offset per machine:// the exactly-once discharge guarantee lives in this movement.import type { WaveTuple } from "../wave/gate";import type { RegisterFile } from "./register-file";import { recordTransition } from "./record-transition";import { setDriver, setWaveContext } from "./set-wave-context";export function sweepNextTuple(file: RegisterFile): WaveTuple | null {const engine = file.registers.engine;const membrane = file.registers.membrane;if (membrane.cursor >= engine.base + engine.window.length) return null;const tuple = engine.window[membrane.cursor - engine.base];membrane.cursor += 1;↑ the membrane's pointer moves on by onesetWaveContext(file, { offset: tuple.offset, phase: "sweep" });setDriver(file, "membrane");recordTransition(file, "membrane", "MEMBRANE.CURSOR", "sweep", { offset: tuple.offset });↑ the change is written into the journalreturn tuple;}
AGPL-3.0-onlyThe Lab's demonstration environment, as this fragment ran it (build 043cc8b). The code may change, and may differ from the code of a working machine.
Nest VM core, incubated in the CoAgnes garden · build 043cc8b (2026-09-21) · this file last changed in 6730f58 (2026-09-13)
Choose a step in the stack — or press →.
A doer's definition
Brings a doer into the machine: its name, the listener it waits for, and what it does once that listener is ready. This doer has no local action: what it does is ask the world. Its instruction, the shape the answer must have and the type the answer will be written as are its whole contract — it never learns who answers.
#1sys.descriptor.defined a person
| envelope | |
|---|---|
offset | 1Its place in the log — the only address a record has. The engine gives it when the record is added, the next free number, and it never changes. |
kind | sys.descriptor.definedWhich of the four kinds of record the machine knows. The kind decides what the payload holds. |
key | ∅No lane (∅): a definition belongs to the whole machine, not to one lane. |
| payload | |
id | note.askThe doer's name, unique in this machine. |
meta | title · glossWords for people — a title and a gloss. The machine's own parts never read them; only the screens do. |
| payload.operator | |
on | note.gateThe listener it waits for. When that listener is ready, the doer acts. |
| payload.operator.service | |
instruction | «Answer the note in one plain sentence.»What it asks the world to do, in words. |
schema | type · properties · required ×1The shape the answer must have: here an object with one text field, answer. An answer of another shape comes back as a failure, never as half an answer. |
| payload.operator.service.emit | |
writes | note.answeredThe type the world's answer will be written as. |
end · #1
In the specificationVol. 03 §1Vol. 03 §2Vol. 03 §5Vol. 04 §2.2Vol. 06 §3
Names it shares with other records
note.ask— also on #4 a request, #5 the answer
The record as the machine keeps it
{
"offset": 1,
"kind": "sys.descriptor.defined",
"key": null,
"payload": {
"id": "note.ask",
"meta": {
"title": "The note, answered by the world",
"gloss": "One bind: when the knot is ready it asks the world to answer the note — a service request crosses the membrane, and the answer comes back as a fact."
},
"operator": {
"on": "note.gate",
"service": {
"instruction": "Answer the note in one plain sentence.",
"schema": {
"type": "object",
"properties": {
"answer": {
"type": "string"
}
},
"required": [
"answer"
]
},
"emit": {
"writes": "note.answered"
}
}
}
}
}