Files
Aura/docs/design/contracts/c16-engine-project-split.md
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

6.0 KiB

C16 — Engine / project separation; three-tier node reuse

Guarantee. aura is the reusable engine; each research project is a separate external repo that depends on aura via cargo (the game-engine / game split). Node reuse is cargo-native, in three tiers: aura-std (universal blocks, shipped with the engine) / shared node crates (cross-project-reusable, their own repos, pulled as cargo git deps) / project-local node crates (experimental, project-specific). A reusable node is an rlib dependency; the hot-reload unit is the project-side cdylib that composes it (C13).

A project is a directory anchored by a static Aura.toml (project context, paths only: data archive root, runs dir), in two tiers (#241, ratified 2026-07-12):

  • Data-only — the default, smallest project: Aura.toml + blueprints/ + runs/, blueprints and research documents over the std vocabulary, no crate, no build step.
  • Native — node logic lives in node crates: separate cdylib crates referenced via Aura.toml [nodes], scaffolded and attached by a dedicated verb (the visible role-2 switch, C25).

The load boundary tier-selects: a [nodes] pointer list → load that crate; a root Cargo.toml → the pre-#241 native project, unchanged; neither → std-vocabulary-only. aura new scaffolds the data-only tier; aura nodes new scaffolds a node crate beside the project and attaches it. During research the aura host loads and runs the project (C13 hot-reload); for deploy the chosen strategy + broker freeze into a standalone binary.

Dependency policy (amended 2026-06-10). Dependencies are admitted by deliberate, per-case review — what a crate pulls in weighed against what it buys — with particular scrutiny for anything that enters the frozen deploy artifact (C13: this bot = this commit). Well-established standard crates (serde, rayon, …) pass that review and are used wherever they do the job, including in the bot. There is no blanket zero-dependency commitment and no blanket admission; hand-rolling what a vetted standard crate already does is the anti-pattern, not the dependency. aura-ingest is the data-source ingestion edge, not a dependency firewall.

Forbids. Project-specific signals in the aura repo (it keeps at most example/fixture nodes under examples/ for its own tests); a multi-project manager inside aura; a bespoke node registry/marketplace (cargo + Gitea is the package mechanism). Dependency admission is governed by the per-case policy above, not a blanket ban.

Why. The engine/game split keeps the engine sharp and reusable while each project versions its own research with its own forward-queue. Promotion (local → shared → std) is the ordinary Rust reuse gradient, no new mechanism. The original "a project is always a Rust crate" invariant was deliberately amended (#241) once the role model diagnosed that the smallest project carries no native logic at all.

Current state

The engine workspace carries the non-node crates beyond aura-std; the full roster and its layering are C28's ladder — this contract does not re-enumerate it. aura-ingest is the data-source ingestion edge, where the data-server external tree enters.

Engine ↔ domain seam — the metric-generic engine (decision log: #136 → #147/#290/#291/#292). aura-engine is the domain-free, metric-generic run loop: RunReport<M> (crates/aura-engine/src/report.rs) is parametrized over a metric type. The concrete trading instantiation M = RunMetrics and the backtest metric reductions (RunMetrics, RMetrics, summarize_r, PositionEvent / PositionAction / derive_position_events) live in the outer-rung crate aura-backtest (crates/aura-backtest/src/metrics.rs). The domain-neutral statistics substrate and selection provenance — the multiple-comparison hurdle math (inv_norm_cdf, expected_max_of_normals), the bootstrap/permutation kit (MetricStats, resample_block, permute), the MetricVocabulary trait, and FamilySelection / SelectionMode — live in aura-analysis (crates/aura-analysis/src/lib.rs). aura-registry's selection vocabulary and aura-measurement's IC (IcMetrics) are the trait's two production implementors. This is the realized form of the once-deferred "make RunReport generic / turn the orchestration layer into a domain-agnostic substrate" work.

Campaign-execution leaf. aura-campaign owns campaign-execution semantics — cell enumeration, preflight, gate evaluation, winner selection, walk-forward rolling, realization assembly (C18) — as a leaf library whose deps deliberately exclude aura-ingest / aura-std / aura-composites; harness construction and data binding enter only through the one-method MemberRunner seam (&dyn MemberRunner), so each consumer binds its own runner while the semantics live here once. It is explicitly not C21's World: it realizes one campaign document and owns no topology, data sources, or UI.

Two-tier scaffolding. aura new emits the data-only project (crates/aura-cli/src/scaffold.rs: Aura.toml + blueprints/*.json + runs/, no crate); aura nodes new emits a node crate beside the project and appends the [nodes] pointer (crates/aura-cli/src/main.rs; the load-boundary tier hints live in graph_construct.rs::tier_hint_for_type_id). Provenance widened additively: a data-only run stamps commit-only (crates/aura-runner/src/project.rs::Env::provenance).

See also

  • C1 — the behaviour-preserving invariant the crate extractions kept
  • C13 — hot-reload authoring loop / frozen deploy artifact
  • C18 — the run registry and campaign realization assembly
  • C21 — the World the campaign leaf is deliberately not
  • C25 — the role-2 switch aura nodes new makes visible
  • C28 — the full crate roster and the layer ladder

History: c16-engine-project-split.history.md