Files
Aura/docs/design/contracts/c12-atomic-sim-unit.md
T
claude 9eb6d6b4f6 docs(readme, guides, glossary, ledger), bench: the surviving surface everywhere
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
2026-07-25 22:45:24 +02:00

88 lines
5.3 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.
# 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 24) 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)