From 3d3baaeb246c44845f1f2d7999156cdafc7631d6 Mon Sep 17 00:00:00 2001 From: Brummel Date: Wed, 24 Jun 2026 14:45:27 +0200 Subject: [PATCH] refactor(stage1-r): dedicated broker label + intern col-port names (no per-build leak) Two cosmetic smells the cycle-0065 close audit flagged (#132), neither a correctness issue: 1. Broker label. run_stage1_r reused sim_optimal_manifest, recording broker: "sim-optimal(pip_size=...)" for a harness that also runs a RiskExecutor branch. It now overrides the label to "sim-optimal+risk-executor(pip_size=...)" so the dual-tap harness reads honestly. A new assertion in run_stage1_r_synthetic_folds_an_r_block pins it. 2. col[i] leak. stage1_r_blueprint did format!("col[{i}]").leak() per PositionManagement field (14 strings) to satisfy the &'static str port-name API -- harmless for a CLI one-shot, but a leak-per-build smell once the harness is reused in a sweep / Monte-Carlo loop (the #133 direction). Replaced with a process-wide LazyLock> (COL_PORTS), interned once: any number of builds now reuse the same 14 strings. (#132 deferred this to #133, but the intern is robust to any reuse pattern, so it lands here cleanly.) Behaviour-preserving (the port names and the recorded R-record are unchanged); the broker label is the only observable change, and it is pinned. Verified: clippy --all-targets -D warnings clean; full suite 514 passed / 0 failed; live `aura run --harness stage1-r` reports "broker":"sim-optimal+risk-executor(pip_size=0.0001)". closes #132 --- crates/aura-cli/src/main.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/crates/aura-cli/src/main.rs b/crates/aura-cli/src/main.rs index f62d5e9..b21390f 100644 --- a/crates/aura-cli/src/main.rs +++ b/crates/aura-cli/src/main.rs @@ -31,6 +31,7 @@ use aura_std::{ Bias, Ema, LinComb, LongOnly, Recorder, SimBroker, Sma, Sub, PM_FIELD_NAMES, PM_RECORD_KINDS, }; use std::sync::mpsc::{self, Receiver}; +use std::sync::LazyLock; use std::collections::HashSet; /// The pip size the built-in *synthetic* harnesses run at: a 5-decimal FX major @@ -1719,6 +1720,13 @@ fn stage1_r_prices() -> Vec<(Timestamp, Scalar)> { .collect() } +/// Interned `col[i]` recorder-port names, built once. The `GraphBuilder::input` API +/// wants `&'static str`; interning here (instead of `format!(...).leak()` per field) +/// means reusing the stage1-r harness in a sweep / Monte-Carlo loop reuses these +/// strings rather than leaking 14 fresh ones per build (#132). +static COL_PORTS: LazyLock> = + LazyLock::new(|| (0..PM_FIELD_NAMES.len()).map(|i| format!("col[{i}]")).collect()); + /// The Stage-1 R harness: the SMA-cross → `Bias` signal fanned into BOTH a `SimBroker` /// (pip equity, the existing pip yardstick) AND the `risk_executor` (the dense R-record, /// the new R yardstick), so one run scores the same signal in pips and in R. Four taps: @@ -1770,8 +1778,7 @@ fn stage1_r_blueprint( g.connect(broker.output("equity"), eq.input("col[0]")); // tap the dense R-record (all PM fields) for summarize_r. for (i, field) in PM_FIELD_NAMES.iter().enumerate() { - let col: &'static str = format!("col[{i}]").leak(); - g.connect(exec.output(field), rrec.input(col)); + g.connect(exec.output(field), rrec.input(COL_PORTS[i].as_str())); } // r_equity sum + tap. g.connect(exec.output("cum_realized_r"), r_equity.input("term[0]")); @@ -1820,7 +1827,7 @@ fn run_stage1_r(data: RunData, trace: Option<&str>) -> RunReport { let r_rows: Vec<(Timestamp, Vec)> = rx_r.try_iter().collect(); let req_rows: Vec<(Timestamp, Vec)> = rx_req.try_iter().collect(); - let manifest = sim_optimal_manifest( + let mut manifest = sim_optimal_manifest( vec![ ("sma_fast".to_string(), Scalar::i64(2)), ("sma_slow".to_string(), Scalar::i64(4)), @@ -1832,6 +1839,9 @@ fn run_stage1_r(data: RunData, trace: Option<&str>) -> RunReport { 0, pip_size, ); + // #132: the dual-tap harness runs a RiskExecutor branch alongside the SimBroker, so + // the plain "sim-optimal" label would under-report it — record both honestly. + manifest.broker = format!("sim-optimal+risk-executor(pip_size={pip_size})"); if let Some(name) = trace { persist_traces_r(name, &manifest, &eq_rows, &ex_rows, &req_rows); } @@ -2943,6 +2953,13 @@ mod tests { assert!(r.n_trades >= 1, "expected >= 1 trade, got {}", r.n_trades); assert!(r.sqn.is_finite(), "SQN must be finite, got {}", r.sqn); assert!(r.expectancy_r.is_finite(), "E[R] must be finite, got {}", r.expectancy_r); + // #132: the dual-tap harness runs a RiskExecutor branch alongside the + // SimBroker, so its manifest carries a dedicated broker label. + assert!( + report.manifest.broker.contains("risk-executor"), + "stage1-r manifest should carry a dedicated broker label, got: {}", + report.manifest.broker + ); } /// Property: a bare `aura run` parses to the default harness/data — `--harness sma`