8688a60ded
The single-file ledger had grown to 2968 lines / ~42k tokens, mixing current design law with accreted history: 59 cycle-stamped realization blocks, 18 [HISTORY] passages, 22 supersession markers, and the C10 / C22 / C24 reframe sagas layered several supersessions deep. A code-grounding audit (31 agents, adversarially verified) confirmed 11 defects stated as current truth: stale crate homes from the C28 #288 roster split (cost nodes, PositionManagement, PositionEvent, Session), the renamed InputSpec->PortSpec, the pre-#241 project model in C16 and the open-threads section, a stale HarnessKind retirement deferral in C24, and three C28-internal inconsistencies. New shape, per the ailang precedent: - INDEX.md stays the sole addressable entry point: foundation, external components, a C-id-keyed contract map (one line per contract), and only the genuinely open architectural threads. - contracts/cNN-<slug>.md carries each contract's current truth only: Guarantee / Forbids / Why with ratified refinements integrated, plus a code-anchored Current state. All confirmed defects are fixed here; crate anchors were re-verified against the tree. - contracts/cNN-<slug>.history.md (18 sidecars) and INDEX.history.md preserve every superseded block verbatim, stamps and issue refs intact, under a frozen-record banner. Nothing was deleted: superseded design intent remains an addressable working-tree artifact, off the per-cycle audit walk. - Ledger discipline is now stated in INDEX.md: live files are edited in place at cycle close, superseded text moves verbatim to the sidecar, and a supersession marker in a live file is itself an audit finding. Every contract file was verified against its old text by an independent zero-loss pass (statement-by-statement) plus a code-accuracy spot check; C-ids and contract titles are unchanged, so existing C-id citations in code, tests, and issues resolve as before.
119 lines
8.0 KiB
Markdown
119 lines
8.0 KiB
Markdown
# C19 — Bootstrap: blueprint → instance (recursive)
|
|
|
|
**Guarantee.** Construction is a distinct phase, recursive at every level. Each
|
|
node type has a **factory** `params → sized concrete node` (e.g. `SMA(length)`
|
|
sizes its ring buffer). A **blueprint** is the param-generic, input-role-generic
|
|
graph-as-data produced by running a Rust builder (C9); it carries *free* numeric
|
|
params (declared ranges) and *free* input roles. The **bootstrap** binds
|
|
`(blueprint + param-set + data bindings + seed)` into a concrete, **frozen
|
|
instance** — buffers sized, topology fixed. This is precisely the "wiring / graph
|
|
build" that C7 ("sized at wiring", "topology frozen per sim") and C12 ("params
|
|
injected at graph build") reference; the same machinery applies recursively up to
|
|
the harness (C20). A sweep builds many instances from one blueprint; instances are
|
|
disjoint (C1).
|
|
|
|
This binding is a **compilation**: the param-generic, named blueprint (the source)
|
|
is lowered to a flat, type-erased **`FlatGraph`** (C23) **wired by raw index, not
|
|
by name** (`Edge { from, to, slot, from_field }`) — composite boundaries dissolve
|
|
entirely and field / role names are demoted to **non-load-bearing** debug symbols
|
|
(exactly as `FieldSpec.name` already is, C8/C23). One narrow exception (#275): a
|
|
`SourceSpec.role` — the lowered bound-`Role` name — is **load-bearing for source
|
|
binding**, the key `Harness::run_bound` / `bind_sources` resolve a keyed source
|
|
supply against; every other flat-graph name (edges, ports, composite boundaries)
|
|
stays a non-load-bearing debug symbol, and the raw-index positional `run` path
|
|
carries no role. "No recompile" means no **Rust / 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.
|
|
|
|
**Forbids.** Params that change topology (a topology change is a *different*
|
|
blueprint — Fork A, C7 "frozen"); resizing buffers after bootstrap; running a sim
|
|
against an un-bootstrapped blueprint.
|
|
|
|
**Why.** Separating the param-generic blueprint from the param-bound instance is
|
|
what makes one strategy reusable across a whole sweep and lets the optimizer mutate
|
|
"the 20" by *rebuilding* an instance (cheap; no recompile, C12) instead of
|
|
rewriting code. Naming the build phase makes the implicit "wiring" of C7/C12
|
|
explicit — and naming it a *compilation* makes its successor explicit: the flat
|
|
graph is the target of behaviour-preserving optimisation (C23).
|
|
|
|
## Current state
|
|
|
|
**Value-empty recipe.** A blueprint leaf is **value-empty** — `BlueprintNode::Primitive`
|
|
holds a `PrimitiveBuilder { name, schema, build }` recipe
|
|
(`crates/aura-core/src/node.rs`), not a built node — and the tuning value lives only
|
|
in the injected param vector (no baked default), so the blueprint stays a pure
|
|
param-generic recipe. This realizes C12's "params injected at graph build" and C19's
|
|
factory `params → sized node` literally. `compile_with_params(&[Scalar])` /
|
|
`bootstrap_with_params(Vec<Scalar>)` on `Composite`
|
|
(`crates/aura-engine/src/blueprint.rs`) **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 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 value *domain* (e.g.
|
|
`length ≥ 1`) stays the constructor's own `assert`; the search-range is the run's
|
|
(#32/C20, still pending). The lowering is structurally invariant under the injected
|
|
point, so the **flat graph stays bit-identical** for a given point (C23, the
|
|
correctness invariant).
|
|
|
|
**The root is the fully-bound composite.** There is no separate `Blueprint` type:
|
|
the root graph **is** a `Composite`, and `compile` / `compile_with_params` /
|
|
`bootstrap_with_params` / `param_space` are its methods. What once distinguished the
|
|
root — its bound data sources — is a property of its input roles: `Role` carries
|
|
`source: Option<ScalarKind>` (`crates/aura-engine/src/blueprint.rs`) — `None` = an
|
|
open interior port wired by the enclosing graph, `Some(kind)` = a bound ingestion
|
|
feed (C3: sources bind at ingestion only). A composite is **runnable iff every root
|
|
role is bound**; an open root role is a compile-time `CompileError::UnboundRootRole`.
|
|
`compile` validates structurally **pre-build** (via `signature()`, no node
|
|
constructed — an ill-typed wiring is caught before any build closure fires) and
|
|
emits the `FlatGraph`, which `Harness::bootstrap` consumes (kinds/firing from the
|
|
carried signatures, buffer depth from `lookbacks()`); the per-flat-node signature
|
|
travels beside the node, so `bootstrap` needs no built-node `schema()` call.
|
|
|
|
**`FlatGraph` shape.** `FlatGraph { nodes, signatures, sources, edges, taps }`
|
|
(`crates/aura-engine/src/harness.rs`): `signatures[i]` is the static `NodeSchema` of
|
|
`nodes[i]` gathered at lowering; `sources` are the lowered bound roles in
|
|
role-declaration order; `taps` are the declared measurement points (C27), with
|
|
interior-composite taps hoisted to the root list.
|
|
|
|
**Structural-constant bind (#55).** `PrimitiveBuilder::bind(slot, value)`
|
|
(`crates/aura-core/src/node.rs`) adds the **third** param category beside the
|
|
topology factory-arg (C7/C19) and the tuning param (the value-pin): a **structural
|
|
constant**. Pinning a value in the injected vector leaves the knob **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
|
|
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; both dock sites already key off `builder.params()`, so the
|
|
construction layer is byte-unchanged and chained binds reconstruct the correct
|
|
positional vector (each layer computes its slot index relative to the param list it
|
|
sees). `bind` resolves the param **name** to a position at **authoring** time (the
|
|
by-name authoring address space) and the flat graph stays wired by raw index — the
|
|
name never reaches it (C23 unaffected). The complementary export of 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).
|
|
|
|
**Graph render.** `aura graph` renders no ASCII: the render path is a deterministic
|
|
JSON **model serializer** (`aura_engine::model_to_json`,
|
|
`crates/aura-engine/src/graph_model.rs`) plus a self-contained WASM-Graphviz **HTML
|
|
viewer** (`aura-cli::render::render_html`) that inlines the model and lays it out in
|
|
the browser — aura ships no layout engine (C9: graph-as-data). This render surface,
|
|
and the debug-symbol labels it draws, belongs to C9/C22.
|
|
|
|
## See also
|
|
- [C7](c07-scalar-soa.md), [C9](c09-fractal-composition.md), [C12](c12-atomic-sim-unit.md) — sized-at-wiring, graph-as-data, params-injected-at-build that this phase names.
|
|
- [C8](c08-node-contract.md) — the `PrimitiveBuilder` / `NodeSchema` recipe and `FieldSpec.name` as the non-load-bearing precedent.
|
|
- [C13](c13-hot-reload-frozen-deploy.md) — "no recompile" means no cdylib rebuild.
|
|
- [C20](c20-strategy-harness.md) — the harness is the recursive top of the bootstrap.
|
|
- [C22](c22-playground-traces.md) — the graph render / viewer surface.
|
|
- [C23](c23-graph-compilation.md) — the flat graph as the optimisation target.
|
|
- [C24](c24-blueprint-data.md) — the deferred named-frozen-blueprint value (#60).
|
|
|
|
> History: [c19-bootstrap.history.md](c19-bootstrap.history.md)
|