feat(aura-core,aura-engine,aura-cli): node-instance naming retires ParamAlias
Every blueprint node now carries a name. A primitive builder gains an optional
instance name (Sma::builder().named("fast")); when omitted it defaults to the
node's type label, ASCII-lowercased verbatim ("SMA"->"sma", "SimBroker"->
"simbroker"). param_space() is now uniformly <node>.<param> at every level
including the root (sma_cross.fast.length, exposure.scale). Fan-in
distinguishability (C9) and signature_of re-key onto the node name: two same-type
siblings both defaulting to "sma" collide and IndistinguishableFanIn fires, so
one act -- naming the legs "fast"/"slow" -- fixes both the naming collision and
the fan-in check. The index-addressed ParamAlias overlay, Composite.params, the
Composite::new 5th argument, aliases_on, and check_alias_indices are removed
(Role.name and OutField.name untouched). Ledger C9 and C23 amended.
This is why the change is correct, not merely convenient: blueprints are
value-empty (C11), so the thing that would otherwise distinguish two SMAs --
their length -- is not present at construction; identity must come from a name,
not a deferred value. Closes the #56 friction surfaced by the param-space &
sweep milestone fieldtest (a freshly-authored 2-SMA cross was unbindable and
would not bootstrap without two hand-counted ParamAlias overlays).
Two plan defects were corrected during implementation and verified:
- the three new fan-in/path tests authored sma_cross at root level, which would
qualify to "fast.length" (root prefix is empty) and is not the nested case the
fan-in check inspects; nesting sma_cross under a root (a shared
sma_cross_under_root helper) restores the asserted "sma_cross.fast.length" and
IndistinguishableFanIn{node:2};
- three cycle-0030 named-binder tests bound the real harness by the old names
(sma_cross.fast / scale) and were migrated to the new path strings, surfaced by
the workspace test gate.
Verified by the orchestrator: cargo build/test --workspace green (198 tests,
0 red), clippy --all-targets -D warnings clean. model_to_json emits the type
label + factory param names (node-name-independent), so sample-model.json and the
graph_model golden are byte-identical (untouched). NodeSchema gained a Default
derive (the builder default-name test constructs an empty schema). fieldtests/
are frozen non-workspace records, not migrated.
closes #56
This commit is contained in:
+27
-24
@@ -349,30 +349,33 @@ its producing node as a `name := …` binding; originally `[out:<name>]` markers
|
||||
but are dropped at lowering — `ItemLowering::Composite.output` is `Vec<(usize,
|
||||
usize)>`, raw index pairs only, so the compilat is name-free (verified: the
|
||||
compiled-view render stayed bit-identical across this change).
|
||||
**Realization (cycle 0019 — name the composite boundary, #41).** The same
|
||||
named-projection shape now covers the other two boundary edge-kinds, so **all
|
||||
three** are uniform: `input_roles` is a `Vec<Role { name, targets }>` (was a bare
|
||||
`Vec<Vec<Target>>`) and a composite carries `params: Vec<ParamAlias { name, node,
|
||||
slot }>`, alongside `output: Vec<OutField>`. Each is an ordered, positionally-indexed
|
||||
**named projection** of interior handles. Param aliasing is a **pure naming overlay**,
|
||||
not curation: `param_space()` relabels an aliased slot's surface name **in place** —
|
||||
slot order, arity, and kinds are unchanged, so the sweep surface is identical and the
|
||||
`param_space_mirrors_compiled_flat_node_param_order` anchor stays green. Like the
|
||||
output names, role and param **names** are **non-load-bearing** (C23): they live at
|
||||
the blueprint boundary and in render (`[in:<name>]` / `[param:<name>]` markers) but
|
||||
are dropped at lowering — the compilat is wired by raw index and a dangling alias is
|
||||
rejected at compile (`BadInteriorIndex`), not silently lowered. The full composite
|
||||
boundary signature (named inputs, params, multi-outputs) is now legible without
|
||||
changing the compilat.
|
||||
**Refinement (fan-in distinguishability, 2026-06-08).** A fan-in node (>1 input)
|
||||
is well-formed only if its colliding sources — sources with equal recursive
|
||||
signatures (type initial + alias initials + recursive input signatures) — do not
|
||||
hide an unnamed configuration axis: a collision is a `CompileError`
|
||||
(`IndistinguishableFanIn`) when at least one colliding source carries an
|
||||
unaliased param slot. Genuinely-interchangeable sources (equal signatures, no
|
||||
param) stay legal. Construction-phase only; the compilat stays name-free (C23).
|
||||
The graph view renders each fan-in input as the shortest sibling-unique prefix
|
||||
of its source signature.
|
||||
**Realization (cycle 0019 — name the composite boundary, #41; param-overlay retired,
|
||||
cycle 0031).** The named-projection shape covers the surviving boundary edge-kinds:
|
||||
`input_roles` is a `Vec<Role { name, targets }>` (was a bare `Vec<Vec<Target>>`),
|
||||
alongside `output: Vec<OutField>`. Each is an ordered, positionally-indexed
|
||||
**named projection** of interior handles. **Param projection is no longer a
|
||||
composite overlay** (the index-addressed `ParamAlias` was retired in cycle 0031):
|
||||
a node's surface param name flows from its own **instance name** — every node
|
||||
carries a name (default = its lowercased type label, override via `.named()`), and
|
||||
`param_space()` is uniformly `<node>.<param>` at every level including the root. A
|
||||
same-type fan-in is distinguished by naming the colliding legs, the same single act
|
||||
that qualifies their param paths. Like the output and role names, **node names are
|
||||
non-load-bearing** (C23): they live at the blueprint boundary and in render but are
|
||||
dropped at lowering — the compilat is wired by raw index. The full composite
|
||||
boundary signature (named inputs, multi-outputs) and the per-node param path are
|
||||
legible without changing the compilat.
|
||||
**Refinement (fan-in distinguishability, 2026-06-08; node-name keying, cycle 0031).**
|
||||
A fan-in node (>1 input) is well-formed only if its colliding sources — sources
|
||||
with equal recursive **node-name** signatures (each node contributes its name —
|
||||
the instance name, default = the lowercased type label — then its inputs'
|
||||
signatures in slot order, stopping at a named source) — do not hide an unnamed
|
||||
configuration axis: a collision is a `CompileError` (`IndistinguishableFanIn`)
|
||||
when at least one colliding source carries a **param** (a param-bearing same-name
|
||||
collision), resolved by giving the colliding nodes distinct names. Paramless
|
||||
interchangeable same-name sources (equal signatures, no param) stay legal.
|
||||
Construction-phase only; the compilat stays name-free (C23). The graph view
|
||||
renders each fan-in input as the shortest sibling-unique prefix of its source
|
||||
signature.
|
||||
|
||||
### C10 — Strategy output is an intent/exposure stream; position management is a decoupled derived layer; brokers are downstream nodes
|
||||
**Guarantee.** A strategy's primary, backtestable output is **not** an equity
|
||||
|
||||
Reference in New Issue
Block a user