From a70c5faab789812868a453e6220b833dfb312f54 Mon Sep 17 00:00:00 2001 From: Brummel Date: Sun, 7 Jun 2026 21:08:49 +0200 Subject: [PATCH] =?UTF-8?q?audit:=20cycle=20B=20(0016)=20=E2=80=94=20ledge?= =?UTF-8?q?r=200016=20realization=20note=20(C8/C19),=20debt=20#36=20filed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Architect drift review of the #31 cycle (2a9a141..4b64409) against the design ledger. The feature is clean: C19/C23 realized literally (LeafFactory recipe; compile_with_params builds-then-wires slot-by-slot in the same walk param_space() projects — #34's dual-traversal hazard genuinely subsumed, one traversal, both mirror tests green incl. nesting); C12 "no recompile per param-set" holds (value-empty blueprint, vector-bound, bit-identity green); the removed Composite::schema/BlueprintNode::schema confirmed caller-free. ledger (fixed here): - C8: the 0015 note's "binding a value to a slot (#31) ... deferred" line was stale (shipped). Updated to record #31 landed in 0016, and that the param declaration's authoring home moved to LeafFactory.params() (read pre-build) alongside the built node's schema().params (the duplication is debt #36). - C19: added a "Realization (cycle 0016 — param-set injection)" note (the per-cycle pattern C8/C10 already carry for 0005/0006/0007/0015): the value-empty leaf, build-then-wire bootstrap_with_params/compile_with_params, the typed kind/arity errors, the bit-identical compilat, and the C22 blueprint-view bare-type label (value-bearing SMA(2) now only in the compiled view). debt (filed, carry-on): - Every param-bearing node declares its ParamSpecs twice (factory() and schema()), kept in lockstep only by a per-node test; drift compiles. Filed as #36 (sibling of #34's traversal-duplication concern). Not active drift — the agreement holds and is tested per node. regression: profile declares no regression scripts and no architect_sweeps — the architect review is the sole gate. No baseline to update. Cycle B is drift-clean after these amendments. NOT a milestone close — that needs the end-to-end milestone fieldtest, deferred until the sweep root (#32-#33) lands. --- docs/design/INDEX.md | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/docs/design/INDEX.md b/docs/design/INDEX.md index a04a777..e215fa8 100644 --- a/docs/design/INDEX.md +++ b/docs/design/INDEX.md @@ -260,8 +260,12 @@ symbol (like `FieldSpec.name`) — same-type siblings in one composite share a n uniqueness is at the slot. A vector knob (`LinComb.weights`) expands to `N` flat `weights[i]` entries, `N` topology-fixed (C19). Permitted kinds are `i64`/`f64`/ `bool` (a `timestamp` knob is a structural axis, C20, never a numeric sweep param). -Binding a value to a slot (#31) and enumerating a sweep (#32) are the deferred next -layers. +Binding a value to a slot landed in cycle 0016 (#31, see C19/C23); enumerating a +sweep (#32) is the deferred next layer. The 0016 binding also moved the param +declaration's *authoring* home: a value-empty blueprint leaf is a `LeafFactory` +recipe whose `params()` is read pre-build, while the built node's `schema().params` +still reports the same slots — the two are kept in lockstep by a per-node test +(a duplication filed as debt, #36). ### C9 — Fractal, acyclic composition **Guarantee.** A composite is itself a `Node` that wires a sub-graph and exposes @@ -544,6 +548,27 @@ cdylib** rebuild (C12/C13: the cdylib loads once); re-deriving an instance per param-set is a cheap **graph re-compilation**, not a code recompile. Naming the build phase a compilation makes its successor explicit: the compilat is the target of behaviour-preserving optimisation (C23). +**Realization (cycle 0016 — param-set injection).** The bootstrap now binds an +injected param-set, realizing C12's "params injected at graph build (the optimizer +sees a generic vector of typed ranges)" and C19's "factory `params → sized node`" +*literally*: a blueprint leaf is **value-empty** — `BlueprintNode::Leaf` holds a +`LeafFactory { name, params, build }` recipe, not a built node — and the value lives +only in the injected vector (no baked default), so the blueprint stays a pure +param-generic recipe. `Blueprint::bootstrap_with_params(Vec)` / +`compile_with_params` **build each leaf through its own constructor** (the single +sizing/validation gate) from its kind-checked slice **while lowering** (build-then- +wire), consuming the vector slot-by-slot in the *same* depth-first walk +`param_space()` projects — so the two share one traversal (subsuming the #34 dual- +traversal hazard) and the value reaches the node at the slot the sweep enumerates. +Arity is checked up front (`param_space().len()`); a wrong-kind or wrong-length +vector is a typed `CompileError::{ParamKindMismatch, ParamArity}` (the typed-value +check C8 deferred). The lowering/edge/source rewrite is structurally unchanged, so +the **compilat stays bit-identical** for a given point (C23, the correctness +invariant). The value *domain* (e.g. `length ≥ 1`) stays the constructor's own +`assert`; the search-range is still the run's (#32/C20). One value-empty leaf +detail for C22: the blueprint view (pre-run, param-generic) labels a leaf by **bare +type** (`LeafFactory::label` → `[SMA]`) — the value-bearing `SMA(2)` of C8's render- +label refinement now appears only in the *compiled* view (built nodes, `Node::label`). ### C20 — Strategy ↔ harness; the harness is the root sim graph **Guarantee.** A **strategy** is a reusable composite-node blueprint (C9):