refactor(cli): remove the redundant --macd flag, superseded by --harness macd

The --macd flag was a back-compat alias for --harness macd, added in cycle 0065
iter-3 while the uniform `--harness <name>` selector was introduced. With that
selector in place the alias is pure redundancy, so drop it: --harness <name> is
now the sole way to pick a built-in harness.

Removed from parse_run_args: the macd_flag accumulator, its match arm, and the
(harness, macd_flag) conflict resolution -- harness selection collapses to
`harness.unwrap_or(HarnessKind::Sma)`. Both usage strings drop `[--macd]`; the
parse_run_args doc and the parse_real_args note no longer cite the flag.

The MACD harness itself is untouched: run_macd, the macd() composite, and
`--harness macd` all stay. Tests updated -- the alias test becomes a positive
`--harness macd -> Macd` test plus an assertion that `--macd` is now rejected as
an unknown token; the "repeated --macd" edge is dropped (the flag is gone, and
repeated-flag strictness is still covered by --harness/--trace).

INDEX.md: the two realization notes that documented `--macd` as a live run form
updated (`aura run [--real ...]`; `run --harness macd`). The historical
graph-viewer retirement note and the frozen fieldtest capture are left as the
record of their time.

Verified: clippy --all-targets -D warnings clean; full suite 513 passed / 0
failed (assertions rewritten in place, no test count change); live smoke --
`aura run --harness macd` emits a RunReport, `aura run --macd` exits with the
updated usage.
This commit is contained in:
2026-06-24 13:57:15 +02:00
parent 1a6eafa056
commit 0288878ad2
2 changed files with 19 additions and 31 deletions
+17 -29
View File
@@ -636,8 +636,8 @@ fn parse_chart_args(rest: &[&str]) -> Result<(String, Option<String>, 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<String>,
}
/// Parse the `run` tail: `[--harness <name>] [--macd] [--real <SYM> [--from <ms>] [--to <ms>]]
/// [--trace <name>]` 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 <name>] [--real <SYM> [--from <ms>] [--to <ms>]]
/// [--trace <name>]` 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<RunArgs, String> {
let usage = || {
"usage: aura run [--harness <sma|macd|stage1-r>] [--macd] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--trace <name>]"
"usage: aura run [--harness <sma|macd|stage1-r>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--trace <name>]"
.to_string()
};
let mut harness: Option<HarnessKind> = None;
let mut macd_flag = false;
let mut symbol: Option<String> = None;
let mut from: Option<i64> = None;
let mut to: Option<i64> = None;
@@ -1894,10 +1893,6 @@ fn parse_run_args(rest: &[&str]) -> Result<RunArgs, String> {
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<RunArgs, String> {
_ => 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<RunReport, String> {
}
const USAGE: &str =
"usage: aura run [--harness <sma|macd|stage1-r>] [--macd] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--trace <name>] | aura chart <name> [--tap <t>] [--panels] | aura graph | aura sweep [--strategy <sma|momentum>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n>|--trace <n>] | aura mc [--name <n>|--trace <n>] | aura walkforward [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n>|--trace <n>] | aura runs families | aura runs family <id> [rank <metric>]";
"usage: aura run [--harness <sma|macd|stage1-r>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--trace <name>] | aura chart <name> [--tap <t>] [--panels] | aura graph | aura sweep [--strategy <sma|momentum>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n>|--trace <n>] | aura mc [--name <n>|--trace <n>] | aura walkforward [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n>|--trace <n>] | aura runs families | aura runs family <id> [rank <metric>]";
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
+2 -2
View File
@@ -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/<name>/` (`aura-registry::TraceStore`, beside the
run registry's `runs.jsonl`), reachable via `aura run [--macd] [--real <SYM> …]
run registry's `runs.jsonl`), reachable via `aura run [--real <SYM> …]
--trace <name>`; `aura chart <name> [--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