Files
Aura/docs/design/contracts/c19-bootstrap.history.md
T
claude 8688a60ded docs(ledger): split the design ledger into an INDEX map, per-contract live files, and history sidecars
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.
2026-07-21 16:40:36 +02:00

119 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 00190022; 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).