From e12b4a730bec4c64d48a9737017708c0bde633f3 Mon Sep 17 00:00:00 2001 From: claude Date: Mon, 13 Jul 2026 22:59:07 +0200 Subject: [PATCH] =?UTF-8?q?test:=20red=20executable-spec=20for=20#265=20?= =?UTF-8?q?=E2=80=94=20introspect=20--unwired=20states=20knob=20units?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The four silently-misreadable cost/risk knobs (cost_per_trade, slip_vol_mult, vol.length, vol.k) must carry one-line unit/semantics annotations in campaign introspect --unwired — blocking the price-vs-R and length-as-timescale misreadings that produce no error today. refs #265 --- crates/aura-cli/tests/research_docs.rs | 52 ++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/crates/aura-cli/tests/research_docs.rs b/crates/aura-cli/tests/research_docs.rs index 36bdc80..ad5b1e7 100644 --- a/crates/aura-cli/tests/research_docs.rs +++ b/crates/aura-cli/tests/research_docs.rs @@ -667,6 +667,58 @@ fn campaign_introspect_unwired_lists_the_risk_slot_when_explicitly_empty() { ); } +/// #265: the cost and risk slots name their knobs but not their UNITS or +/// SEMANTICS, and the two natural misreadings are silent (wrong by orders of +/// magnitude / change an experiment's meaning, with no error). Property: when +/// `campaign introspect --unwired` lists the open cost and risk slots, each of +/// the four silently-misreadable knobs carries a one-line unit/semantics note +/// that blocks its misreading — `constant.cost_per_trade` is in PRICE units +/// (charged per close as cost/|entry−stop| in R), `vol_slippage.slip_vol_mult` +/// is a MULTIPLIER on the per-cycle vol estimate (charged in R likewise), +/// `vol.length` SMOOTHS the estimator and does NOT set the stop's timescale, +/// and `vol.k` SCALES the stop distance. Autonomous: a bare `{}` envelope +/// (both slots open) written inline, no project, hostless. Wording stays free +/// (matched case-insensitively on load-bearing fragments, not whole lines); it +/// fails today because the annotations are absent, not on scaffolding. +#[test] +fn campaign_introspect_unwired_annotates_cost_and_risk_knob_units() { + let dir = temp_cwd("campaign-introspect-unwired-knob-units"); + write_doc(&dir, "bare.json", "{}"); + let (out, code) = run_code_in(&dir, &["campaign", "introspect", "--unwired", "bare.json"]); + assert_eq!(code, Some(0), "stdout/stderr: {out}"); + let low = out.to_lowercase(); + + // constant.cost_per_trade — price units, not R (the order-of-magnitude trap). + assert!(low.contains("cost_per_trade"), "the cost knob must still be named: {out}"); + assert!( + low.contains("price units"), + "cost_per_trade must be annotated as a PRICE-unit numerator (its misreading is a cost in R): {out}" + ); + + // vol_slippage.slip_vol_mult — a multiplier on the per-cycle vol estimate. + assert!(low.contains("slip_vol_mult"), "the vol-slippage knob must still be named: {out}"); + assert!( + low.contains("multiplier on the per-cycle vol"), + "slip_vol_mult must be annotated as a MULTIPLIER on the per-cycle vol estimate: {out}" + ); + + // vol.length — smooths the estimator; it does NOT set the stop's timescale. + assert!( + low.contains("smooths"), + "vol.length must be annotated as SMOOTHING the per-cycle vol estimator: {out}" + ); + assert!( + low.contains("does not set the stop's timescale"), + "vol.length must state it does NOT set the stop's timescale (its exact misreading): {out}" + ); + + // vol.k — scales the stop distance (the risk-unit lever). + assert!( + low.contains("scales the stop distance"), + "vol.k must be annotated as SCALING the stop distance (the risk-unit lever): {out}" + ); +} + #[test] fn campaign_introspect_unwired_reports_the_spec_example_slots() { let dir = temp_cwd("campaign-introspect-unwired");