From 499121e5c8749755b8859ab0f65fceb56929e8dd Mon Sep 17 00:00:00 2001 From: Brummel Date: Wed, 24 Jun 2026 16:21:26 +0200 Subject: [PATCH] fix(stage1-r): record fixed R-defining params in swept member manifests Cycle-0066 close audit found a C18/C10 gap: a stage1-r sweep member's manifest recorded only the floated knobs (fast.length, slow.length) via zip_params, omitting the fixed R-defining params (stop_length, stop_k, bias_scale) that the single run records. A family member must be reproducible from its own manifest (C18), and the constant stop -- which defines 1R -- must be visible so cross-member SQN comparability (C10) is auditable from the family record, not just the swept fast/slow knobs. The sweep run_one now appends the three fixed params, matching the single run; the integration test pins their presence per member. Verified: full workspace suite 521 passed / 0 failed; clippy -D warnings clean. refs #133 --- crates/aura-cli/src/main.rs | 10 +++++++++- crates/aura-cli/tests/cli_run.rs | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/aura-cli/src/main.rs b/crates/aura-cli/src/main.rs index 37a4a7e..0787605 100644 --- a/crates/aura-cli/src/main.rs +++ b/crates/aura-cli/src/main.rs @@ -1140,7 +1140,15 @@ fn stage1_r_sweep_family(_trace: Option<&str>, data: &DataSource) -> SweepFamily let eq_rows: Vec<(Timestamp, Vec)> = rx_eq.try_iter().collect(); let ex_rows: Vec<(Timestamp, Vec)> = rx_ex.try_iter().collect(); let r_rows: Vec<(Timestamp, Vec)> = rx_r.try_iter().collect(); - let named = zip_params(&space, point); + // record the swept knobs PLUS the fixed R-defining params (the stop and + // bias scale), matching the single run: a family member must be + // reproducible from its own manifest (C18), and the constant stop — which + // defines 1R — must be visible so cross-member SQN comparability (C10) is + // auditable from the family record, not just the floated fast/slow knobs. + let mut named = zip_params(&space, point); + named.push(("bias_scale".to_string(), Scalar::f64(0.5))); + named.push(("stop_length".to_string(), Scalar::i64(STAGE1_R_STOP_LENGTH))); + named.push(("stop_k".to_string(), Scalar::f64(STAGE1_R_STOP_K))); let mut manifest = sim_optimal_manifest(named, window, 0, pip); manifest.broker = stage1_r_broker_label(pip); let mut metrics = summarize(&f64_field(&eq_rows, 0), &f64_field(&ex_rows, 0)); diff --git a/crates/aura-cli/tests/cli_run.rs b/crates/aura-cli/tests/cli_run.rs index 78a6a8e..0088f57 100644 --- a/crates/aura-cli/tests/cli_run.rs +++ b/crates/aura-cli/tests/cli_run.rs @@ -1643,6 +1643,13 @@ fn sweep_strategy_stage1_r_ranks_a_family_by_sqn() { for line in &lines { assert!(line.contains("\"r\":{"), "member must carry an r block: {line}"); assert!(line.contains("\"sqn\""), "member r block must carry sqn: {line}"); + // each member records the fixed R-defining params (the stop that defines 1R), + // so it is reproducible from its own manifest (C18) and the constant-stop + // basis of cross-member SQN comparability (C10) is auditable from the record. + assert!( + line.contains("\"stop_length\"") && line.contains("\"stop_k\""), + "member manifest must record the fixed R-defining stop params: {line}" + ); } // rank the family by sqn — highest first. let rank = Command::new(BIN)