Declare node tunable parameters in the schema (typed, ranged) #30
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?
Part of milestone "The World — parameter-space & sweep" (cycle A — the root of the sequence).
Node parameters are currently hard-coded at build sites in the Rust builder — e.g.
SMA(2),Exposure(0.5)— so there is no declared, enumerable parameter surface for an orchestration axis to vary. Contract C8 (docs/design/INDEX.md) already reserves this: a node'sschema()declares "the node's own tunable parameters — typed, with ranges, which aggregate into the blueprint's param-space the optimizer sweeps". C23 names the gap explicitly: the sweep-level pass "presupposes per-node param declarations (C8 — deliberately not in the schema yet)".This cycle adds the declaration: each node type exposes its tunable parameters as typed, ranged values that aggregate into the blueprint's param-space. No sweeping yet — only the declarable surface that param-set injection (next cycle) and the sweep (C12.1) build on.
Design is not yet settled (param type mechanism, how ranges are expressed, how per-node params aggregate to the blueprint) — entry via brainstorm → specify → planner.
Ledger refs: C8, C12, C19, C23 (docs/design/INDEX.md).
Refinement of the "design not yet settled" note — two precisions from a design discussion
Both sharpen what this cycle's param declaration must carry, and shift the #30 / #32 boundary. Neither is decided — they are arguments for the brainstorm entry, not a ratified design.
Precision 1 — the range form is not uniform; it is per-scalar-kind
"Range" as a single notion is misleading. The four scalar kinds (C7) are structurally different as a parameter domain, because "how is it enumerated" differs per type:
i64— countable; the grid islo..=hi.f64— continuous; an interval[lo, hi]holds uncountably many values. How finely it is sampled (5 points? 50? random-100?) is a property of the run, not the node — so an f64 declaration carrieslo, hibut nostep.bool— no range concept; the domain is{false, true}. A uniformlo..hiwould have to writefalse..true, which is nonsense — this alone refutes a single range form.timestamp— likely not a tuning param at all; a timestamp-valued knob (e.g.session_start) is almost always a structural axis (which data window, C20), not a numerically swept param.Proposed shape: an
enum ParamDomainwith one variant per admissible kind, parallel to the existingScalar/ScalarKindline — not a genericRange<T>, because the domains differ structurally, not just in element type:Open question for the brainstorm: may all four kinds be params, or only i64/f64/bool?
Precision 2 — the search-range belongs to the run, not the node; the validity constraint drives no mechanism
The range that an optimization run sweeps (
length in 5..50one run,2..200the next, with a chosen discretization) is itself a parameter of that run. So there are two ranges at two locations, and they do not collapse:length >= 1. Permanent type property; known only to the node author.The search axis therefore belongs in the experiment-builder surface (#32 / C20), not in the node.
Functional analysis of what a param declaration must carry — what the param-set bind step (cycle B, #31) actually reads:
Identity + kind + slot is the load-bearing part: the bootstrap must know "knob 0 of this node is an i64 named length" to bind the vector, and the sweep (cycle C, #32) must know which knobs exist. That drives mechanism.
The validity constraint drives nothing. It is touched only to check an injected value, and only catches what the run misconfigured (the sweep enumerates the run-supplied search-axis; if that lies inside the valid set — which the run author ensures — the constraint never fires). And the guard already exists, at the right place:
A schema-level constraint would only duplicate this
assert!and fire slightly earlier (at bind, not at construction).One condition makes the definition domain functional after all: an autonomous optimizer whose search-range is not run-supplied but derived from the node domain ("sweep the whole valid range"). That, however, forces the node to invent an upper bound (
length up to 200) that is not a truth about the node — the tension Precision 1's f64 point and this precision both flag. The two readings are mutually exclusive: either the run supplies the search-range (node constraint is a pure guard) or the optimizer derives it from the node domain (node must invent a bound it does not own).Scope consequence for #30 vs #32
This thins the param declaration to its functionally-forced core:
assert!) and an optional recommended default range (UX hint for a C22 playground slider /aura newscaffolding) are optional add-ons with a named, smaller purpose — each decided separately in the brainstorm, neither the substance of #30.The substance of #30 is that a param exists at all as a typed, addressable knob.