Node output is a record (composite stream), not a single scalar #1
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation
Today every node emits exactly one scalar per cycle:
aura-core/src/node.rs:37—NodeSchema.output: ScalarKind(singular)aura-core/src/node.rs:46—Node::eval(...) -> Option<Scalar>aura-engine/src/harness.rs—Edge { from, to }forwards that one scalar; the harness stores one output column per node.This is too narrow. A node's output is generally a record of scalars — a bundle of named, typed base columns that together form one composite stream over the cycles. A single scalar is just the degenerate K=1 case. OHLCV is the obvious example (open/high/low/close/volume emitted together); the position table (C10) is another (5-column position events). C8's current wording — "at most one output (one series per node)" — conflates "one output port" with "one scalar series" and is wrong: the port stays single, but its payload is a record.
This is a BLOCKER for the trading half of the walking skeleton: the position table (C10) and the broker nodes that consume it cannot exist until a node can emit more than one column.
Design decisions (converged)
Output generalizes, input does not.
NodeSchema.output: ScalarKind→RecordSchema(an ordered list of{ name, kind }fields over the four base types).Node::eval(...) -> Option<Scalar>→-> Option<Record>(one row of K scalars;None= no emission this cycle).dyn Any, no heterogeneous buffer.Binding is always field-wise.
Edgegainsfrom_field: usize— which field of the producer's record it reads. Kind-check per field:producer.output[from_field].kind == consumer.inputs[to_slot].kind.Record fields are co-fresh by construction.
eval, so they always share a cycle / timestamp. Splitting a record across N input bindings therefore needs no barrier among those fields; C6 remains for cross-source synchronization only.This is a contract change, not a refactor. C8 must be revised (and C7 sharpened) in the design ledger: a node has one output port whose payload is a record of 1..K base columns.
Blast radius
aura-core: newRecord/RecordSchematypes;NodeSchema.outputbecomesRecordSchema;Node::evalreturnsOption<Record>.aura-std:Sma,Submigrate to 1-field records (degenerate case; behaviour unchanged).aura-engine:Edgegainsfrom_field; the harness stores K output columns per node and kind-checks per field; the per-cycle push / forward path threads the field index.Scope when picked up
Prove the generalization with a neutral multi-field test node (OHLCV) — a pure substrate change, isolated from any trading domain model. The position table (C10) and brokers are deliberately out of scope; they are later cycles that consume this capability.
Ledger
Revise C8 (output is a record, not a single series) and sharpen C7 (composite stream = bundle of base columns is the node-output model, not just an ingestion-side note) when this lands.