docs,engine: drop coined "compilat", use FlatGraph / "flat graph"

"Compilat" (German "Kompilat") was a coined noun for the product of the
bootstrap compilation — neither English nor a natural fit. The runtime
artifact already has a code identifier for exactly this thing: the
`FlatGraph` struct (harness.rs). Replace the coinage with that identifier:

- prose mentions          -> "flat graph" (mirrors the type, reads plainly)
- definitional anchors    -> `FlatGraph` (C11, C23, the running-graph line)
- `render_compilat`       -> `render_flat_graph` (historical render symbol;
                             keeps the `render_blueprint` / `render_flat_graph`
                             source-vs-product pairing)
- `intra-compilat`        -> `intra-graph`
- `from_compilat` (test)  -> `from_flat`

"compilation" / "re-compilation" / "bootstrap-as-compilation" (the process,
ordinary English) are deliberately left untouched. Behaviour-preserving:
only comments, design ledger, specs/plans, one test-local variable and its
assert messages change. Full workspace test suite green; clippy clean.
This commit is contained in:
2026-06-14 17:02:15 +02:00
parent 8b330e3eaa
commit 21c1621bd0
41 changed files with 186 additions and 186 deletions
+27 -27
View File
@@ -12,7 +12,7 @@ C10 was later reframed in cycle 0007 — the intent/exposure stream is the prima
output, the position table a derived layer — see C10). C19C22 were added as the
construction / World / playground layer; C23 and the C9/C19 compilation
refinements were settled 2026-06-05 for the **Construction-layer** milestone (the
blueprint→compilat reading of composites and graph optimisation).
blueprint→flat-graph reading of composites and graph optimisation).
The `CLAUDE.md` **Domain invariants** section is the compressed, always-loaded
summary of the
subset that agents must never violate; this file is the fuller form with
@@ -265,11 +265,11 @@ sweep covers is an experiment axis, #32/C20; the node declares the knob's existe
and type, never its search interval). (2) Identity is **positional** (the slot,
C23 "by index, not name"); the path-qualified `name` is a non-load-bearing debug
symbol (like `FieldSpec.name`) — uniqueness is at the slot. **Refinement (cycle
0032):** identity in the **compilat** stays positional (C23, unchanged), but the
0032):** identity in the **flat graph** stays positional (C23, unchanged), but the
`param_space()` **name projection** — the authoring / by-name address space (the
surface a sweep axis or single-run binding addresses) — must be **injective** for a
blueprint to compile (a duplicated path is unaddressable; see C9). Two layers:
positional wiring below (the compilat), an injective name address space above (the
positional wiring below (the flat graph), an injective name address space above (the
authoring boundary). So same-type siblings in one composite no longer silently
share a name — they must be `.named(...)` apart, which is also what disambiguates a
same-type fan-in (C9). A vector knob (`LinComb.weights`) expands to `N` flat
@@ -332,7 +332,7 @@ never consumers, so only interior input slots are subject to the rule. There is
optional-input concept**: every declared input port is required (no shipped node runs
meaningfully without one; an unwarmed mode-A input is *wired-but-not-yet-valued*, not
unwired). The check is **index-based and name-free** — it touches no name machinery
and emits nothing into the compilat, so C23 is untouched (it proves the existing
and emits nothing into the flat graph, so C23 is untouched (it proves the existing
raw-index wiring is total and single-valued). Inherited identically by the raw
`Composite::new` path and the `GraphBuilder::build()` path (both compile via
`compile_with_params`).
@@ -358,7 +358,7 @@ sub-graph into the one flat instance (C19/C23): the composite *boundary* dissolv
into the raw index wiring the run loop already consumes, and names stay
**non-load-bearing** (informative debug symbols only, as `FieldSpec.name` already
is). So "nestable arbitrarily" and "graph-as-data" hold at the **blueprint
(source)** level; the running graph is the flat, index-wired **compilat**. The earlier reading — *a composite survives as a `Box<dyn Node>`
(source)** level; the running graph is the flat, index-wired **`FlatGraph`**. The earlier reading — *a composite survives as a `Box<dyn Node>`
driving a nested sub-engine* — is **explicitly rejected**: it would keep the
interior opaque to the cross-graph optimiser (C23) and add a runtime sub-loop the
flat model does not need. Inlining is what makes the composite boundary free.
@@ -376,7 +376,7 @@ completion, not a contract change. A strategy composite is simply the K=1 case
they live at the blueprint boundary and in render (cycle 0022/#46 folds each onto
its producing node as a `name := …` binding; originally `[out:<name>]` markers, #13)
but are dropped at lowering — `ItemLowering::Composite.output` is `Vec<(usize,
usize)>`, raw index pairs only, so the compilat is name-free (verified: the
usize)>`, raw index pairs only, so the flat graph is name-free (verified: the
compiled-view render stayed bit-identical across this change).
**Realization (cycle 0019 — name the composite boundary, #41; param-overlay retired,
cycle 0031).** The named-projection shape covers the surviving boundary edge-kinds:
@@ -390,9 +390,9 @@ carries a name (default = its lowercased type label, override via `.named()`), a
same-type fan-in is distinguished by naming the colliding legs, the same single act
that qualifies their param paths. Like the output and role names, **node names are
non-load-bearing** (C23): they live at the blueprint boundary and in render but are
dropped at lowering — the compilat is wired by raw index. The full composite
dropped at lowering — the flat graph is wired by raw index. The full composite
boundary signature (named inputs, multi-outputs) and the per-node param path are
legible without changing the compilat.
legible without changing the flat graph.
**Refinement (param-namespace injectivity, cycle 0032; supersedes the fan-in
distinguishability check).** A blueprint compiles only if its `param_space()` name
projection is **injective** — every path-qualified knob name is unique. A duplicated
@@ -416,7 +416,7 @@ That breadth guarded **render identity**, dead since the renderer was retired in
0026; both extra rejections are **intentionally dropped**. A future node-/wiring-name
distinguishability check, if ever wanted (e.g. for the WASM graph view's #21
thread), is decoupled from param-space injectivity. Construction-phase only; the
compilat stays name-free (C23).
flat graph stays name-free (C23).
### C10 — Strategy output is an intent/exposure stream; position management is a decoupled derived layer; brokers are downstream nodes
**Guarantee.** A strategy's primary, backtestable output is **not** an equity
@@ -670,13 +670,13 @@ of rewriting code. Naming the build phase makes the implicit "wiring" of C7/C12
explicit.
**Refinement (Construction-layer milestone, 2026-06-05).** This binding is a
**compilation**: the param-generic, named blueprint (source) is lowered to a flat,
type-erased **compilat** (C7) **wired by raw index, not by name**
type-erased **flat graph** (C7) **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 (as
`FieldSpec.name` already is). "No recompile" above 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. Naming the
build phase a compilation makes its successor explicit: the compilat is the target
build phase a compilation makes its successor explicit: the flat graph 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
@@ -697,7 +697,7 @@ traversal hazard) and the value reaches the node at the slot the sweep enumerate
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
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
@@ -726,7 +726,7 @@ definitions pass recurses). The interactive *enter/focus* counterpart (a composi
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 compilat is
**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
@@ -739,7 +739,7 @@ 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 compilat, now first-class — which `Harness::bootstrap` consumes (kinds/firing
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).
@@ -785,7 +785,7 @@ 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
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).
@@ -884,23 +884,23 @@ Recorded streams are sparse and timestamped (a record per fired cycle, tagged
### C23 — Graph compilation and behaviour-preserving optimisation
**Guarantee.** The bootstrap (C19) is a **compilation**: it lowers a param-generic,
named **blueprint** (the authoring source — nodes, composites, strategy, harness;
C8/C9/C20) into a flat, type-erased **compilat** — the frozen runnable
C8/C9/C20) into a flat, type-erased **`FlatGraph`** — the frozen runnable
instance (C7) — **wired by raw index, not by name** (`Edge { from, to, slot,
from_field }`). Composites are **inlined** at this step (C9): the composite
*boundary* dissolves entirely (there is no composite in the compilat). The
*boundary* dissolves entirely (there is no composite in the flat graph). The
blueprint's field / input-role *names* are **non-load-bearing** — the wiring
resolves by index, and names survive at most as **informative debug symbols**
(exactly as `FieldSpec.name` already is, C8), kept for tracing / rendering (C9
graph-as-data, #13) but carrying no run semantics. The compilat is then the target of **behaviour-preserving
graph-as-data, #13) but carrying no run semantics. The flat graph is then the target of **behaviour-preserving
optimisation** — any transform that leaves every observable sink trace
bit-identical (C1 is the correctness invariant) — on two levels:
- **intra-compilat** (within one graph): **common-subexpression elimination**
- **intra-graph** (within one graph): **common-subexpression elimination**
two identical nodes (same type, same bound params, same input source) merge to
one with output fan-out, so fractal composition (C9) costs no redundant compute —
and **dead-node elimination** — a node on no path to a sink is dropped.
Pure-consumer sinks (C8, no output) are never CSE candidates, so their
out-of-graph side effects are preserved by construction.
- **across the sweep family** (over the family of compilats one blueprint yields
- **across the sweep family** (over the family of flat graphs one blueprint yields
under a param sweep, C12): the sub-graph whose nodes carry **no swept param** and
whose inputs are **all sweep-invariant** (transitively from the sources — same
data window) is **loop-invariant** w.r.t. the sweep and is computed **once**; its
@@ -915,16 +915,16 @@ analysed or rewritten across its boundary, so it forecloses both levels.
for these rewrites — a behaviour-preserving transform is only meaningful because
"same input → bit-identical run" makes "same result" decidable, and a
sweep-invariant sub-graph is reproducible enough to compute once and share. The
compilat representation (C19) is the necessary condition: only a flat, inspectable
flat graph representation (C19) is the necessary condition: only a flat, inspectable
graph-as-data — with each node's declared param-ranges (C8) — lets the compiler
identify identical sub-expressions, dead nodes, and the sweep-invariant frontier.
This is precisely why a composite is an inlining (C9) and not a runtime
sub-engine: the flat compilat is what makes the whole graph optimisable.
**Status (Construction-layer milestone).** The compilat *representation*
sub-engine: the flat graph is what makes the whole graph optimisable.
**Status (Construction-layer milestone).** The flat graph *representation*
blueprint → inline / compile → flat instance — is the load-bearing substrate built
**first**; the optimisation passes (intra-compilat CSE/DCE, sweep-invariant
**first**; the optimisation passes (intra-graph CSE/DCE, sweep-invariant
hoisting) are **deferred**, behaviour-preserving follow-on work, each gated by a
"compilat with pass ≡ compilat without pass, bit-identical run" test (C1). The
"flat graph with pass ≡ flat graph without pass, bit-identical run" test (C1). The
sweep-level pass further presupposes per-node param declarations (C8 — landed in
cycle 0015 as `name`+`kind`; the swept *range* still pending #32/C20) and the sweep
orchestration itself (C12/C21).
@@ -934,9 +934,9 @@ The bootstrap-as-compilation now includes one structural gate:
C12-C19), run before name resolution. It reads the **boundary** name projection — the
authoring address space — and rejects a duplicated path (`DuplicateParamPath`). Node
names stay **non-load-bearing**: they qualify the param path at construction and are
dropped at lowering (the compilat is wired by raw index, unchanged). The check makes
dropped at lowering (the flat graph is wired by raw index, unchanged). The check makes
the by-name *authoring address space* injective; it does **not** make names
load-bearing in the compilat.
load-bearing in the flat graph.
---