From 47179ce5a4192d72d1777d2a3c241a79c3e7b0b8 Mon Sep 17 00:00:00 2001 From: Brummel Date: Sun, 14 Jun 2026 00:04:55 +0200 Subject: [PATCH] spec: 0038 dedup-sma-cross-test-fixtures (boss-signed) Collapse the three verbatim-duplicated SMA-cross harness test fixtures (synthetic_prices, sma_cross, composite_sma_cross_harness) in aura-engine's blueprint.rs and sweep.rs #[cfg(test)] modules into one shared crate-root #[cfg(test)] mod test_fixtures. Behaviour-preserving, test-only. Auto-signed under /boss: all objective gates green (precondition, self-review, grounding-check PASS) and a unanimous five-lens spec-skeptic panel returned SOUND. refs #53 --- .../0038-dedup-sma-cross-test-fixtures.md | 269 ++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 docs/specs/0038-dedup-sma-cross-test-fixtures.md diff --git a/docs/specs/0038-dedup-sma-cross-test-fixtures.md b/docs/specs/0038-dedup-sma-cross-test-fixtures.md new file mode 100644 index 0000000..7b77c81 --- /dev/null +++ b/docs/specs/0038-dedup-sma-cross-test-fixtures.md @@ -0,0 +1,269 @@ +# Dedup the SMA-cross harness test fixtures inside aura-engine — Design Spec + +**Date:** 2026-06-13 +**Status:** Draft — awaiting user spec review +**Authors:** orchestrator + Claude + +## Goal + +Collapse the verbatim-duplicated SMA-cross harness **test fixtures** that +currently live in two separate `#[cfg(test)]` modules of `aura-engine` into a +single shared, crate-local fixture module that both modules import. This is a +pure, behaviour-preserving tidy: `#[cfg(test)]`-only, no production code change. + +Closes #53 (re-scoped today three-way → two-way: cycle 0036 drifted the CLI +sample off this topology, so the CLI binary is no longer a third peer; the +surviving duplication is entirely inside `aura-engine`). + +### What is duplicated today + +Three fixtures are defined **verbatim** in both +`crates/aura-engine/src/blueprint.rs` (`#[cfg(test)] mod tests`) and +`crates/aura-engine/src/sweep.rs` (`#[cfg(test)] mod tests`): + +| Fixture | blueprint.rs | sweep.rs | Status | +|---|---|---|---| +| `synthetic_prices() -> Vec<(Timestamp, Scalar)>` | :1520 | :256 | byte-identical (`diff` clean) | +| `sma_cross() -> Composite` | :1593 | :274 | identical modulo whitespace | +| `composite_sma_cross_harness() -> (Composite, Receiver, Receiver)` | :1614 | :298 | identical modulo whitespace/comments | + +`sweep.rs:271` already documents its copies as *"duplicated from blueprint.rs"*. +No test pins the copies equal, so an edit to one silently diverges the other — +the exact hazard #53 names. + +### Explicitly out of scope (must NOT be touched) + +- `blueprint.rs:1114 sma_cross_under_root(named: bool)` — a *different* fixture + (a naming-test variant), not a verbatim copy. +- `blueprint.rs:1538 hand_wired_sma_cross_harness()` — the flat hand-wired + baseline the composite is compared bit-for-bit against; blueprint-local. +- `sweep.rs:335 run_point()` / `sweep.rs:355 sma_cross_grid()` — sweep-local + helpers that *consume* the shared fixtures but are not duplicated. +- `graph_model.rs:311 sma_cross()` / `:340 sample_root` — a fourth, + **intentionally minimal** copy kept small and standalone for the graph-model + golden test. Leaving it independent is deliberate; do not fold it in. + +## Architecture + +Add one new crate-local, test-only module to `aura-engine`: + +- `crates/aura-engine/src/test_fixtures.rs`, declared in `lib.rs` as + `#[cfg(test)] mod test_fixtures;` — consistent with the existing + `#[cfg(test)] mod reexport_tests` precedent at `lib.rs:53`. +- The three fixtures move there unchanged, as `pub(crate)` free functions. +- `blueprint.rs` and `sweep.rs` test modules delete their local copies and gain + `use crate::test_fixtures::*;` (or named imports). + +**Why a crate-root `#[cfg(test)]` module, not "make one file canonical and +import from it":** the two copies live in *private* `#[cfg(test)] mod tests` +submodules. A sibling module cannot import another module's private test items. +A `pub(crate)` `#[cfg(test)]` module hung off the crate root is the idiomatic +Rust home for fixtures shared across unit-test modules, and the crate already +uses exactly this shape (`reexport_tests`). The C16 "engine ships no sample" +constraint is untouched: a `#[cfg(test)]` module is never compiled into a shipped +artifact. + +## Concrete code shapes + +### Delivered code — the new shared fixture module + +`crates/aura-engine/src/test_fixtures.rs` (test-only; the three fixtures moved +verbatim, made `pub(crate)`): + +```rust +//! Shared `#[cfg(test)]` fixtures for the SMA-cross signal-quality harness, +//! consumed by the `blueprint` and `sweep` unit-test modules. Kept in one place +//! so the harness topology cannot silently diverge between them (see #53). +//! Gated test-only at the declaration site in `lib.rs` +//! (`#[cfg(test)] mod test_fixtures;`), matching the `reexport_tests` precedent. + +use crate::blueprint::{BlueprintNode, Composite, Edge, OutField, Role}; +use crate::harness::Target; +use aura_core::{Firing, Scalar, ScalarKind, Timestamp}; +use aura_std::{Exposure, Recorder, SimBroker, Sma, Sub}; +use std::sync::mpsc; + +/// Seven synthetic F64 ticks driving the harness; deterministic input fixture. +pub(crate) fn synthetic_prices() -> Vec<(Timestamp, Scalar)> { + [ + (1_i64, 1.0000_f64), + (2, 1.0010), + (3, 1.0030), + (4, 1.0060), + (5, 1.0040), + (6, 1.0010), + (7, 0.9990), + ] + .iter() + .map(|&(t, p)| (Timestamp(t), Scalar::F64(p))) + .collect() +} + +/// The SMA-cross signal as a reusable value-empty composite: one input role +/// (price), one output (fast-minus-slow spread). Lengths injected at compile. +pub(crate) fn sma_cross() -> Composite { + Composite::new( + "sma_cross", + vec![ + Sma::builder().named("fast").into(), + Sma::builder().named("slow").into(), + Sub::builder().into(), + ], + vec![ + Edge { from: 0, to: 2, slot: 0, from_field: 0 }, + Edge { from: 1, to: 2, slot: 1, from_field: 0 }, + ], + vec![Role { + name: "price".into(), + targets: vec![Target { node: 0, slot: 0 }, Target { node: 1, slot: 0 }], + source: None, + }], + vec![OutField { node: 2, field: 0, name: "out".into() }], + ) +} + +/// The signal-quality harness as a value-empty composite blueprint with two +/// recording sinks (equity, exposure). +#[allow(clippy::type_complexity)] +pub(crate) fn composite_sma_cross_harness() -> ( + Composite, + mpsc::Receiver<(Timestamp, Vec)>, + mpsc::Receiver<(Timestamp, Vec)>, +) { + let (tx_eq, rx_eq) = mpsc::channel(); + let (tx_ex, rx_ex) = mpsc::channel(); + let bp = Composite::new( + "root", + vec![ + BlueprintNode::Composite(sma_cross()), + Exposure::builder().into(), + SimBroker::builder(0.0001).into(), + Recorder::builder(vec![ScalarKind::F64], Firing::Any, tx_eq).into(), + Recorder::builder(vec![ScalarKind::F64], Firing::Any, tx_ex).into(), + ], + vec![ + Edge { from: 0, to: 1, slot: 0, from_field: 0 }, // composite out -> Exposure + Edge { from: 1, to: 2, slot: 0, from_field: 0 }, // exposure -> broker slot 0 + Edge { from: 2, to: 3, slot: 0, from_field: 0 }, // equity -> sink + Edge { from: 1, to: 4, slot: 0, from_field: 0 }, // exposure -> sink + ], + vec![Role { + name: "src".into(), + targets: vec![ + Target { node: 0, slot: 0 }, // price -> sma_cross role 0 + Target { node: 2, slot: 1 }, // price -> SimBroker price slot + ], + source: Some(ScalarKind::F64), + }], + vec![], // output: the root ends in sinks + ); + (bp, rx_eq, rx_ex) +} +``` + +> The exact `use` paths above are illustrative — the planner resolves the real +> import paths against the crate's actual item visibility (e.g. whether +> `Composite`/`Edge`/`Role`/`Target`/`OutField`/`BlueprintNode` are reached via +> `crate::blueprint::…`, `crate::harness::…`, or a `pub use` re-export). The +> *shape* — one `#[cfg(test)]` module, three `pub(crate)` fns moved verbatim — is +> what this spec fixes. + +### Before → after — the two consuming test modules + +`crates/aura-engine/src/blueprint.rs`, `#[cfg(test)] mod tests`: + +```text +BEFORE: + fn synthetic_prices() -> Vec<(Timestamp, Scalar)> { ... } // :1520 + fn sma_cross() -> Composite { ... } // :1593 + fn composite_sma_cross_harness() -> (...) { ... } // :1614 + (callers: composite_sma_cross_runs_bit_identical_to_hand_wired, etc.) + +AFTER: + use crate::test_fixtures::{synthetic_prices, sma_cross, composite_sma_cross_harness}; + // the three local fn defs deleted; callers unchanged. +``` + +`crates/aura-engine/src/sweep.rs`, `#[cfg(test)] mod tests`: + +```text +BEFORE: + fn synthetic_prices() -> Vec<(Timestamp, Scalar)> { ... } // :256 + fn sma_cross() -> Composite { ... } // :274 ("duplicated from blueprint.rs") + fn composite_sma_cross_harness() -> (...) { ... } // :298 + (callers: run_point, sma_cross_grid) + +AFTER: + use crate::test_fixtures::{synthetic_prices, sma_cross, composite_sma_cross_harness}; + // the three local fn defs (and the "duplicated from" doc-comment) deleted; + // callers unchanged. +``` + +Any `use` import in either test module that was needed *only* by a moved fn +becomes unused and must be removed (the surviving local helpers — +`hand_wired_sma_cross_harness`, `sma_cross_under_root`, `run_point`, +`sma_cross_grid` — keep their own imports). `cargo clippy --workspace +--all-targets -- -D warnings` is the backstop: an unused import fails the lint +gate, so this cannot ship un-cleaned. + +## Components + +- **New:** `aura-engine/src/test_fixtures.rs` — test-only module, three + `pub(crate)` fixture fns. +- **Modified:** `aura-engine/src/lib.rs` — add `#[cfg(test)] mod test_fixtures;`. +- **Modified:** `aura-engine/src/blueprint.rs` — delete three local fixtures, + import from `crate::test_fixtures`, drop now-unused imports. +- **Modified:** `aura-engine/src/sweep.rs` — same, plus delete the stale + "duplicated from blueprint.rs" doc-comments. + +## Data flow + +No runtime data-flow change. The fixtures construct the same `Composite` +blueprints and the same `synthetic_prices` input vector as before; the only +difference is the *definition site*. Every existing test calls the same-named +functions with the same signatures, so call sites are untouched. + +## Error handling + +None introduced. This is a mechanical move of test-only code; there are no new +runtime paths, results, or panics. Compile errors during the move (wrong import +path, visibility) are caught by `cargo build`/`cargo test`; an unused import by +`clippy -D warnings`. + +## Testing strategy + +The dedup is its own correctness witness: there is now **one** definition of +each fixture, so the divergence hazard is eliminated structurally rather than +guarded by a pin-them-equal test (which becomes meaningless once there is a +single definition). Verification is that the **existing** suite still passes +unchanged: + +- `cargo test --workspace` — green, identical results. The load-bearing tests + that exercise these fixtures continue to pass: + - `blueprint.rs::composite_sma_cross_runs_bit_identical_to_hand_wired` + (the composite-vs-hand-wired bit-identical determinism test, C1), + - `sweep.rs::sweep_equals_n_independent_runs` (C11/C12 sweep equivalence). +- `cargo clippy --workspace --all-targets -- -D warnings` — green (no unused + imports left behind). + +No new test is added; adding one would assert a property (two definitions agree) +that the change deletes the premise of. + +## Acceptance criteria + +aura declares no numbered feature-acceptance criterion; the default applies — +the change removes real redundancy without contradicting a design commitment. +Judged against the concrete code above: + +1. **Removes measurable redundancy.** Three verbatim fixtures × two sites → one + shared definition. The silent-divergence hazard #53 names is gone. +2. **Behaviour-preserving.** `#[cfg(test)]`-only; no production code, no runtime + path, no public API touched. `cargo test --workspace` is green with identical + results. +3. **Reintroduces no failure class.** It *strengthens* the integrity of the C1 + determinism and C11/C12 sweep-equivalence fixtures (they can no longer drift + apart between modules). C16 is untouched — a `#[cfg(test)]` module ships in no + artifact. +4. **The intended audience reaches for it.** An engine developer editing the + harness topology now edits one fixture, the natural shared-fixture shape the + crate already uses (`reexport_tests`).