Discover a loaded blueprint's sweepable axis names (--list-axes / graph introspect) #169
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?
A loaded-blueprint sweep (
aura sweep <blueprint.json> --axis <name>=<csv>, cycle0093, #166) resolves axes by the verbatim
param_space()names, which for anested signal are prefixed — e.g.
stage1_signal.fast.length, not the barefast.lengththe hard-wired--strategy stage1-rsweep accepts. A consumer has noway to discover the axis names short of triggering a
MissingKnob/UnknownKnoberror and reading the message.
Add an axis-discovery surface so a data-level author can list a loaded blueprint's
open knobs before sweeping — e.g.
aura sweep --list-axes <blueprint.json>orextending
aura graph introspectto print a blueprint'sparam_space()names +kinds. Surfaced by the cycle-0093 architect drift review (classified debt-low).
Design reconciliation (specify, cycle 0096)
Spec: 0096-discover-a-loaded-blueprints-sweepable-axes. This issue lists
the surface fork open (its body offers "
aura sweep --list-axes <blueprint.json>or extendingaura graph introspect"); this recordsthe resolution as a derived decision (rationale, not user-provenance).
Fork: which surface lists a loaded blueprint's sweepable axis names?
Decision → a query sub-mode on the sweep verb:
aura sweep <blueprint.json> --list-axes(path first, matching the existing.json-discriminator dispatch; flag follows the path). Not agraph introspect --axesmode.Basis (derived). The axis names
--axisaccepts are produced by thesweep's own harness-wrapping, not by the raw blueprint. A loaded-blueprint
sweep resolves axes against
wrap_stage1r(reload(doc)).param_space()(crates/aura-cli/src/main.rs:3190-3191): the loaded signal composite (its
namefield is"stage1_signal") is nested as aBlueprintNode::Composite(main.rs:2917), and
collect_paramsprefixes a nested composite's paramswith that composite's own
name(crates/aura-engine/src/blueprint.rs:760-766).So the sweep-accepted names are prefixed —
stage1_signal.fast.length,not the raw
fast.lengththe blueprint's ownparam_space()yields.Empirically confirmed against the current tree:
aura sweep stage1_signal_open.json --axis stage1_signal.fast.length=2,3→ passes name resolution (advances to
MissingKnob("stage1_signal.slow.length")— the loaded-blueprint sweep requires every open knob bound).
aura sweep stage1_signal_open.json --axis fast.length=2,3→
UnknownKnob("fast.length").aura sweep stage1_signal_open.json --axis nonexistent.knob=1,2→
UnknownKnob("nonexistent.knob")— the error names only the unknownknob, never the valid set, so today there is genuinely no discovery path.
Therefore only the sweep verb — which owns the wrapping — can print the
names the user will actually pass to
--axis. Agraph introspect --axesreading the raw blueprint would print
fast.length(names the sweeprejects); teaching
graph introspectto applywrap_stage1rwould couplethe general read-only-query surface to one specific research harness. So
correctness (print exactly what
--axisaccepts) beats query-surfacecohesion. A further robustness gain: because
--list-axescomputes thesame probe the sweep resolves against, it stays correct by construction
when the hard-wired stage1-r wrapping is retired (#159) — the listed names
track whatever the sweep actually resolves, with no second source of truth.
Derived sub-decisions (output shape + edge cases)
<name>:<kind>line per open knob, inparam_space()order (deterministic), kind = the
ScalarKindtoken (I64/F64/Bool/Timestamp). Forstage1_signal_open.json:stage1_signal.fast.length:I64/stage1_signal.slow.length:I64.stage1_signal.json) → printnothing, exit 0 — a valid "no open axes" answer, not an error.
--list-axesis a query, mutually exclusive with a real sweep →combined with
--axisit is a usage error (exit 2).blueprint_from_jsonvalidation already reject with a namedaura:errorand exit 2 (main.rs:4101-4111), before arg parsing;
--list-axesridesbehind that boundary.
Ships independently of #173, which needs this to know which axes to re-fit
per in-sample window.