Files
Aura/docs/design/contracts/c12-atomic-sim-unit.md
claude f108291b7f audit: harvest 2026-07-26 cycle close — intake enumeration completed, ledger notes, stale comments
Architect drift review (scope 77ad046..HEAD): What holds — the #343
reference-semantics hash is code-backed on both output surfaces
(record line + trace index), the RiskRegime::Fixed stamp/re-derive
lockstep is complete both ways, and both new guide examples build
against the binary. Drift resolved in this commit: C24's
root-name-gated intake enumeration gains the introspect --taps FILE
branch plus its missing per-site pin (byte-identical refusal to the
register sibling — the #331 class-enumeration lesson applied); C27
gains the #337 realization note (positive discovery view closes the
recovery-only gap); C12's inline-hash sentence updated to the topo
parameter; five stale dispatch_run comments reworded to name
exec_blueprint_leg as the surviving owner.

Remaining drift routed: the unpinned guide op-scripts are a durable
debt class, filed as #344 (idea) rather than swept here.

Regression gate: aura-bench all five fingerprints OK (report-only
deltas within noise on a loaded box; no baseline move, nothing to
ratify).

refs #337
refs #343
2026-07-26 14:03:09 +02:00

95 lines
5.8 KiB
Markdown
Raw Permalink 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. The
reopened execution's `topology_hash` stays the base document's own — reference
semantics, not the reopened topology's (#343, revised; full clause in
[C24](c24-blueprint-data.md)'s "Reproduction identity"). 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 by default (`run_signal_r`'s
`topo: Option<&str>` parameter's `None` arm, every caller but one; #319 Task 9
retired the CLI-side wrapper that used to duplicate this one call), or
supplied by the caller as a ready reference-semantics hash (`Some`, #343
revised — `exec`'s override branch passes the loaded base document's own id,
computed before `reopen_all`, so the SAME value reaches both the record line
and the trace-store persistence) — never a re-opened probe either way, 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)