Implement composite nodes (C9): a Node wiring a sub-graph with one output #12
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?
Concern
C9 (design ledger
docs/design/INDEX.md) defines fractal composition: "Acomposite is itself a
Nodethat wires a sub-graph and exposes one output;signal, combined signal, and strategy are all the same abstraction, nestable
arbitrarily." This is not implemented.
aura-stdships only flat single nodes(
crates/aura-std/src/{sma,sub,add,lincomb,exposure,sim_broker}.rs); a graph isassembled only as a flat node array via
Harness::bootstrap(
crates/aura-engine/src/harness.rs). There is no way to package a sub-graph asa reusable named node.
Direction
A composite is a type implementing the
Nodetrait(
crates/aura-core/src/node.rs) that internally wires a sub-graph of nodes andpresents one output port (C8: at most one output) plus declared input roles. It
must hold the existing invariants: acyclic (C9), the four scalar kinds at its
edges (C7), and the firing policies on its declared inputs (C6).
Relation to the builder/blueprint layer
C9 also states "Wiring is written in Rust (builder API)" and C19 defines the
blueprint as "the param-generic graph-as-data produced by running a Rust
builder". Claim (unverified, a design fork for brainstorm to settle): a composite
is most naturally expressed through such a builder — wiring sub-nodes by named
handle rather than the raw
Edge { from: 0, .. }indices used today — so thebuilder/blueprint layer is likely a prerequisite or co-requisite, not a separate
later step. The exact boundary (does the composite own a
Blueprint, or is it aNodedelegating to a bootstrapped sub-Harness?) is an open design question.Why it matters
Without composites, "build me this signal and show its graph" cannot show a
signal's internals — a signal is not yet a named thing with a visible interior.
Composites are the unit that makes signal reuse (C16 three-tier) and the
playground's nested structure view (C22) possible.
Acceptance
Nodetype that wires >=2 sub-nodes and exposes one output.Harnesslike any node (C9 self-application).aura-stdor example composite (e.g. an SMA-cross signal) demonstrates it end-to-end.Related: #13 — the graph-render feature consumes composites as ascii-dag subgraph (cluster) boxes; the "useful cut" there depends on the named builder/blueprint layer discussed here.
Design fork settled -- commit
ff1dce5, ledger C23 + C9/C19 refinements.A composite is NOT a runtime Box driving a nested sub-Harness; that reading is explicitly rejected (it keeps the interior opaque to the cross-graph optimiser and adds a runtime sub-loop the flat model does not need). A composite is an AUTHORING-LEVEL node: a blueprint fragment the bootstrap COMPILES AWAY BY INLINING into the one flat, type-erased compilat (wired by raw index; field/role names are non-load-bearing debug symbols).
So the blueprint layer is a co-requisite -- the representation IS the composite mechanism -- but only the minimal compile substrate. The ergonomic named-handle wiring API is deferred (out of this milestone's scope).
Acceptance below stands in spirit, read in light of C23:
The exact API shape comes from the spec (next step).
Resolved by cycle 0012 (spec/plan 0012-blueprint-compile-composites, feat
a4fb5d7, audit9fbc16a, ledger contractff1dce5).The design fork this issue flagged — composite-as-runtime-Node vs composite-through-the-builder — was settled toward the latter: a
Compositeis an authoring-level node, NOT aBox<dyn Node>sub-engine.Blueprint::compile()inlines it by raw-index lowering into the flat(nodes, sources, edges)the unchangedHarness::bootstrapconsumes, so the sacrosanct deterministic run loop is byte-untouched (C1) and the composite interior stays fully inspectable for the deferred C23 optimiser. Recursive index rewriting handles nesting; construction faults surface as a typedCompileError; the lowered compilat is validated by bootstrap's existing kind/Kahn check.Acknowledged debt filed separately: #24 (schema() panic vs typed CompileError) and #25 (schema() re-alloc at resolve). Render follow-up tracked in #13.