diff --git a/docs/design/INDEX.md b/docs/design/INDEX.md index 356bd1b..5693f06 100644 --- a/docs/design/INDEX.md +++ b/docs/design/INDEX.md @@ -1680,6 +1680,8 @@ and both callers are untouched; maintenance is lazy-only — put-time indexing was rejected because it would need a roster-free doc-level identity function whose equivalence to the loaded-composite path no green test ratifies (decision log: #191 comments). + +### C19 — Bootstrap: blueprint → instance (recursive) **Guarantee.** Construction is a distinct phase, recursive at every level. Each node type has a **factory** `params → sized concrete node` (e.g. `SMA(length)` sizes its ring buffer). A **blueprint** is the param-generic, input-role-generic @@ -2590,6 +2592,116 @@ benefit — a sweep paying zero for the study wires behind an unbound tap — is **deferred to the future DCE cycle** (C23); the mechanism ships now, verified sound. (#282, 2026-07-18.) +### C28 — Internal stratification: the trading ladder, the process column, the shell +**Guarantee.** The aura workspace's crates realize a layered responsibility +model along two axes. A **ladder**, ordered by domain specificity from inner to +outer: +1. **engine** — the domain-free deterministic streaming runtime and vocabulary + (cells/kinds/freshness/firing, graph build, compile, run, taps/trace — C1–C9, + C19, C23, C24), the domain-free node roster (arithmetic/logic/rolling nodes + plus the generic `Recorder`/`GatedRecorder`/`SeriesReducer` sinks), and + generic statistics (the Monte-Carlo and moving-block-bootstrap kernels). The + layer name is wider than the crate `aura-engine`: it spans `aura-core`, + `aura-engine`, the domain-free part of `aura-std`, and the generic-statistics + surface. +2. **market** — what a market *is*, carrying no analysis or strategy intent: + instruments and pip/point geometry (C15), session anchoring, bar resampling, + market-data ingestion (`aura-ingest`). +3. **measurement** — descriptive statistics over market streams (session + statistics, conditional rates, distributions). Sibling of **strategy**: both + consume *market*, neither imports the other. +4. **strategy** — the *definition* of trading signals: bias, stop rules, sizing, + cost-model nodes. +5. **backtest** — the *evaluation* of strategies: simulated execution without + money (the `SimBroker`, position-management), the R-metric reductions and the + position-event table, and the per-run scaffold. Backtest mirrors *execution* + on the research side — execution semantics in R units, money exiled. +6. **execution** — money, account-term sizing, the live broker; already exiled to + the deploy edge by C10/C13, existing today only as that ratified boundary. + +Beside the ladder stands the **process column** — the research-process machinery +(the run registry C18, the process/campaign document types, campaign execution). +It consumes run *artifacts*, not market streams, and orchestrates runs of any +ladder layer; it stands beside the ladder, not on a rung. The **shell** (the +`aura` CLI) imports everything and is imported by nothing. + +**Import rule.** An outer ladder layer may import inner layers, never the +reverse; *measurement* and *strategy* are siblings (no import either way); +*backtest* may import *strategy*. The process column imports the engine layer +plus the run-artifact and metric interfaces, and is imported by no ladder crate; +column-internal edges are free. The shell imports all; nothing imports the +shell. **`dev-dependencies` are exempt** — tests may cross layers (the existing +`engine`/`ingest`/`registry` → `std` edges are dev-only and stay). The rule +binds **crate structure, not graph composition**: a blueprint may feed a +measurement statistic into a bias input — data flow inside a graph is free (C24); +layers govern imports, graphs compose freely. + +**Forbids.** An inner layer importing an outer one — most sharply the engine +layer importing backtest reductions, or market importing strategy. A ladder crate +importing the process column. Money (currency P&L, account sizing) inside the +strategy or backtest layers (C10/C13 — it lives only at the execution/deploy +edge). Once a second consumer warrants the split, keeping multiple layers welded +in one crate's roster. + +**Why.** The stack is a framework specialized for traders: the inner engine is a +domain-free analysis substrate (the same machinery would measure robot telemetry +or any timestamped process), the outer rungs the trading specialization, and the +two together are the "game engine for traders" (C16's game/engine split applied +*inside* the workspace, from the engine|project boundary to the intra-stack +layering). Separable responsibilities behind narrow, contract-defined seams let a +contributor focus on one rung without absorbing the rest, and make each boundary +auditable. Enforcement is the crate graph itself: once crates are cut along these +cells, a layer violation is a compile error and every new edge a visible +`Cargo.toml` diff — no linter, no discipline appeals. Five of the six seams are +already ratified contracts and this model only *names* them as layer boundaries: +the node contract (C8, engine ↔ any vocabulary), blueprint-as-data (C24, +topology ↔ engine — its shape selecting the run scaffold is the additive #286 +refinement, phase 3 below), declared taps (C27, run ↔ analysis — the only way +values leave a run), the run registry (C18, run ↔ process column), and the +deploy edge (C10/C13, everything ↔ money). Only the +process column ↔ metric interface is new (a named metric vocabulary *supplied* by +measurement and backtest instead of baked in R-only — this is #147). + +**Status (2026-07-19, milestone "Stratification — ladder, process column, +shell", #286).** This contract states the *target*. At HEAD the crates cut by +mechanical role (vocabulary / reductions / documents / orchestration / CLI), not +cleanly by layer, so the layering is realized only partially: +- The dependency *direction* already nearly obeys the rule. The one hard + production violation is `aura-engine → aura-analysis`: `report.rs:20` + re-exports the R-metrics, the position-event table, the hurdle math, and the + selection-provenance types (`RMetrics`/`RunMetrics`/`summarize_r`/ + `r_metrics_from_rs`, `PositionEvent`/`PositionAction`/`derive_position_events`, + `inv_norm_cdf`/`expected_max_of_normals`, `FamilySelection`/`SelectionMode`), + and the generic-statistics kernel in `mc.rs` carries R/bias-typed fields + (`McAggregate.bias_sign_flips`, `RBootstrap.e_r`) inside otherwise domain-free + structs. +- **That violation is the exact surface of the deliberately-deferred #147.** + Cutting it cleanly needs the metric genericity (`RunReport` plus abstracting + the registry deflation vocabulary) that #136 ratified *deferring* (user-ratified + 2026-06-27: the registry `Metric`/`metric_cmp`/deflation vocabulary "stays in + the registry by design … forcing genericity would be a one-implementor + abstraction", deferred to the World/C21 layer — see the C16 realization note). + The stratification supplies the *second* metric consumer (measurement) that the + deferral was waiting on, so retiring #147 and cutting this edge are one coupled + decision — reserved to the user, since it reverses a ratified deferral. +- The interweaving is mostly *inside* crates. `aura-std` holds four layers in one + roster: engine (arithmetic/logic/rolling + the generic sinks), market + (`session.rs`, `resample.rs`), strategy (`bias.rs`/`stop_rule.rs`/`sizer.rs` + + the cost nodes) and backtest (`sim_broker.rs`, `position_management.rs`); + `aura-analysis` holds backtest reductions and generic hurdle math together. No + crate exists yet for *measurement* (its run verb is the additive shape dispatch, + #286) or *execution* (unbuilt — the C10/C13 edge only). Under this model the + `aura-registry → aura-research` edge is column-internal and legal. +- Phased realization (each independently shippable; behaviour byte-identical + except the purely additive shape dispatch): (1) this contract; (2) cut the + `engine → analysis` edge — coupled to the #147 decision above; (3) the #286 + shape dispatch plus the per-run scaffold as a library (seeds an `aura-backtest` + crate, gives *measurement* its run verb, removes the measured O(cycles) run-time + retention); (4) split the `aura-std` roster along engine / market / + strategy+backtest; (5) split `aura-analysis` into generic statistics and + backtest metrics; (6) generify the column's metric interface (demand-driven — + this is #147). Crate names provisional; full evidence on #286 and the milestone. + --- ## Open architectural threads not yet resolved