From 20000ddeb36bd4b0db51b754f25a674225b33adb Mon Sep 17 00:00:00 2001 From: Brummel Date: Fri, 12 Jun 2026 16:30:43 +0200 Subject: [PATCH] =?UTF-8?q?audit:=20cycle=200034=20(#55)=20=E2=80=94=20rec?= =?UTF-8?q?ord=20structural-constant=20bind=20in=20the=20ledger;=20drift-c?= =?UTF-8?q?lean=20otherwise?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Architect drift review over 52e0214..HEAD. All hard invariants hold; the only drift was a ledger-prose gap — the new .bind() structural-constant affordance had no contract entry, so the code offered a capability the contracts did not name. Contracts (all hold): - C23: bind resolves a param name -> position at authoring time and stores the index; the compilat stays wired by raw index, the name never reaches it. The by-name authoring address space (0032 amendment) is exactly where bind sits. - C19/C8: the shrink is schema.params.remove(pos) on the single source of truth that params()/schema()/collect_params/lower_items all read, so no desync is structurally possible; param_space() injectivity (0032) is untouched (bind only removes entries). The param-declared-once posture holds. - C9/C10: a pure builder-level value op — no by-name runtime node lookup, no registry, no DSL-style dynamic resolution. - C16: zero Cargo.toml / lockfile changes. - Construction layer (collect_params/lower_items/param_space/compile_with_params) byte-unchanged — verified independently; the blueprint.rs diff is a test-only hunk at 1886, the sole production edit is bind in aura-core/src/node.rs. Regression: none configured (profile regression: []) — no-op; architect is the gate. Resolution -- fix (1 ledger note, added inline this commit): - docs/design/INDEX.md C19 — added a cycle-0034 realization note recording PrimitiveBuilder::bind as the structural-constant path (knob REMOVED from param_space), distinct from the cycle-0016 value-pin (knob stays, fixed in the injected vector); the #55 deform-vs-tune discriminator; C23 unaffected; export of a named frozen strategy deferred to #60. Cycle 0034 drift-clean after this note. Not a milestone close (no milestone fieldtest run). Gates: doc-only edit, compile-inert; cargo build/clippy/test --workspace verified green this session. --- docs/design/INDEX.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/design/INDEX.md b/docs/design/INDEX.md index fe13ef7..e7411f5 100644 --- a/docs/design/INDEX.md +++ b/docs/design/INDEX.md @@ -742,6 +742,32 @@ notation — superseding the cycle-0017 flat-ascii model and its renderer-defect workaround. The DOT/SVG are Graphviz-version-dependent and not golden-tested; the deterministic JSON model is the asserted contract. +**Realization (cycle 0034 — structural-constant bind: a knob *removed* from +param_space, #55).** `PrimitiveBuilder::bind(slot, value)` adds the **third** param +category beside the topology factory-arg (C7/C19) and the tuning param (the +cycle-0016 value-pin): a **structural constant**. The cycle-0016 binding *pins* a +value in the injected vector while the knob **stays** in `param_space` (a tuning +param the sweep varies); `bind` instead **removes** the slot from `param_space` +entirely — the knob is gone, not fixed. The discriminator is the #55 +deform-vs-tune test: a value whose variation yields another valid point of the +*same* strategy is a **tuning param** (stays in `param_space`); a value whose +variation *deforms* the strategy into a different one (e.g. the `2` of an +"SMA2-entry" bound to its two-candle construction) is a **structural constant** +(bound out), so a sweep never enumerates deformed strategies as valid family +members. Mechanically `bind` shrinks the builder's declared param surface +(`schema.params`) and wraps its build closure to re-splice the constant at its +original positional slot; the construction layer +(`collect_params`/`lower_items`/`param_space`/`compile_with_params`) is +**byte-unchanged** — both dock sites already key off `builder.params()`, so the +shrink propagates for free, and chained binds reconstruct the correct positional +vector because each layer computes its slot index relative to the param list it +sees. C23 is unaffected: `bind` resolves the param **name** to a position at +**authoring** time (the by-name authoring address space, the 0032 amendment) and +the compilat stays wired by raw index — the name never reaches it. The +complementary question — exporting a **named frozen** strategy (all/most knobs +bound) as a reusable blueprint *value* — is deferred (#60); `bind` ships only the +per-knob overlay, no registry (C9/C10 intact). + ### C20 — Strategy ↔ harness; the harness is the root sim graph **Guarantee.** A **strategy** is a reusable composite-node blueprint (C9): broker-, data-, and viz-independent, with inputs declared as named **roles**