diff --git a/crates/aura-cli/src/main.rs b/crates/aura-cli/src/main.rs index 1a74249..5f316e9 100644 --- a/crates/aura-cli/src/main.rs +++ b/crates/aura-cli/src/main.rs @@ -636,8 +636,8 @@ fn parse_chart_args(rest: &[&str]) -> Result<(String, Option, ChartMode) /// family parsers (`parse_sweep_args` / `parse_walkforward_args`). It holds the /// one home of the real/window grammar — flag-repeat strictness, the empty-symbol /// rejection, and the "window flags require `--real`" rule — so the two siblings -/// agree with each other (the `run` parser inlines the same strictness — its -/// valueless `--macd` flag rules out reusing this accumulator). Each parser owns its other +/// agree with each other (the `run` parser inlines the same strictness rather than +/// sharing this accumulator). Each parser owns its other /// flags (strategy / name / trace); on a `--real`/`--from`/`--to` token it calls /// `accept`, and at the end calls `finish` to validate and build the `DataChoice`. #[derive(Default)] @@ -1875,18 +1875,17 @@ struct RunArgs { trace: Option, } -/// Parse the `run` tail: `[--harness ] [--macd] [--real [--from ] [--to ]] -/// [--trace ]` in any order, each flag at most once. `--harness sma` is the default; -/// `--macd` is a back-compat alias for `--harness macd` and conflicts with `--harness`; -/// `--from`/`--to` are legal only with `--real`. Pure (no I/O, no exit) so the grammar is -/// unit-testable; `main` does the side effects. +/// Parse the `run` tail: `[--harness ] [--real [--from ] [--to ]] +/// [--trace ]` in any order, each flag at most once. `--harness sma` is the default +/// (`--harness macd` / `--harness stage1-r` select the others); `--from`/`--to` are legal +/// only with `--real`. Pure (no I/O, no exit) so the grammar is unit-testable; `main` does +/// the side effects. fn parse_run_args(rest: &[&str]) -> Result { let usage = || { - "usage: aura run [--harness ] [--macd] [--real [--from ] [--to ]] [--trace ]" + "usage: aura run [--harness ] [--real [--from ] [--to ]] [--trace ]" .to_string() }; let mut harness: Option = None; - let mut macd_flag = false; let mut symbol: Option = None; let mut from: Option = None; let mut to: Option = None; @@ -1894,10 +1893,6 @@ fn parse_run_args(rest: &[&str]) -> Result { let mut tail = rest; while let Some((flag, t)) = tail.split_first() { match *flag { - "--macd" if !macd_flag => { - macd_flag = true; - tail = t; - } "--harness" if harness.is_none() => { let (value, t) = t.split_first().ok_or_else(usage)?; harness = Some(match *value { @@ -1934,13 +1929,7 @@ fn parse_run_args(rest: &[&str]) -> Result { _ => return Err(usage()), } } - // --macd is the alias; it conflicts with an explicit --harness. - let harness = match (harness, macd_flag) { - (Some(_), true) => return Err(usage()), - (Some(h), false) => h, - (None, true) => HarnessKind::Macd, - (None, false) => HarnessKind::Sma, - }; + let harness = harness.unwrap_or(HarnessKind::Sma); // --from/--to require --real. if symbol.is_none() && (from.is_some() || to.is_some()) { return Err(usage()); @@ -1970,7 +1959,7 @@ fn run_dispatch(args: RunArgs) -> Result { } const USAGE: &str = - "usage: aura run [--harness ] [--macd] [--real [--from ] [--to ]] [--trace ] | aura chart [--tap ] [--panels] | aura graph | aura sweep [--strategy ] [--real [--from ] [--to ]] [--name |--trace ] | aura mc [--name |--trace ] | aura walkforward [--real [--from ] [--to ]] [--name |--trace ] | aura runs families | aura runs family [rank ]"; + "usage: aura run [--harness ] [--real [--from ] [--to ]] [--trace ] | aura chart [--tap ] [--panels] | aura graph | aura sweep [--strategy ] [--real [--from ] [--to ]] [--name |--trace ] | aura mc [--name |--trace ] | aura walkforward [--real [--from ] [--to ]] [--name |--trace ] | aura runs families | aura runs family [rank ]"; fn main() { // Collect argv and match the whole vector: every accepted form is exhaustive, @@ -2979,14 +2968,14 @@ mod tests { assert_eq!(a.trace.as_deref(), Some("q1")); } - /// Property: `--macd` is a back-compat ALIAS for `--harness macd` (so the historic - /// `run --macd` form survives), it conflicts with an explicit `--harness`, an unknown - /// harness name is rejected, and a window flag (`--from`) without `--real` is rejected - /// — the grammar's four refusal edges. + /// Property: `--harness macd` selects the MACD harness — the sole selector now that the + /// `--macd` back-compat flag is removed, so `--macd` is rejected as an unknown token; an + /// unknown harness name is rejected, and a window flag (`--from`) without `--real` is + /// rejected — the grammar's refusal edges. #[test] - fn parse_run_args_macd_is_an_alias_and_rejects_harness_conflict() { - assert!(matches!(parse_run_args(&["--macd"]).unwrap().harness, HarnessKind::Macd)); - assert!(parse_run_args(&["--macd", "--harness", "sma"]).is_err()); + fn parse_run_args_harness_macd_selects_macd_and_rejects_removed_flag() { + assert!(matches!(parse_run_args(&["--harness", "macd"]).unwrap().harness, HarnessKind::Macd)); + assert!(parse_run_args(&["--macd"]).is_err()); // the removed flag is now an unknown token assert!(parse_run_args(&["--harness", "nope"]).is_err()); assert!(parse_run_args(&["--from", "1"]).is_err()); // --from without --real } @@ -3000,7 +2989,6 @@ mod tests { assert!(parse_run_args(&["--real", "GER40", "--from", "x"]).is_err()); // non-i64 from assert!(parse_run_args(&["--real", "GER40", "--to", "1.5"]).is_err()); // non-i64 to assert!(parse_run_args(&["--harness", "sma", "--harness", "macd"]).is_err()); // repeated --harness - assert!(parse_run_args(&["--macd", "--macd"]).is_err()); // repeated --macd assert!(parse_run_args(&["--real", "GER40", "--trace", "a", "--trace", "b"]).is_err()); // repeated --trace assert!(parse_run_args(&["--harness"]).is_err()); // flag missing its value assert!(parse_run_args(&["--real", "GER40", "--from"]).is_err()); // flag missing its value diff --git a/docs/design/INDEX.md b/docs/design/INDEX.md index 17f1ccc..8e9ef6d 100644 --- a/docs/design/INDEX.md +++ b/docs/design/INDEX.md @@ -1115,7 +1115,7 @@ Recorded streams are sparse and timestamped (a record per fired cycle, tagged **Realization (the web-from-disk visual face, #101).** The C14/C22 web seam shipped (amendment 3b56efb): a recording run persists each drained tap as a columnar (SoA, C7) `ColumnarTrace` to `runs/traces//` (`aura-registry::TraceStore`, beside the -run registry's `runs.jsonl`), reachable via `aura run [--macd] [--real …] +run registry's `runs.jsonl`), reachable via `aura run [--real …] --trace `; `aura chart [--panels]` reads them back, aligns all taps on a synthetic-union timestamp spine via the post-run `join_on_ts` (C3 — not in-graph; C1 — pure, no live external call), and emits a static self-contained uPlot page @@ -1189,7 +1189,7 @@ by key for determinism, C1); a family is its *first producer* — the deliberate step toward the programmable analysis meta-level (C21) **without** rebuilding the orchestration axes (that is its own later cycle). Name resolution is made a **total function** by the write-guard `TraceStore::ensure_name_free`, called once per tracing -command (`run`/`run --macd`/`run --real` → Run; `sweep`/`mc`/`walkforward` → Family) +command (`run`/`run --harness macd`/`run --real` → Run; `sweep`/`mc`/`walkforward` → Family) to refuse cross-kind name reuse — so the one ambiguous on-disk state (a name used by both a run and a family) is unreachable. Every error path exits 2, never panics (C18/C10 refuse-don't-guess). Engine untouched (C9/C14): the whole change is