feat(aura): fan-in input distinguishability — construction constraint + source-derived render
A fan-in node (>1 input) whose colliding sources hide an unnamed configuration axis is now illegal at construction, and the definition view renders each fan-in input as a source-derived recursive-signature identifier instead of the positional, meaningless #A/#B. The root defect was sma_cross: two Sma into a Sub with unaliased length params, rendering sma_cross() -> (cross) with two indistinguishable [SMA] and [Sub(#A,#B)] — the author meant fast vs slow but the identity hid it. Now it renders sma_cross(fast:i64, slow:i64) with [SMA(fast)]/[SMA(slow)] and [Sub(#Sf,#Ss)]. Shape (single source of truth for "signature" shared by engine + CLI): - aura-engine signature_of(): a node's recursive authoring identity — type initial + alias initials + each wired input's signature (recursing into interior leaves, stopping at named roles/composites at their initial). - aura-cli leaf_label/fan_in_identifiers: shortest sibling-unique prefix of a source's signature, never below its base (type + alias initials); a role-fed slot renders its name verbatim (#price); equal-signature interchangeable inputs keep the positional letter. - aura-engine IndistinguishableFanIn: a signature collision is a fault only when a colliding source carries an unaliased param (the unnamed axis); param-less interchangeable sources (fan_composite's Pass/Pass) stay legal. Param-aware criterion (refined during design): keeps the blast radius to the param-bearing alias-less fixtures (sma_cross CLI + engine, the nested fast_slow); fan_composite and the hand-wired flat fixtures stay green. Placement decision (deviates from the plan): the constraint runs as a structural pre-pass (check_fan_in_distinguishability) at the head of compile_with_params, BEFORE the param-arity gate — not inside inline_composite as the plan drafted. Reason: the no-param compile() of a param-bearing composite would hit ParamArity first and preempt the fault; the spec mandates a structural check needing no param values, so the pre-pass is the spec-aligned home. Alias-validity ordering (BadInteriorIndex before the fan-in fault) is preserved at the pre-pass head. C23 untouched: the check is construction-phase; the compilat stays name-free (compiled_view_golden byte-stable). Ledger C9 carries the refinement. Known debt (non-gating): the alias-index validity check now exists in both inline_composite and the pre-pass (the pre-pass reaches every composite first, making inline_composite's copy effectively dead). Left for a separate tidy — a 5-line, correctness-neutral removal with its own test surface. closes #44
This commit is contained in:
@@ -322,6 +322,15 @@ are dropped at lowering — the compilat is wired by raw index and a dangling al
|
||||
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.
|
||||
|
||||
### 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