feat(aura-core): name input ports
PortSpec gains a non-load-bearing `name: String`, so an input port is named just as FieldSpec.name (output) and ParamSpec.name (param) already are — input ports were the lone unnamed member of the node signature. Identity stays positional by slot (C23); the name is render/debug only, never read by bootstrap or the run loop. PortSpec drops Copy (String is not Copy), exactly as ParamSpec already does. - Every aura-std node names its input slots: SMA/EMA "series", Sub/Add "lhs"/"rhs", Exposure "signal", SimBroker "exposure"/"price" (the slots become self-documenting), LinComb "term[i]" and Recorder "col[i]" generated in their build loops (mirroring LinComb's existing weights[i] param loop). - derive_signature carries a composite's Role.name into the derived input port (it was dropped before — the output side already carried FieldSpec.name), so the graph model is homogeneously named at both levels. - model_to_json (port_json + the composite-header inputs in scope_json) emits the name as a third tuple element: ["f64","any","exposure"]. The byte golden was re-captured (machine bytes) and its substring twins updated; the model is now fully named across inputs/outputs/params. - All 16 PortSpec construction sites threaded in one compile-gate change; test fixtures carry fixture names. C8 realization note added to the design ledger. Why name-only, no validation: the name is a pure debug symbol. Wire-by-name was rejected (it would be a C23 contract change). Bootstrap slot-wiring validation (which would close #21's same-kind swap footgun) is deferred to its own cycle — a name alone does not catch the swap; it makes the slots self-documenting and gives a future validation something to check against. Verified: cargo test --workspace 168 green; clippy --all-targets -D warnings clean; cargo build --workspace clean. Read-only render path (C9), no serde (C14), scalar kinds unchanged (C4). closes #50 refs #21 refs #51
This commit is contained in:
@@ -26,14 +26,20 @@ pub enum Firing {
|
||||
Barrier(u8),
|
||||
}
|
||||
|
||||
/// One declared input **port** of a node: its scalar kind and firing policy (C6).
|
||||
/// The lookback depth is NOT here — it is a build-time *sizing* concern answered by
|
||||
/// `Node::lookbacks()`, not part of the static signature (a node's lookback can
|
||||
/// depend on an injected param, e.g. `Sma`'s window = its `length`).
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
/// One declared input **port** of a node: its scalar kind, firing policy (C6), and
|
||||
/// a non-load-bearing name. The lookback depth is NOT here — it is a build-time
|
||||
/// *sizing* concern answered by `Node::lookbacks()`, not part of the static
|
||||
/// signature (a node's lookback can depend on an injected param, e.g. `Sma`'s
|
||||
/// window = its `length`). The `name` is a **non-load-bearing** debug symbol (C23):
|
||||
/// identity is the positional slot, the name is for tracing / graph rendering
|
||||
/// (#13), never read by bootstrap or the run loop (which wire by index). A
|
||||
/// `String`, not `&'static str` like `FieldSpec.name`: a variadic node generates
|
||||
/// per-slot names (`term[0]`), exactly as `ParamSpec.name` does (`weights[0]`).
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PortSpec {
|
||||
pub kind: ScalarKind,
|
||||
pub firing: Firing,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// One declared output column of a node's record: its name (metadata for sinks /
|
||||
@@ -171,11 +177,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn port_spec_carries_firing() {
|
||||
let a = PortSpec { kind: ScalarKind::F64, firing: Firing::Any };
|
||||
let b = PortSpec { kind: ScalarKind::F64, firing: Firing::Barrier(0) };
|
||||
let a = PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "lhs".into() };
|
||||
let b = PortSpec { kind: ScalarKind::F64, firing: Firing::Barrier(0), name: "rhs".into() };
|
||||
assert_eq!(a.firing, Firing::Any);
|
||||
assert_eq!(b.firing, Firing::Barrier(0));
|
||||
assert_ne!(a.firing, b.firing);
|
||||
// the name is carried (non-load-bearing, but present)
|
||||
assert_eq!(a.name, "lhs");
|
||||
assert_eq!(b.name, "rhs");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user