The machine in reference · Volume 05
Volume 05 — Activation Knots: the Accumulating Units
Status in the set: CURRENT
Status: CURRENT · Snapshot date: 2026-07-14 · Previous: 04-tuple-reference.md · Next: 06-bind-descriptors.md
An activation knot is the machine's accumulator: it matches wave tuples, winds them into wound state, and tests readiness. It accumulates understanding. Its minimal form — a single condition matcher — is a degenerate configuration of the same accumulator, never a different kind of unit. This volume specifies the knot lifecycle, the two bundled strategies, the two winding policies, and the registers each maintains.
§1. Lifecycle
Every knot executor implements the lifecycle over IKnotExecutor (Vol. 02 §2):
committed domain.fact
│
matches(t)? ──no──► (ignored by this clew)
│yes
wind(t) ──────────► emissions (winding intentions only, or none)
│
test()? ──no──► (waits for more)
│yes
topology commits sys.knot.ready {knotId, understanding()} ← snapshot first
│
reset() ← policy appliesNormative rules:
matchesMUST be a pure predicate over the tuple; it MUST NOT mutate state.windintegrates the matched tuple into the clew's registers. It MAY return emissions, but only winding intentions bounded to the knot's own accumulation and correlated back to the knot (§5). It MUST NOT publish integrations for others or emit decisions.testMUST be synchronous and read-only over wound state. While an integration is in flight, the knot is simply not ready.understanding()MUST be a synchronous snapshot of the wound state — the value reified intosys.knot.ready.resetclears the clew per its reset policy:on_ready(default) clears everything;neverkeeps wound state across readiness, allowing repeated readiness (the journal pattern).- Readiness is evaluated after every wind of the clew; the topology, not the knot, commits the readiness tuple (Vol. 02 §5).
§2. Clews: instantiation and attribution by key
A knot definition (the registered record) is distinguished from its clews (executor instances). The topology maintains one clew per (definition, key) pair:
- Registration eagerly constructs the null-key clew; construction failure is a registration defect (invalid configuration surfaces immediately).
- A clew for key
kis created lazily on the firstdomain.factwithkey = kdispatched to the definition. - Clews never share registers: parallel keys wind independent understanding.
- A clew's identity for correlation purposes is the knot id; uid sequences are per clew (
WIND.CTRlives in the executor instance).
§3. Collection rules (shared by both strategies)
The winding side of a knot configuration is a list of collection rules:
type CollectWhereClause = { field: string; equals?: unknown; not_equals?: unknown };
type SemanticCollectionRule = {
as: string; // slot name in the clew
match_type: string; // fact type to accept ('match' is the authoring alias)
reduce: 'append' | 'latest' | 'overwrite'; // 'latest' ≡ 'overwrite' (keep most recent)
field?: string; // payload data field to read; absent = whole data
where?: readonly CollectWhereClause[]; // complementarity predicates
};Matching (normative, shared function):
- A rule accepts a fact iff
factType = match_typeand everywhereclause holds overdata:equalsrequires strict equality ofdata[field];not_equalsrequires strict inequality. - A knot matches a fact iff at least one rule accepts it (semantic knots additionally match their own correlated integration, §5.3).
- A fact is wound once per accepting rule.
- Delta extraction: with
field, the delta isdata[field](for the semantic knot: if it is not a string, the wholedatais serialised as JSON instead); withoutfield, the wholedata. - Reduction:
appendaccumulates a sequence;latest/overwritekeeps only the newest value in the slot.
where clauses are the canvas subscription mechanism: they let one clew collect only complementary tuples (for example, siblings' integrations on a particular lane) — see §7 and Vol. 10 §4.
§4. The deterministic strategy
Status: CURRENT. The degenerate clew that winds locally and projects nothing.
Configuration:
type DeterministicKnotConfig = {
wind: { collect: readonly SemanticCollectionRule[]; reset?: 'on_ready' | 'never' };
condition: string; // null-guard conjunction over slot names
};Semantics:
- Winding stores collected values into
COLLECTED[as]per rule (§3); no emissions ever. - The condition language at this stage is the closed subset
name != null/name == nulljoined by&&, where everynameis a declared slot. Parsers MUST reject anything richer explicitly — richer conditions are an extension rail (Vol. 11 §4.5). test()evaluates the parsed conjunction against the slots;understanding()is the record of collected slots.- Duplicate
asnames across a deterministic knot's rules are an authoring error (the slots would alias).
Deterministic knots are the machine's gates and rendezvous latches: "wait until these named things exist" (Vol. 10 §2).
§5. The semantic strategy
Status: CURRENT. The accumulator whose integration is semantic. Configuration:
type SemanticKnotConfig = {
wind: {
collect: readonly SemanticCollectionRule[];
integrate?: 'local' | 'through_world'; // default: local
reset?: 'on_ready' | 'never'; // default: on_ready
lane?: string; // canvas mark echoed by controllers
budget?: number; // max winding intentions per clew
};
condition: {
evaluate_understanding: boolean; // false disables readiness entirely
questions: readonly string[]; // the knot's angle of perception
threshold_grade: number; // readiness threshold over GRADE
};
};test() is evaluate_understanding && GRADE ≥ threshold_grade; understanding() is { state: STATE, grade: GRADE }.
§5.1 Local winding (integrate: local)
Each accepted delta is stored into SLOTS per rule, and the clew's injected local integrator — a function (deltas) → {state, grade} supplied by the strategy registry, not chosen by the knot — recomputes STATE/GRADE from all collected values. No emissions. A deterministic machine uses a pure function here; the reference bundles a demonstration heuristic (refimpl 05 §6).
§5.2 Winding through the world (integrate: through_world)
Semantic growth cannot complete locally: integrating a delta into wound understanding is an inference. Winding therefore unfolds as a two-tact cascade through the world; the knot gains a projecting face bounded to its own metabolism.
Tact one — accept and project. On accepted deltas:
- push each delta (labelled per §5.4) into
DELTAQ; - if
INFLIGHT.UID ≠ null→ return no emissions (at most one intention in flight per clew); - if
budgetis declared andWIND.CTR ≥ budget→ return no emissions (the resonance damper: queued deltas stay unwound; the wave settles unfinished and the stall is visible on the log); - otherwise:
WIND.CTR += 1;uid ← "<knotId>#<WIND.CTR>"; move the wholeDELTAQinto the intention; setINFLIGHT.UID ← uid; emit oneinference.request{knotId, uid, questions, state: STATE, deltas, lane?}on the clew's key (Vol. 04 §4.1).
Tact two — wind the integration. On a committed inference.response whose data.knotId equals the knot id:
- if
data.uid ≠ INFLIGHT.UID→ ignore (stale or foreign answer); STATE ← data.state;GRADE ← data.grade;INFLIGHT.UID ← null;- if
DELTAQis non-empty, project the next intention per tact one (budget permitting).
Readiness then follows the ordinary lifecycle: test() reads the freshly wound GRADE. Note the two-tact discipline preserves rule 3 of §1: between tacts the clew is not ready.
§5.3 Own-integration matching
A through-world clew's matches accepts, besides its collection rules, exactly the facts factType = 'inference.response' ∧ data.knotId = id. Reasoning and failure facts are NOT matched by the clew: a failure leaves INFLIGHT.UID set and the clew stalls honestly (Vol. 04 §4.4) unless the topology collects the failure deliberately.
§5.4 Delta labelling on a canvas
With a single collection rule the delta stays raw. With several rules — a canvas cell collecting from complementary sources — each delta is labelled by its rule name: "[<as>] <text>", so the integration sees where material came from.
§6. Budgets and stalling
The winding budget caps intentions per clew, bounding cost and divergence:
- A clew whose budget is exhausted below its threshold leaves the wave settled but unfinished — never an exception, never a retry loop; the stall is visible on the log (queued deltas unwound, no readiness).
- Budget accounting counts projections, including those answered by failure.
- Extensions layering wider budgets (per-run, per-Cell) MUST keep this semantics: the first action over a hard ceiling is withheld and the state is reported honestly (Vol. 12 §8).
§7. Lanes and the understanding canvas
A clew's lane mark is written into its winding intentions and echoed verbatim by controllers into the answers (Vol. 04 §4). Complementary cells subscribe by where clauses over lane (or any payload field), which composes into the understanding canvas: several clews winding in parallel, cross-pollinating through each other's committed integrations, each guarded by its own budget. The construct-level treatment with a worked figure is Vol. 10 §4.
§8. Strategy registry (extension point)
Strategies are resolved by name through a registry of factories:
type KnotFactory = (id: string, config: KnotConfig) => IKnotExecutor<AnyTuple>;
type KnotStrategyRegistry = ReadonlyMap<string, KnotFactory>;- The bundled names are
deterministicandsemantic_evaluator; an unknown name is a registration defect. - An implementation MAY install additional strategies (a rules engine, a vector accumulator, a human-answer latch) provided the executor honours §1 and the station rules of Vol. 02 §3.
- The registry is also the injection seam for the local integrator: the knot itself stays free of any concrete evaluator.
- Authoring-format visibility of a custom strategy requires the compiler to accept its name and validate its config; unknown strategies in YAML are rejected explicitly (Vol. 09 §5).
§9. Demonstration: minimal conforming deterministic knot
class GateKnot implements IKnotExecutor<AnyTuple> {
readonly id: string;
private slots = new Map<string, unknown>();
constructor(id: string, private readonly rules: SemanticCollectionRule[],
private readonly wants: (lookup: (n: string) => unknown) => boolean) {
this.id = id;
}
matches(t: AnyTuple) {
return t.kind === 'domain.fact' &&
this.rules.some(r => ruleMatches(r, t.payload.factType, t.payload.data));
}
wind(t: AnyTuple) {
if (t.kind !== 'domain.fact') return [];
for (const r of this.rules)
if (ruleMatches(r, t.payload.factType, t.payload.data))
this.slots.set(r.as, r.field === undefined ? t.payload.data
: (t.payload.data as any)[r.field]);
return [];
}
test() { return this.wants(n => this.slots.get(n)); }
understanding() { return Object.fromEntries(this.slots); }
reset() { this.slots = new Map(); }
}Anything beyond this skeleton — projection, budgets, canvases — is additive behaviour inside the same five-method lifecycle.