9eb6d6b4f6
Slice 8, closing the #319 retirement's prose and bench debt. Bench argv rides exec (fixed_cost single-run probe, campaign surfaces, and the seed helper that still called the retired sweep at runtime — caught by the bench run itself); all five fingerprints unchanged against the committed baselines, confirming record-line parity through the retirement. Live docs (README, authoring guide, project layout, glossary) describe only exec + campaign documents + graph introspect --params; three glossary entries explicitly mark their verb retired. Ledger amendments per the C29 discipline — C25's executor-verb-set re-settled (exec + the --override residue), C14's dual grammar reduced to the one dispatch, C24's document-built runs/families + gated-intake route list (lockstep with the code comment), C12's override clause and identity anchor repointed to the runner-layer hash computation, C18/C22/C27/C01 mention rewrites — superseded sentences moved verbatim to the history sidecars (c25's created). Stale dual-grammar doc comment on is_blueprint_file rewritten. refs #319
88 lines
5.3 KiB
Markdown
88 lines
5.3 KiB
Markdown
# C12 — The atomic sim unit and the four orchestration axes
|
||
|
||
**Guarantee.** The atomic unit is `(frozen topology + param-set + data-window +
|
||
RNG-seed) → deterministic run → metrics`. Parameters are typed, ranged, runtime
|
||
values injected at graph build — no recompile per param-set; the optimizer sees a
|
||
generic vector of typed ranges. A **bound blueprint param is that param's
|
||
default**: "open" means *must be bound by an axis*, "bound" means *default,
|
||
overridable by an axis*, so a campaign axis (param-sweep) may name a bound
|
||
param — the family boundary re-opens it on the probe and on every member
|
||
reload, and the axis binds it per cell; `exec`'s blueprint leg still requires
|
||
every param resolved (a truly open param refuses), and its own `--override
|
||
NODE.PARAM=VALUE` (#246 residue, #319) reopens exactly the named bound param
|
||
for that one execution — the single-member analogue of a campaign axis.
|
||
Identity is untouched: `content_id_of` (`crates/aura-research/src/lib.rs`) is
|
||
the one hashing primitive, read directly off the authored document by
|
||
`aura_runner::member`'s `run_signal_r`/`run_blueprint_member` — where the
|
||
manifest's `topology_hash` is computed inline (#319 Task 9 retired the
|
||
CLI-side wrapper that used to duplicate this one call) — never a re-opened
|
||
probe, and each member manifest records its per-cell bindings (#246, ratified
|
||
2026-07-12; the restriction this amends — axes bind only open knobs — was an
|
||
implementation consequence of `bind()` shrinking the param surface, not a recorded
|
||
decision). Raw data is shared read-only across sims via `Arc<[T]>` (the
|
||
data-server is built for this). Four axes orchestrate the atomic unit:
|
||
(1) param-sweep (grid/random), (2) optimization (argmax metric), (3) walk-forward
|
||
(rolling in-sample optimize + out-of-sample test), (4) Monte-Carlo (N seeded
|
||
realizations perturbing input). **MC = sweep over seeds**; each realization is
|
||
itself deterministic given its seed.
|
||
|
||
**Forbids.** Baking a specific search strategy (Bayesian/genetic) into the
|
||
primitive — those are pluggable policies atop the atomic unit; recompiling on a
|
||
param change.
|
||
|
||
**Why.** A stable primitive + orchestration axes keeps "wahnsinnig schnell"
|
||
(embarrassingly parallel across the unit) cleanly separated from search policy.
|
||
Seed-as-input reconciles Monte-Carlo with C1. The "frozen topology" of the atomic
|
||
unit is one harness instance, selected by the harness's **structural axes** (C20);
|
||
the structural experiment matrix is the outer orchestration over this dimension,
|
||
the tuning sweep the inner (C19/C20).
|
||
|
||
## Current state
|
||
`Harness::run` is typed as a **producer seam** — the object-safe `Source` trait
|
||
(`peek`/`next`, plus `bounds` and a `resident_records()` residency probe;
|
||
`crates/aura-engine/src/harness.rs`) that the k-way merge drives (C3). Two source
|
||
shapes back it. The eager `load_m1_window`/`close_stream` path
|
||
(`crates/aura-ingest/src/lib.rs`), wrapped as `VecSource`, materializes a whole
|
||
stream and is retained for bounded loads. The streaming `M1FieldSource`
|
||
(`crates/aura-ingest/src/lib.rs`) pulls a data-server window lazily, borrowing one
|
||
`Arc<[M1Parsed]>` chunk per pull (zero-copy *within* a source) and decoding each
|
||
`Scalar` on demand, so its **source ring** is resident O(one chunk), not
|
||
O(window length) — `resident_records()` is a *per-source* bound, not
|
||
whole-process RSS.
|
||
|
||
Raw-data sharing is realized both within and across sims. The data-server's
|
||
`FileCache` retains each window's parsed chunks read-only for the pass, so process
|
||
residency is O(records-touched) — the **replay-many** sharing model, not a leak.
|
||
Across sims, the sweep / Monte-Carlo / walk-forward families (axes 2–4) build their
|
||
members over **one** shared `Arc<DataServer>` (one `FileCache`;
|
||
`crates/aura-ingest/src/lib.rs`), so a window is parsed once and every member's
|
||
`M1FieldSource` borrows the same cached `Arc<[M1Parsed]>` chunks. The single-pass
|
||
*parse* cost of a window is tracked as #95.
|
||
|
||
Axis 1 (param-sweep) is built. `GridSpace` enumerates a cartesian lattice over
|
||
discrete per-slot value-lists; `RandomSpace` draws `N` seeded points over typed
|
||
continuous `ParamRange`s (I64 inclusive `[lo,hi]`, F64 half-open `[lo,hi)`),
|
||
validated against the param-space before any run; a `ListSpace` enumerates an
|
||
explicit point list. All implement the `Space` trait the disjoint `sweep` /
|
||
`run_indexed` core is generic over (`crates/aura-engine/src/sweep.rs`), so every
|
||
enumeration runs through one execution path (C1: results in enumeration order, not
|
||
completion order). The other axes are realized as families over that core:
|
||
`walk_forward` + `WindowRoller` (`crates/aura-engine/src/walkforward.rs`) for the
|
||
rolling in-sample/out-of-sample split, `monte_carlo`
|
||
(`crates/aura-backtest/src/mc.rs`) for the seed sweep; optimization is argmax over
|
||
a sweep's metrics, a policy atop the core rather than a baked-in strategy. The
|
||
seeded sampler reuses the bit-stable `SplitMix64`
|
||
(`crates/aura-analysis/src/lib.rs`) as a **code-path-disjoint** instance from the
|
||
data-edge seed RNG (the source-seam firewall, #52/#71: they share only the `u64`
|
||
type, never a path).
|
||
|
||
## See also
|
||
- [C1](c01-determinism.md)
|
||
- [C11](c11-sources-record-replay.md)
|
||
- [C18](c18-registry.md)
|
||
- [C19](c19-bootstrap.md)
|
||
- [C20](c20-strategy-harness.md)
|
||
- [C23](c23-graph-compilation.md)
|
||
|
||
> History: [c12-atomic-sim-unit.history.md](c12-atomic-sim-unit.history.md)
|