Split aura-analysis into generic statistics and backtest metrics (C28 phase 5) #291
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 5 of the Stratification milestone (contract C28, Status block in
docs/design/INDEX.md). User-ratified 2026-07-20 together with phase 2; the ratification and the split disposition of the coupled deferral are recorded on #147.aura-analysisinterweaves two roles:inv_norm_cdf,expected_max_of_normals,MetricStats, the bootstrap kernel -- pure math naming no trading concept.RMetrics,RunMetrics,summarize_r,r_metrics_from_rs, the position-event table (PositionEvent/PositionAction/derive_position_events),FamilySelection/SelectionMode.Under C28 the statistics half is foundation-grade (usable from any rung), while the backtest-metrics half belongs to the backtest layer. The split is the precondition for phase 2 (cutting the
aura-engine -> aura-analysisedge): after it, the engine may legally keep the domain-free statistics dependency -- only the backtest-metrics dependency is the layer violation.Behaviour-preserving structural cut (C1);
runs.jsonlbyte-identity (C18) and all goldens unchanged. Exact crate names and the per-item roster assignment are derived against C28 during spec production and recorded here as decision-log comments before the spec is written.Decision log (spec production) -- derived roster and crate assignment
Recon of the current tree (main HEAD
b39fd63) settles the split's load-bearing forks. All five are derived decisions recorded with rationale for audit and veto; the phase itself was user-ratified 2026-07-20 (recorded on #147).Ground (verified).
aura-analysisis a single file (crates/aura-analysis/src/lib.rs, 1163 lines) whose two halves are internally uncoupled: the generic-statistics items (inv_norm_cdfat :501,expected_max_of_normalsat :534) are called by no backtest item and reference no backtest type; the composition happens only externally (crates/aura-registry/src/lib.rs:824).MetricStatsand the moving-block bootstrap kernel do NOT live inaura-analysis-- they are native toaura-engine/src/mc.rs(:48, :193) and out of this phase's scope (they belong to the engine-edge cut, phase 2).aura-backtest.RunMetrics,RMetrics,summarize_r,r_metrics_from_rs,PositionEvent/PositionAction/derive_position_events(with the privater_col/cost_colcolumn maps andSQN_CAP) move into the existing backtest-layer crate as ametricsmodule. Rationale: C28 files backtest reductions under the backtest layer; and the positional-column lockstep contract betweensummarize_randPositionManagement::FIELD_NAMES(crates/aura-backtest/src/position_management.rs:28-49vs today'scrates/aura-analysis/src/lib.rs:137-164) becomes intra-crate, removing a documented cross-crate fragility (that contract comment still namesaura-std, stale since #288 -- evidence the cross-crate form drifts).aura-backtestgains the workspaceserdedependency; its aura-* dependency set stays{aura-core}, so the C28 structural test (crates/aura-vocabulary/tests/c28_layering.rs) is unaffected by design (it filters non-aura deps).aura-analysisstays and becomes the domain-free statistics crate. Post-move it holdsinv_norm_cdf+expected_max_of_normals(plus D3), with[dependencies]shrinking toserdeonly (noaura-coretype remains). Rationale: no new workspace member, no rename cascade; the remaining content is exactly the "generic statistics" half C28 names; a pure-statistics crate is foundation-grade, importable from any rung without violating the ladder direction.FamilySelection+SelectionModestay inaura-analysis. By heritage they are sweep-selection provenance, but by content they are domain-free (metric NAME as a free string, trial counts, deflation/plateau annotation scalars, seeds -- verified field-by-field atcrates/aura-analysis/src/lib.rs:17-53: no R, no pip, no trading type). Keeping them beside the hurdle math meansRunManifest.selection(engine-side) keeps embedding a foundation-grade type, so the phase-2 edge cut needs genericity only forRunReport.metrics, not aRunManifestredesign. This is the structurally decisive assignment of the split.crates/aura-engine/src/report.rs:20becomes twopub uselines (seven names fromaura_backtest, four fromaura_analysis); every indirect consumer (aura-registry,aura-cli,aura-composites,aura-ingest) compiles unchanged. Accepted consequence:aura-backtestmoves fromaura-engine's dev-dependencies into[dependencies]-- a transient widening of the known layer violation, removed by phase 2 on the same branch (the ratified order, #147).aura-campaigngainsaura-backtestas a dev-dependency only. Its production code reachesRunMetricsthrough the engine re-export (crates/aura-campaign/src/exec.rs:17), which D4 preserves; the only direct import of a moving symbol is the metric-vocabulary drift guard (crates/aura-campaign/tests/metric_vocabulary_e2e.rs:12), a test target. The guard's import splits across the two crates (summarize_r/RunMetricsfromaura_backtest;FamilySelection/SelectionModeunchanged fromaura_analysis); its 17-name assertion is untouched.Scope notes:
mc.rs's R/bias-typed fields (McAggregate,RBootstrap) are untouched (phase 2). Extending the C28 structural test's coverage beyond the node crates is deferred to phase 2, when the target edges exist. Behaviour-preserving throughout: serde shapes byte-identical (C18), goldens and the drift guard stay green; the bulk move is agit mvso blame survives.