feat: recording is a node role, not a type (multi-sink substrate)
Replace the engine's single observe: usize recording affordance with recording-by-node, so one run records many streams. A recording node reads its typed input windows + ctx.now() in eval and pushes the record to a destination it holds as a field (a channel, a chart handle) — an out-of-graph side effect. There is no Sink type, trait, or engine flag: a pure-consumer node returns None, and a node may record AND return a forwarded output in the same eval (the C8 "both" case). In-graph routing stays engine-owned data (the edge table); the escape out of the graph is the node's own side effect, and that boundary is the determinism / graph-as-data boundary. Engine surface shrinks: Ctx gains now: Timestamp + now() (C2-causal, the present cycle's timestamp); Harness loses the observe field, its observe >= n bootstrap check, and the per-cycle observed-row collection; bootstrap drops its 4th param; run returns (). Recorded streams are now sparse and timestamped (a record per fired cycle) instead of the dense Vec<Option<row>>. The Ctx::new signature change touched 9 call sites across three crates (not the 3 the spec estimated) — aura-std's node tests and the engine run loop were threaded too. The engine test suite migrated to a test-local Recorder fixture whose read-back is an mpsc channel, never Rc/RefCell, keeping aura-engine/src purity-clean (C7). Eight new proof tests cover the multi-sink headline, producer-and-sink, mixed-kind recording, all-fields tap, both recorder firing modes, determinism, and recorder-edge kind rejection. C8/C22 gain cycle-0006 realization notes. Gates: workspace test 45 green (core 20, std 3, engine 22), clippy -D warnings clean, purity grep clean (only a comment names Rc/RefCell). closes #2
This commit is contained in:
@@ -208,6 +208,16 @@ selects one producer column per edge; consuming a whole record is N edges (no
|
||||
construction** (one `eval`, one timestamp), so C6 is untouched. `eval` returns
|
||||
`Option<&[Scalar]>` — a borrowed row into a node-owned buffer — so the forward
|
||||
path allocates nothing per cycle (C7).
|
||||
**Realization (cycle 0006).** The pure-consumer (sink) half of this contract is
|
||||
now realized at the substrate: **recording is a node role, not a type.** A
|
||||
recording node reads its typed input windows + `ctx.now()` in `eval` and pushes
|
||||
the record to a destination it holds as a field (a channel, a chart handle) — an
|
||||
**out-of-graph side effect**. There is no `Sink` type, trait, or engine flag: a
|
||||
node that only records returns `None` (pure consumer), and a node may record
|
||||
**and** return an output the engine forwards in the same `eval` (the "both"
|
||||
case). In-graph routing stays engine-owned data (the edge table); the escape out
|
||||
of the graph is the node's own side effect — and that boundary is the
|
||||
determinism / graph-as-data boundary (C1/C7).
|
||||
|
||||
### C9 — Fractal, acyclic composition
|
||||
**Guarantee.** A composite is itself a `Node` that wires a sub-graph and exposes
|
||||
@@ -493,6 +503,15 @@ records. Making sinks the one recording-and-observability mechanism keeps "what
|
||||
can I see?" answerable by "what did I instrument?", and keeps the engine
|
||||
UI-agnostic (C14). Live param tuning (runtime values, no topology change —
|
||||
C12 / C19 Fork A) gives the interactive feel without a wiring DSL.
|
||||
**Realization (cycle 0006).** Sinks-as-recording-mechanism is realized at the
|
||||
substrate level: a recorded trace is exactly what a recording node pushed out of
|
||||
the graph (no engine recording registry; the constructing World holds each
|
||||
recording node's destination). The engine's single `observe: usize` affordance is
|
||||
removed — `Harness::run` returns `()` and recording is a node-side concern, so one
|
||||
run records *many* streams (one per recording node) instead of exactly one row.
|
||||
Recorded streams are sparse and timestamped (a record per fired cycle, tagged
|
||||
`ctx.now()`), matching a trace of timestamped events (C18). No new contract; the
|
||||
`Harness` API change (observe removed, `run -> ()`) is recorded here.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user