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.6 KiB
Markdown
119 lines
8.6 KiB
Markdown
# C19 — Bootstrap: blueprint → instance (recursive): history
|
||
|
||
> FROZEN HISTORICAL RECORD. Each block below was true as of its cycle/date stamp
|
||
> and may be superseded; this file is NOT current truth and NOT a grounding
|
||
> surface. Current contract: [c19-bootstrap.md](c19-bootstrap.md).
|
||
|
||
**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. (Renamed in cycle 0024: `BlueprintNode::Primitive` holds a
|
||
`PrimitiveBuilder { name, schema, build }` — the recipe now carries the full
|
||
signature, see the C8 0024 realization; `bootstrap_with_params`/`compile_with_params`
|
||
moved onto `Composite` when `struct Blueprint` collapsed into it, see the C19 0024
|
||
realization.) `bootstrap_with_params(Vec<Scalar>)` /
|
||
`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 **flat graph 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** (`PrimitiveBuilder::label`, was `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`).
|
||
|
||
**Realization (cycle 0017 — blueprint render = main graph + definitions).** The
|
||
`aura graph` blueprint view (C9 graph-as-data, #13) renders the **authored
|
||
structure** as a *program with subroutines*: a flat **main graph** wiring the
|
||
harness with each composite shown as a **single opaque node** `[name]`, plus a
|
||
`where:` section that defines each **distinct** composite type **once** (its
|
||
interior with named input-entry nodes and outputs folded onto their producers as
|
||
`name := …` bindings (render refined through cycles 0019–0022; originally
|
||
`[in:k]`/`[out]` port markers); deduped by `name()`, collected
|
||
recursively so nested composites are opaque nodes with their own definitions). This
|
||
supersedes #13's original cluster-box model and is the durable split this view
|
||
realizes: **blueprint = source** (composites as named subroutines, body once) vs.
|
||
**compiled = inlined machine form** (C23, boundary dissolved). The substantive cause
|
||
for retiring cluster boxes is a real renderer defect — `ascii-dag` 0.9.1's subgraph
|
||
level-centering rounds sibling x-positions with `/2`, overlapping wide sibling
|
||
labels (width/parity-sensitive, no config/padding dodge surviving unequal-width
|
||
siblings); the **flat** layout is collision-free, and both views now build flat
|
||
graphs only. The model also scales (blueprint size tracks top-level wiring, not
|
||
inlined node count) and removes #13's nested-composite `unimplemented!` (the
|
||
definitions pass recurses). The interactive *enter/focus* counterpart (a composite
|
||
collapsed to a navigable node) is the playground's, parked as a separate concern
|
||
(#37); the static CLI keeps the all-at-once definitions form (#38).
|
||
|
||
**Realization (cycle 0024 — the root is the fully-bound composite; the flat graph is
|
||
a named type).** `struct Blueprint` is **deleted**: the root graph IS a `Composite`,
|
||
and `compile_with_params`/`bootstrap_with_params`/`param_space` are its methods.
|
||
What distinguished the root — its bound data sources — is now a property of its input
|
||
roles: `Role` carries `source: Option<ScalarKind>` (`None` = an open interior port,
|
||
wired by the enclosing graph; `Some(kind)` = a bound ingestion feed). A composite is
|
||
**runnable iff every root role is bound** (C3: sources bind at ingestion only); an
|
||
open root role is a compile-time `CompileError::UnboundRootRole`. So the "main graph"
|
||
is no longer a separate kind — only the composite all of whose roles are
|
||
source-bound, governed by the same conditions as any other node. Compilation now
|
||
targets a **named type**: `compile` validates structurally **pre-build** (via
|
||
`signature()`, no node constructed — an ill-typed wiring is caught before any build
|
||
closure fires) and emits `FlatGraph { nodes, signatures, sources, edges }` — the
|
||
C23 flat graph, now first-class — 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` reads it without a built-node
|
||
`schema()` call (which no longer exists, see the C8 0024 realization).
|
||
|
||
**Realization (cycle 0026 — graph render redesign: model + WASM-Graphviz viewer,
|
||
#51).** `aura graph` no longer renders ASCII. The render path is now two pieces:
|
||
a read-only **model serializer** (`aura_engine::model_to_json`, iteration 1) that
|
||
walks the root composite + every distinct composite type into a deterministic,
|
||
hand-rolled JSON model (C14, golden-tested; the engine's last hand-rolled JSON
|
||
writer after `RunReport::to_json` moved to serde in cycle 0033; the
|
||
swapped-param mis-wire property moved here from the old compiled-view test), and a
|
||
**self-contained HTML viewer** (`aura-cli::render::render_html`, iteration 2) that
|
||
inlines that model, the ported prototype viewer JS, and a vendored Graphviz-WASM
|
||
blob into one page emitted to stdout. Layout/SVG happen in the browser via
|
||
WebAssembly — aura ships no layout engine and stays a serializer (C9: graph-as-data,
|
||
no `eval`/build on the path). The viewer is a render asset (C10 — no node/strategy
|
||
logic, no DSL); it labels every input pin from the model's now-real names (C23
|
||
debug symbols, named in cycle 0027) and colours wires by the four scalar base
|
||
types (C4). This **retires `ascii-dag`** and its adapter (`graph.rs`), the
|
||
`--compiled`/`--macd` flag plumbing, and the invented `#Sf`/`:=`/`histogram →`
|
||
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 flat graph 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).
|