a wave is settlingengine working on #2membrane waiting at #2

Wave 2 · record #2domain.factnote.given

#2 · a note arrives

The listener opens a lane for this session, keeps the note, has what it waits for, empties its slot and announces it — as record #3. On the way, CellSpace sets up its registers.

Came froma personA person gave it at the door: the only thing a person adds in this wave. step 13

Read as

when it came in at the door

  1. 13Record #2 enters the logLOG · append

    a wave is settlingengine: next: #2membrane: waiting at #2

    The log
    1. #0a listener
    2. #1a doer that asks
    3. #2a notenewenginemembrane
    4. end of the log
    The log
    Whatbeforeafter
    records in the log23
    #2—a note · note.given

    The door adds the note to the log as record #2: a fact of type note.given. Its text asks the fragment's own question.

    Where it happens appendEmissions()Vol. 02 §4.1 · Vol. 03 §1

    The 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() in core/registers/append-emissions.ts, line 14: the new record gets the next free number
    Journal
    LOG · append · offset: 2, kind: domain.fact · by engine
    Picture
    records in the log: 2 → 3
    core/registers/append-emissions.ts · build 043cc8b
    1. // The one LOG writer (Vol. 02 §4.1, Vol. 03 §1): emissions become tuples by
    2. // receiving the next dense absolute offset — `base + window.length` — and
    3. // nothing else ever grows the log. Each append is journalled under the
    4. // ambient context, so a batch born of a propagated tuple carries that
    5. // tuple's offset as its cause — the cube's provenance line (ADR-002).
    6. import type { WaveEmission, WaveTuple } from "../wave/gate";
    7. import type { RegisterFile } from "./register-file";
    8. import { recordTransition } from "./record-transition";
    9. export function appendEmissions(file: RegisterFile, emissions: readonly WaveEmission[]): void {
    10. const engine = file.registers.engine;
    11. for (const emission of emissions) {
    12. const tuple: WaveTuple = { ...emission, offset: engine.base + engine.window.length };↑ the new record gets the next free number
    13. engine.window.push(tuple);↑ it is added at the end of the log
    14. recordTransition(file, "engine", "LOG", "append", {↑ the change is written into the journal
    15. offset: tuple.offset,
    16. kind: tuple.kind
    17. });
    18. }
    19. }

    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 #2

  1. 14The engine takes #2ENGINE.CURSOR · propagate

    a wave is settlingengine: working on #2membrane: waiting at #2

    The log
    1. #0a listener
    2. #1a doer that asks
    3. #2a noteengine · workingmembrane
    4. end of the log
    The engine
    Whatbeforeafter
    pointer — the next record to take#2#3

    The engine's pointer moves past #2. It is the only thing a person gives in this wave; everything after it, the machine and the world do.

    Where it happens takeNextTuple()Vol. 02 §4.1

    The 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() in core/registers/take-next-tuple.ts, line 15: at the end of the log, the engine stops
    Journal
    #2 · ENGINE.CURSOR · propagate · offset: 2 · by engine
    Picture
    pointer — the next record to take: #2 → #3
    core/registers/take-next-tuple.ts · build 043cc8b
    1. // ENGINE.CURSOR advance (Vol. 02 §4.1) — the machine's instruction pointer:
    2. // returns the tuple at the cursor and moves it forward exactly once, or null
    3. // at quiescence. Advancing IS the context switch: the ambient wave context
    4. // moves to the propagated tuple in the same movement, so every transition
    5. // journalled during its propagation is attributed to it — the cube's spine.
    6. // The cursor never rewinds.
    7. import type { WaveTuple } from "../wave/gate";
    8. import type { RegisterFile } from "./register-file";
    9. import { recordTransition } from "./record-transition";
    10. import { setDriver, setWaveContext } from "./set-wave-context";
    11. export function takeNextTuple(file: RegisterFile): WaveTuple | null {
    12. const engine = file.registers.engine;
    13. if (engine.cursor >= engine.base + engine.window.length) return null;↑ at the end of the log, the engine stops
    14. const tuple = engine.window[engine.cursor - engine.base];
    15. engine.cursor += 1;↑ the engine's pointer moves on by one
    16. setWaveContext(file, { offset: tuple.offset, phase: "propagate" });
    17. setDriver(file, "engine");
    18. recordTransition(file, "engine", "ENGINE.CURSOR", "propagate", { offset: tuple.offset });↑ the change is written into the journal
    19. return tuple;
    20. }

    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)

  2. 15The listener opens a lane for this sessionCLEWS · open-clew

    a wave is settlingengine: working on #2membrane: waiting at #2

    The log
    1. #0a listener
    2. #1a doer that asks
    3. #2a noteengine · workingmembrane
    4. end of the log
    The listener note.gate
    Whatbeforeafter
    lane · this session—open

    The note carries a key — this session. The listener opens a lane for that key, where this session's notes are kept apart from any other.

    Where it happens ensureClew()Vol. 02 §4.2 · Vol. 03 §5.1

    Opens a lane in a listener for a new key — the first time a fact with that key reaches it.

    Specification
    Vol. 02 §4.2 · Vol. 03 §5.1
    Code
    ensureClew() in core/registers/ensure-clew.ts, line 15: a new lane is opened for this key
    Journal
    #2 · CLEWS · open-clew · key: fragment-one-crossing-det · by knot:note.gate
    Picture
    lane · this session: — → open
    core/registers/ensure-clew.ts · build 043cc8b
    1. // CLEWS lane creation (Vol. 02 §4.2): a clew is created lazily on the first
    2. // tuple of its key — parallel keys wind independent understanding (Vol. 05
    3. // §2, Vol. 03 §5.1). Creation is a transition (journalled); an existing lane
    4. // is a read and passes through silently.
    5. import type { ClewHandle, ClewRegisters } from "./topology-registers";
    6. import { recordTransition } from "./record-transition";
    7. export function ensureClew(clew: ClewHandle, init: () => ClewRegisters): ClewRegisters {
    8. const lanes = clew.region.clews.get(clew.knotId);
    9. if (!lanes) throw new Error(`Clew bank missing for knot '${clew.knotId}' — registration must precede facts (Vol. 02 §5.1).`);
    10. let registers = lanes.get(clew.key);
    11. if (!registers) {
    12. registers = init();
    13. lanes.set(clew.key, registers);↑ a new lane is opened for this key
    14. recordTransition(clew.file, `topology:${clew.region.regionId}/clew:${clew.knotId}`, "CLEWS", "open-clew", {↑ the change is written into the journal
    15. key: clew.key
    16. });
    17. }
    18. return registers;
    19. }

    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)

  3. 16The listener keeps the note in its slotCOLLECTED · collect

    a wave is settlingengine: working on #2membrane: waiting at #2

    The log
    1. #0a listener
    2. #1a doer that asks
    3. #2a noteengine · workingmembrane
    4. end of the log
    The listener note.gate
    Whatbeforeafter
    lane · this session · slot noteempty“Is a request to the world a record of the log, or something outside it?”

    The machine writes the note's text into the listener's slot note. Its condition — the slot is not empty — now holds: the listener has what it waits for.

    Where it happens collectDeterministicSlot()Vol. 02 §4.4 · Vol. 05 §3.3

    Fills a slot of a listener with a value it heard.

    Specification
    Vol. 02 §4.4 · Vol. 05 §3.3
    Code
    collectDeterministicSlot() in core/registers/collect-deterministic-slot.ts, line 20: the slot is filled
    Journal
    #2 · COLLECTED · collect · key: fragment-one-crossing-det, slot: note, reduce: latest · by knot:note.gate
    Picture
    lane · this session · slot note: empty → “Is a request to the world a record of the log, or something outside it?”
    core/registers/collect-deterministic-slot.ts · build 043cc8b
    1. // COLLECTED write (Vol. 02 §4.4, Vol. 05 §3.3): the deterministic knot's
    2. // slot fills — `append` accumulates an array, otherwise the newest value
    3. // stands. The condition never runs here; this op records the landing.
    4. import type { DeterministicClewRegisters, ClewHandle } from "./topology-registers";
    5. import { recordTransition } from "./record-transition";
    6. export function collectDeterministicSlot(
    7. clew: ClewHandle,
    8. registers: DeterministicClewRegisters,
    9. slot: string,
    10. reduce: string,
    11. value: unknown
    12. ): void {
    13. if (reduce === "append") {
    14. const existing = registers.collected.get(slot);
    15. if (Array.isArray(existing)) existing.push(value);
    16. else registers.collected.set(slot, [value]);
    17. } else {
    18. registers.collected.set(slot, value);↑ the slot is filled
    19. }
    20. recordTransition(clew.file, `topology:${clew.region.regionId}/clew:${clew.knotId}`, "COLLECTED", "collect", {↑ the change is written into the journal
    21. key: clew.key,
    22. slot,
    23. reduce
    24. });
    25. }

    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)

  4. 17The slot is emptied againCOLLECTED · reset

    a wave is settlingengine: working on #2membrane: waiting at #2

    The log
    1. #0a listener
    2. #1a doer that asks
    3. #2a noteengine · workingmembrane
    4. end of the log
    The listener note.gate
    Whatbeforeafter
    lane · this session · slot note“Is a request to the world a record of the log, or something outside it?”empty

    Having enough, the listener will announce it — and first empties its slot, so that the next note starts afresh. What it heard travels with the announcement.

    Where it happens resetDeterministicClew()Vol. 02 §4.4

    Empties a listener's slots once it has announced that it is ready.

    Specification
    Vol. 02 §4.4
    Code
    resetDeterministicClew() in core/registers/reset-deterministic-clew.ts, line 9: the slots are emptied
    Journal
    #2 · COLLECTED · reset · key: fragment-one-crossing-det · by knot:note.gate
    Picture
    lane · this session · slot note: “Is a request to the world a record of the log, or something outside it?” → empty
    core/registers/reset-deterministic-clew.ts · build 043cc8b
    1. // The deterministic reset rule (Vol. 02 §4.4): COLLECTED clears at readiness
    2. // unless the policy says `never` — the station holds the policy, this op
    3. // holds the movement.
    4. import type { DeterministicClewRegisters, ClewHandle } from "./topology-registers";
    5. import { recordTransition } from "./record-transition";
    6. export function resetDeterministicClew(clew: ClewHandle, registers: DeterministicClewRegisters): void {
    7. registers.collected = new Map();↑ the slots are emptied
    8. recordTransition(clew.file, `topology:${clew.region.regionId}/clew:${clew.knotId}`, "COLLECTED", "reset", {↑ the change is written into the journal
    9. key: clew.key
    10. });
    11. }

    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)

  5. 18CellSpace sets up its registersREQUESTS,CHARTERS,CELLS · mount

    a wave is settlingengine: working on #2membrane: waiting at #2

    The log
    1. #0a listener
    2. #1a doer that asks
    3. #2a noteengine · workingmembrane
    4. end of the log
    CellSpace · appears
    Whatbeforeafter
    requests—empty
    charters—empty
    Cells—empty

    #2 is the session's first plain fact. CellSpace, the part that runs Cells, creates its three registers the first time it looks — empty. One of them will matter here: the index of requests, when #4 is written.

    Where it happens cellsRegion()Vol. 12 §2

    Creates CellSpace's registers the first time CellSpace needs them.

    Specification
    Vol. 12 §2
    Code
    cellsRegion() in core/registers/cells-region.ts, line 11: three empty registers are created
    Journal
    #2 · REQUESTS,CHARTERS,CELLS · mount · by cellspace
    Picture
    requests: — → empty
    core/registers/cells-region.ts · build 043cc8b
    1. // The CellSpace stratum accessor (Vol. 12 §2): mounted lazily on the first
    2. // touch — an assembly without CellSpace never carries the extension
    3. // registers. Mounting is a transition; an existing stratum is a read.
    4. import type { CellSpaceRegisters } from "./cell-registers";
    5. import type { RegisterFile } from "./register-file";
    6. import { recordTransition } from "./record-transition";
    7. export function cellsRegion(file: RegisterFile): CellSpaceRegisters {
    8. if (!file.registers.cells) {
    9. file.registers.cells = { requests: new Map(), charters: new Map(), cells: new Map() };↑ three empty registers are created
    10. recordTransition(file, "cellspace", "REQUESTS,CHARTERS,CELLS", "mount");↑ the change is written into the journal
    11. }
    12. return file.registers.cells;
    13. }

    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)

  6. 19The readiness enters the log as #3LOG · append

    a wave is settlingengine: working on #2membrane: waiting at #2

    The log
    1. #0a listener
    2. #1a doer that asks
    3. #2a noteengine · workingmembrane
    4. #3readinessnew
    5. end of the log
    The log
    Whatbeforeafter
    records in the log34
    #3—readiness · sys.knot.ready

    The listener's announcement is written at the end of the log as record #3, together with what it heard. A readiness is a record like any other.

    Where it happens appendEmissions()Vol. 02 §4.1 · Vol. 03 §1

    The 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() in core/registers/append-emissions.ts, line 14: the new record gets the next free number
    Journal
    #2 · LOG · append · offset: 3, kind: sys.knot.ready · by engine
    Picture
    records in the log: 3 → 4
    core/registers/append-emissions.ts · build 043cc8b
    1. // The one LOG writer (Vol. 02 §4.1, Vol. 03 §1): emissions become tuples by
    2. // receiving the next dense absolute offset — `base + window.length` — and
    3. // nothing else ever grows the log. Each append is journalled under the
    4. // ambient context, so a batch born of a propagated tuple carries that
    5. // tuple's offset as its cause — the cube's provenance line (ADR-002).
    6. import type { WaveEmission, WaveTuple } from "../wave/gate";
    7. import type { RegisterFile } from "./register-file";
    8. import { recordTransition } from "./record-transition";
    9. export function appendEmissions(file: RegisterFile, emissions: readonly WaveEmission[]): void {
    10. const engine = file.registers.engine;
    11. for (const emission of emissions) {
    12. const tuple: WaveTuple = { ...emission, offset: engine.base + engine.window.length };↑ the new record gets the next free number
    13. engine.window.push(tuple);↑ it is added at the end of the log
    14. recordTransition(file, "engine", "LOG", "append", {↑ the change is written into the journal
    15. offset: tuple.offset,
    16. kind: tuple.kind
    17. });
    18. }
    19. }

    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 #2

  1. 29The membrane passes #2MEMBRANE.CURSOR · sweep

    a wave is settlingengine: at the endmembrane: passing #2

    The log
    1. #0a listener
    2. #1a doer that asks
    3. #2a notemembrane · passing
    4. #3readiness
    5. #4a request
    6. end of the logengine
    The membrane
    Whatbeforeafter
    pointer — the next record to pass#2#3

    Only now, with the engine at the end, does the membrane pass over the new records. #2, the note, asks nothing of the world.

    Where it happens sweepNextTuple()Vol. 02 §4.6 · Vol. 07 §3

    The 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() in core/registers/sweep-next-tuple.ts, line 16: the membrane's pointer moves on by one
    Journal
    #2 · MEMBRANE.CURSOR · sweep · offset: 2 · by membrane
    Picture
    pointer — the next record to pass: #2 → #3
    core/registers/sweep-next-tuple.ts · build 043cc8b
    1. // MEMBRANE.CURSOR advance (Vol. 02 §4.6, Vol. 07 §3): the membrane's own
    2. // reading of the one log — the second reception of one publication, never a
    3. // second truth. The cursor advances exactly once per offset per machine:
    4. // the exactly-once discharge guarantee lives in this movement.
    5. import type { WaveTuple } from "../wave/gate";
    6. import type { RegisterFile } from "./register-file";
    7. import { recordTransition } from "./record-transition";
    8. import { setDriver, setWaveContext } from "./set-wave-context";
    9. export function sweepNextTuple(file: RegisterFile): WaveTuple | null {
    10. const engine = file.registers.engine;
    11. const membrane = file.registers.membrane;
    12. if (membrane.cursor >= engine.base + engine.window.length) return null;
    13. const tuple = engine.window[membrane.cursor - engine.base];
    14. membrane.cursor += 1;↑ the membrane's pointer moves on by one
    15. setWaveContext(file, { offset: tuple.offset, phase: "sweep" });
    16. setDriver(file, "membrane");
    17. recordTransition(file, "membrane", "MEMBRANE.CURSOR", "sweep", { offset: tuple.offset });↑ the change is written into the journal
    18. return tuple;
    19. }

    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 fact: a note given at the door

A fact is anything said to the machine or by it. Its fact type, note.given, is how listeners recognise it; its data holds the note's words. A listener told to hear note.given keeps those words in a slot.

#2domain.factnote.given a person

envelope
offset2Its 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.
kinddomain.factWhich of the four kinds of record the machine knows. The kind decides what the payload holds.
keyfragment-one-crossing-detThis session's lane: every note on it goes to the same lane of each listener.
payload
factTypenote.givenThe fact type — the name listeners match on.
payload.data
text«Is a request to the world a record of the log, or something outside it?»The note's words.

end · #2

In the specificationVol. 03 §1Vol. 03 §2Vol. 03 §5Vol. 04 §3.1Vol. 07 §6

The record as the machine keeps it
{
 "offset": 2,
 "kind": "domain.fact",
 "key": "fragment-one-crossing-det",
 "payload": {
  "factType": "note.given",
  "data": {
   "text": "Is a request to the world a record of the log, or something outside it?"
  }
 }
}