Files
Aura/docs/plans/0014-tidy-dedup-reexport.md
T
Brummel 73938a4e4a plan: 0014 tidy — scalar re-export (#29) + Recorder-fixture dedup (#14)
Post-cycle tidy iteration (audit fix-path: planner + implement). Covers two
pure-tidy issues:

- #29: aura-engine re-exports the core scalar vocabulary (Firing/Scalar/
  ScalarKind/Timestamp) so a Blueprint builder needs one import surface.
- #14: delete the two near-identical #[cfg(test)] Recorder fixtures in
  report.rs/harness.rs in favour of the shipped aura-std::Recorder (identical
  constructor + try_iter drain, so call sites stay byte-identical).

#27 (cross-crate sma_cross dedup) was the third tidy candidate but is excluded:
after the bit-identical-test protection (hand_wired pole must stay independent)
and the aura-run-out-of-scope rule, its only remaining content is deduping a
concrete sma_cross composite across aura-cli (non-test) and aura-engine
(#[cfg(test)]). No C9-clean home exists for that (a feature-gated pub fn would
make a concrete trading signal an engine pub API, which C9 forbids). Narrowed
per orchestrator decision; refs #27.
2026-06-05 23:21:41 +02:00

8.3 KiB

Tidy 0014 — scalar re-export + Recorder-fixture dedup — Implementation Plan

Parent spec: none — this is a post-cycle tidy iteration dispatched per the audit skill's "fix path: planner + implement for a tidy iteration". The source of truth is two Gitea tidy issues (#29, #14) plus the orchestrator's scope constraints. (#27 was the third candidate but is out of this plan: its only remaining content after the bit-identical-test protection and the aura run out-of-scope rule is a cross-crate dedup of a concrete sma_cross composite, which has no C9-clean home — orchestrator decided to narrow/close #27 with that rationale rather than bend C9 in a tidy.)

For agentic workers: REQUIRED SUB-SKILL: use the implement skill to run this plan. Steps use - [ ] checkboxes for tracking.

Goal: Close #29 (aura-engine re-exports the core scalar vocabulary) and #14 (remove the two near-identical #[cfg(test)] Recorder fixtures in aura-engine, using the shipped aura-std::Recorder).

Architecture: Two independent, behaviour-preserving tidies. (1) Add one pub use aura_core::{...} line to aura-engine's crate root so a Blueprint builder needs one import surface, not two. (2) Delete the private f64/all-kind #[cfg(test)] Recorder structs in report.rs and harness.rs and import the shipped aura_std::Recorder instead — its constructor signature, schema, and try_iter() drain are call-for-call identical to both fixtures, so no call site changes; only the struct/impl deletion and one import line per file.

Tech Stack: crates/aura-engine/src/{lib,report,harness}.rs; the shipped aura-std::Recorder (already a [dev-dependencies] of aura-engine).


Files this plan creates or modifies

  • Modify: crates/aura-engine/src/lib.rs:38-40 — add pub use aura_core::{Firing, Scalar, ScalarKind, Timestamp}; after the existing re-exports.
  • Test: crates/aura-engine/src/lib.rs (new #[cfg(test)] module) — assert the four scalar symbols resolve at the aura-engine crate root.
  • Modify: crates/aura-engine/src/report.rs:203 — add Recorder to the existing use aura_std::{...}.
  • Modify: crates/aura-engine/src/report.rs:217-255 — delete the private #[cfg(test)] struct Recorder + its impl Recorder::new + impl Node.
  • Modify: crates/aura-engine/src/harness.rs:340 — add Recorder to the existing use aura_std::{...}.
  • Modify: crates/aura-engine/src/harness.rs:496-559 — delete the private #[cfg(test)] struct Recorder + its impl Recorder::new + impl Node (leave the separate TapForward fixture at L564-585 untouched).

Task 1: #29 — aura-engine re-exports the core scalar vocabulary

Files:

  • Modify: crates/aura-engine/src/lib.rs:38-40

  • Test: crates/aura-engine/src/lib.rs (new #[cfg(test)] module at end of file)

  • Step 1: Add the re-export line

In crates/aura-engine/src/lib.rs, the current re-exports are:

pub use blueprint::{Blueprint, BlueprintNode, CompileError, Composite, OutPort};
pub use harness::{BootstrapError, Edge, Harness, SourceSpec, Target};
pub use report::{f64_field, summarize, RunManifest, RunMetrics, RunReport};

Add one line immediately after pub use report::{...};:

// #29: re-export the core scalar vocabulary a Blueprint builder needs
// (SourceSpec.kind is a ScalarKind; sources/Recorder columns are Scalar /
// Firing / Timestamp) so a graph builder has one import surface, not two.
pub use aura_core::{Firing, Scalar, ScalarKind, Timestamp};
  • Step 2: Add a test that the four symbols resolve at the crate root

Append to crates/aura-engine/src/lib.rs (if the file already ends with a #[cfg(test)] module, add this as a sibling module — do not merge):

#[cfg(test)]
mod reexport_tests {
    // #29: the core scalar vocabulary a Blueprint builder needs is reachable
    // from aura-engine alone (crate::X == external aura_engine::X), so a
    // downstream author does not add a second aura-core import for ScalarKind.
    #[test]
    fn core_scalar_vocabulary_is_reexported_from_crate_root() {
        use crate::{Firing, Scalar, ScalarKind, Timestamp};
        let _k: ScalarKind = ScalarKind::F64;
        let _f: Firing = Firing::Any;
        let _s: Scalar = Scalar::F64(0.0);
        let _t: Timestamp = Timestamp(0);
    }
}
  • Step 3: Build + test + lint

Run: cargo build -p aura-engine && cargo test -p aura-engine reexport_tests && cargo clippy -p aura-engine --all-targets -- -D warnings Expected: build OK; core_scalar_vocabulary_is_reexported_from_crate_root PASS (1 test run, not 0); clippy clean (no unused_imports, no ambiguous_glob_reexports).


Task 2: #14 (part 1) — report.rs uses the shipped Recorder

Files:

  • Modify: crates/aura-engine/src/report.rs:203 (import) and :217-255 (delete fixture)

The private fixture's constructor is Recorder::new(&[ScalarKind], Firing, mpsc::Sender<(Timestamp, Vec<Scalar>)>), identical to aura_std::Recorder::new; both schemas are one InputSpec per kind with empty output; both drain via rx.try_iter(). The two call sites (report.rs:275-276, read back at :308-309) construct Recorder::new(&[ScalarKind::F64], Firing::Any, tx_*) and stay byte-identical — they resolve to aura_std::Recorder once the private struct is gone and the import is added.

  • Step 1: Add Recorder to the aura-std import

In crates/aura-engine/src/report.rs, the test-module import is:

use aura_std::{Exposure, SimBroker, Sma, Sub};

Replace it with (alphabetical, Recorder inserted):

use aura_std::{Exposure, Recorder, SimBroker, Sma, Sub};
  • Step 2: Delete the private Recorder fixture

In crates/aura-engine/src/report.rs, delete the entire private fixture block spanning the #[cfg(test)] struct Recorder { ... } declaration, its impl Recorder { fn new(...) -> Self { ... } }, and its impl Node for Recorder { ... } (the contiguous region at lines ~217-255, ending just before the next test-support item). Delete nothing else — leave every Recorder::new(...) call site and every other helper intact.

  • Step 3: Build + test + lint

Run: cargo test -p aura-engine --lib report && cargo clippy -p aura-engine --all-targets -- -D warnings Expected: report_is_deterministic_end_to_end (report.rs:329) PASS (≥1 test run, not 0); no unused_imports for Recorder; no "cannot find type Recorder" error; clippy clean.


Task 3: #14 (part 2) — harness.rs uses the shipped Recorder

Files:

  • Modify: crates/aura-engine/src/harness.rs:340 (import) and :496-559 (delete fixture)

The private fixture here is the all-four-kinds variant (matches on I64/F64/Bool/Timestamp), behaviourally identical to aura_std::Recorder. Its ~30 call sites (enumerated in recon: L594…L1768, all Recorder::new(&[<kinds>], <Firing>, <tx>), all drained via rx.try_iter()) stay byte-identical. The separate TapForward fixture (L564-585) is NOT a Recorder and is left untouched.

  • Step 1: Add Recorder to the aura-std import

In crates/aura-engine/src/harness.rs, the test-module import is:

use aura_std::{Exposure, Sma, SimBroker, Sub};

Replace it with (Recorder inserted):

use aura_std::{Exposure, Recorder, Sma, SimBroker, Sub};
  • Step 2: Delete the private Recorder fixture

In crates/aura-engine/src/harness.rs, delete the entire private fixture block spanning the #[cfg(test)] struct Recorder { ... } declaration, its impl Recorder { fn new(...) -> Self { ... } }, and its impl Node for Recorder { ... } (the contiguous region at lines ~496-559). Do NOT touch the TapForward struct/impl that follows at ~564-585, and delete no call site.

  • Step 3: Build + full workspace test + lint

Run: cargo build --workspace && cargo test --workspace && cargo clippy --workspace --all-targets -- -D warnings Expected: build OK; all tests PASS — in particular composite_sma_cross_runs_bit_identical_to_hand_wired, run_sample_is_deterministic_and_non_trivial, swapped_sma_inputs_render_differently, the aura-cli golden snapshots, the aura-std SMA disambiguation test, and every harness.rs recording test (e.g. recorder_records_mixed_scalar_kinds, milestone_end_to_end_mixed_dag_records_every_stream_deterministically, signal_quality_loop_is_deterministic) stay green; no unused_imports; clippy clean.