Cut the engine's backtest-metrics edge via RunReport<M> (C28 phase 2) #292
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 2 of the Stratification milestone (contract C28, Status block in
docs/design/INDEX.md). User-ratified 2026-07-20 together with phase 5; ratification and the split disposition of the coupled deferral are recorded on #147. This realizes item 1 of #147 (RunReport<M>genericity); item 2 (the registry deflation vocabulary) stays deferred until a second metric consumer exists (#290).Situation (post-#291)
aura-enginestill names backtest-metric types in production:crates/aura-engine/Cargo.tomlcarriesaura-backtestin[dependencies]-- a commented TRANSIENT widening introduced by #291 so thereport.rsre-export stays name-compatible.RunReport.metricsis concretelyRunMetrics;summarize(pip reduction,report.rs) returnsRunMetrics.mc.rscarries R/bias-typed fields inside otherwise generic structs (McAggregate.total_pips/max_drawdown/bias_sign_flips,RBootstrap.e_r) beside a genuinely generic statistics kernel (MetricStats,quantile,resample_block).Goal
The engine's production surface names no backtest-metric type:
RunReportgeneric over its metric payload; the R-typed reductions and aggregations live in the backtest layer; the generic statistics kernel lives at its C28 foundation home; consumers instantiate the trading metric at the process column / CLI edge. Behaviour-preserving (C1);runs.jsonlbyte-identity (C18) is the hard gate. Exact genericity shape, item routing, and consumer rewiring are derived against C28 during spec production and recorded here as decision-log comments before the spec is written.refs #147
Decision log (spec production) -- genericity shape and item routing
Recon of the post-#291 tree (worktree HEAD
94aaa4c) settles the load-bearing forks. Derived decisions with rationale, for audit and veto.RunReport<M>in the engine, no default type parameter; the concrete alias lives inaura-backtest(pub type RunReport = aura_engine::RunReport<RunMetrics>;, plus aliases for the generic family types where consumers name them). Rationale: a defaultM = RunMetricsin the engine would itself name the backtest type and not cut the edge; "run report with trading metrics" is backtest vocabulary, so the alias is layer-honest.RunManifeststays concrete and engine-owned (itsselection: Option<FamilySelection>embeds the foundation-grade analysis type -- the #291 D3 payoff).aura-analysis(foundation statistics):MetricStats(+from_values),quantile,resample_block, and theSplitMix64RNG they consume (deterministic pure math; the engine re-imports them, a legal inner->foundation edge). Toaura-backtest:summarize(constructsRunMetrics),McDraw/McFamily/McAggregate(+from_draws)/assemble_mc/monte_carlo,RBootstrap/r_bootstrap. Rationale:McAggregate::from_drawsreadsRunMetricsfields BY NAME (total_pips/max_drawdown/bias_sign_flips) -- generifying it is the phase-6 metric-vocabulary abstraction, explicitly deferred; wholesale relocation is the honest cut.monte_carlocomposes the engine's generic parallel kernelrun_indexed, which stays in the engine (C1 machinery). Generic in the engine:SweepPoint<M>/SweepFamily<M>/sweep/assemble_sweep,WindowRun<M>/WindowOutcome<M>/WalkForwardResult<M>/walk_forward, theSweepBinder/RandomBinderbounds,param_stability.aura-enginedropsaura-backtestfrom[dependencies](the #291 TRANSIENT widening, back to[dev-dependencies]for its tests);aura-backtestgainsaura-enginein[dependencies]. End state is cycle-free for lib targets -- the cycle closes only through the engine's dev-dep edge, the same pattern the workspace already tolerates viaaura-vocabulary.aura-registrygainsaura-backtest([dependencies]);aura-campaignpromotes its dev-dep to[dependencies](productionr_bootstrap/RunMetricsuses inexec.rs);aura-clialready depends on it.RunReportalias,RunMetrics,summarize,summarize_r,monte_carlo,McFamily,McAggregate,RBootstrap,r_bootstrap, position events) fromaura_backtest, metric-agnostic machinery (RunManifest,MeasurementReport, spaces,sweep,walk_forward, trace utils) fromaura_engine. The analysis re-export (FamilySelectionetc.) stays -- foundation-grade, legal.aura-analysis ⊆ {}(no aura-* deps),aura-engine ⊆ {aura-core, aura-analysis},aura-backtest ⊆ {aura-core, aura-engine}. The process column (registry/campaign/cli) stays out of the table -- its trading-awareness is C28-legal and its edge policy is #147-item-2 territory.RunManifest.broker"measurement" sentinel honesty fix (stays deferred with #147 item 2); the registryMetric/deflation vocabulary (phase 6, #290 seeder). The ledger's phase-2 label ("cut the engine -> analysis edge"), stale since #291 re-identified the violation as the backtest re-export, is corrected by this cycle's Status-block update.runs.jsonl/families.jsonlbyte-identity (all moved types verbatim;RunReport<M>keeps field ordermanifest,metrics; serde derive auto-bounds coverM = RunMetrics); the CLI pre-serialized-splice contract (main.rsfamily_member_line/mc_member_line) unchanged. All existing byte-pin tests stay green: the engineto_json/round-trip pins (instantiated via dev-depRunMetrics), the registry legacy-line tests, the moved metrics legacy tests, the drift guard.