Node instance name does not reach the graph model (viewer shows identical [SMA] boxes for named fan-in legs) #58
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?
Surfaced by the cycle 0031 architect drift review (node-instance naming, #56).
Cycle 0031 gave every node an instance name (default = lowercased type label,
overridable via
Sma::builder().named("fast")), which is what now disambiguatestwo same-type fan-in legs in
param_space()(sma_cross.fast.lengthvs.slow.length). But that identity does not reach the graph model:model_to_json(crates/aura-engine/src/graph_model.rs ~70-80) emits the primitive
"type"viab.label()(the type label, e.g."SMA") plus the integer index — never theinstance name. So the WASM viewer renders two SMA legs as identical
[SMA]boxes,even when the author named them
fast/slow.This was a deliberate scope decision in 0031 (spec line 211: the cycle does not
change the JSON model surface), not a regression —
sample-model.jsonand themodel_to_jsongolden are intentionally byte-identical. But it leaves the onesurviving render unable to show the disambiguation lever the author just used.
Direction (not prescriptive): have
model_to_jsonsurface the node instance name(alongside or instead of the type label) so the viewer can label a node
fast/slow.Relates to the legibility goals of #13 (graph render) and #37 (interactive
blueprint navigation). Strikeable; no commitment.
Design reconciliation (specify, in-context entry)
Spec: 0035-node-name-in-graph-model. The fork below is still listed open on this
issue ("alongside or instead of the type label"); it was resolved in the
in-context design discussion during a /boss redirect to this issue.
viewer box's primary label is the node instance name (
node_name()),always — one consistent rule, no explicit-vs-default conditional. The type
label (
label()) moves to the secondary surface (the viewer INFO/tooltippanel) and keeps driving role/colour. Unnamed nodes render their default
node_name()(lowercased type), so a lone[SMA]becomes[sma]; thatwhole-graph relabel is accepted and intended.
Rationale: coherent with the cycle-0031 direction —
param_space()addressesknobs by instance identity (
sma_cross.fast.length), so the viewer shouldspeak the same identity language the author uses to address knobs; the type is
a property, the name is the identity.
Provenance: user selected "Name als Label" in the orchestrator's
AskUserQuestion (box =
node_name()ausnahmslos; type → info panel) on2026-06-12.
Attempt 1 RESET — the render decision was semantically wrong (restart from here)
A first cycle (0035) for this issue was fully implemented and audited, then
git reset --hardto origin/main — all 5 commits discarded, never pushed.Recording the failed attempt and the corrected design so the cycle can restart
in a fresh context. This comment supersedes the earlier "Design reconciliation"
comment, which recorded the now-discarded decision.
What was attempted (and is wrong)
Ratified render rule: the viewer box's primary label =
node_name(), with thetype label demoted to the INFO panel.
cellLabelchanged${o.type}→${o.name || o.type}.Why it is wrong — on every level
The parens in a box label were always the parameter signature (
cellLabel'ssig, built fromo.params). Moving the instance name into the head positiontherefore rendered, literally,
fast(length)andslow(length)in thebrowser — which reads as "two functions
fastandslow, each called with alengthargument." That is wrong on every level:SMA, instantiated twice with different lengths.fast/sloware instance names — not function names, and not parameternames. SMA's parameter is
length.SMA(fast=2)) collapsesthe moment a node has more than one parameter: which param is
2?Type, instance name, and params are three orthogonal slots; the attempt
conflated them (instance name stolen into the function-head slot).
Corrected design (entry: brainstorm)
Leaf label as a binding:
name = TYPE(params).TYPEis the head (the function), always shown, with its real params inparens.
=.SMA(length));a bound
.bindconstant (cycle 0034) or a compiled/value-bearing view →name=value(SMA(length=2)); scales to N params (SMA(length=2, alpha=0.3)).SMA(length)(also fixes the ugly lowercased[sma]the attempt produced).For the
sma_crosssample the legs would readfast = SMA(length)/slow = SMA(length), withSubandExposure(scale)beside them.What was correct and should be reproduced
Only the viewer render rule was wrong. The engine half was sound and should
come back unchanged:
prim_record(crates/aura-engine/src/graph_model.rs) emits a"name"fieldcarrying
node_name()into the JSON model — the viewer needs the name in themodel to render the binding prefix. Both goldens (engine inline
model_goldensample-model.json) carry"name". C23/C14 hold (render/model-surfaceonly; name dropped at lowering; deterministic).
Open design points for the restart
SMA(2)vs namedSMA(length=2)inside the parens.aura graphrenders thevalue-empty blueprint, so concrete values only appear for
.bindconstants(cycle 0034) or a future compiled render —
SMA(length)is the max in the plainblueprint view.
it get the same
name = TYPE(...)treatment, and what are its "params"?fast/slowlive insidesma_cross, whichrenders collapsed by default — the disambiguation is only visible after
expanding. Possibly a separate follow-up.
Note
The ascii/
ascii-dagrenderer was retired in cycle 0026; the browser viewer(
graph-viewer.js, served byaura graphas self-contained HTML) is the onlyrender surface.
PrimitiveBuilder::label(the model's"type"field) is unchanged.Design reconciliation (specify, in-context entry)
Spec: 0035-node-name-in-graph-model. The forks below are listed open by the
"Attempt 1 RESET" comment's "open design points for the restart"; they were
resolved in an in-context design discussion this session. This comment
supersedes that open-points list — the points below are now settled.
Fork: viewer label identity (name alongside vs. instead of type). The
leaf box head renders
<name>: <TYPE>[params]— the instance name as an"is-a" declaration prefix joined by
:. The type stays the head; params stayin the brackets. Rejected, and why (so the restart does not relapse):
fast(length)(attempt 1 — steals the name into the function-head slot);fast = SMA(length)(the RESET's own proposal —=reads as a value/resultbinding, and a node's output is a stream, so it conflates instance-identity
with output-value).
Provenance: user, 2026-06-13 — "Aendere die Anzeige von 'SMA[length]' zu
'fast: SMA[length]'"; and, rejecting
=, "Aber 'fast = SMA(length)' siehtso aus, als ob 'fast' das RESULT der Funktion ist!".
Fork: which nodes carry the prefix. Only explicitly
.named()nodes. An unnamed node keeps the bare
TYPE[params];node_name()'slowercased-type default is not treated as "a name present" (it would render
noise like
sub: Sub, a redundant type-duplicate).Provenance: user, 2026-06-13 — "Wenn ein Name da ist, soll er so angezeigt
werden." (read as: an explicit name; flagged to the user as explicit-only,
who proceeded to spec on that framing).
Fork: params shown as names or values. Param names (
SMA[length]),because
aura graphrenders the value-empty blueprint. Unchanged behaviour.Provenance: established behaviour + this session's discussion.
Settled separately: square-bracket param signature
TYPE[...]alreadyshipped (commit
a051571).Out of scope (separate follow-up): collapsed-composite visibility —
fast/slowlive insidesma_cross, which renders collapsed by default, sothe prefix is only visible after expanding the composite. This cycle does not
change default expansion; it specifies the leaf render + the model surface.
Design reconciliation (specify, in-context entry) — addendum
Spec: 0035-node-name-in-graph-model. This supersedes the provenance of two
points the prior reconciliation comment recorded with an orchestrator reading;
the user has now decided them explicitly in-session (2026-06-13), with the full
thread history (including the earlier opposite choice) in front of them.
Fork: which nodes carry the prefix → only explicitly
.named()nodes.An unnamed node keeps the bare
TYPE[params];node_name()'s lowercased-typedefault is NOT surfaced (it would be redundant noise —
sub: Sub— once thetype is already the box head).
Provenance: user, 2026-06-13. The user was shown that they had earlier chosen
the opposite (surface-the-default, whole-graph relabel
[SMA]→[sma]) in thenow-superseded comment 1042 — but that choice was bound to the old
name-replaces-type notation, which the RESET (comment 1043) discarded.
Under the new
name: TYPE[params]prefix notation the user confirmedexplicit-only: "Korrekt." (agreeing the default prefix is redundant once the
type is the head), then "alle vier wie empfohlen" (point 1 = explicit-only).
Sub-decision:
named()non-empty rule → kept; its doc re-grounded in 0035.The non-empty
debug_assert!predates this cycle (written for the old notationwhere an empty name meant an empty box). The code is unchanged; the new
rationale: an explicit name is load-bearing on two surfaces — a knob-address
segment (
sma_cross.<name>.length, vianode_name()incollect_params) andthe
Some/Noneswitch for the model"name"field + viewer prefix — soSome("")is forbidden at source.Provenance: user, 2026-06-13 — "alle vier wie empfohlen" (point 2 = keep rule +
re-ground doc in 0035; point 3 = keep
debug_assert!, do not harden toassert!).Spun off (NOT this cycle): parameter ganging (one knob driving several
nodes) as an explicit composite-exposed shared param — filed as a separate
ideaissue. Explicitly NOT via name collision:param_space()is injective bydesign (C12/C19;
check_param_namespace_injective→DuplicateParamPath), so ashared address is a hard error, not a shared knob.