audit: cycle 0101 tidy (drift-clean after one ledger alignment)

Architect review of 8814e295..HEAD. What holds: the cosmetic-only claim is
verified (every -/+ pair in the code diff is a string literal; no exit(),
channel, or control-flow byte moved; the C14 usage=2/runtime=1 partition
preserved at every touched site); grep gates exact (zero lowercase usage:
literals, 11 'Usage: aura' source lines = 10 edited + the pre-conforming
run_args_from); fieldtests corpus and refusal diagnostics byte-identical.
The recorded spec deviation (3 additive house-style pins) strengthens
coverage over a real pin gap and is decision-logged on the issue.

Regression: cargo build rc=0, cargo test --workspace rc=0 (cli_run 133
passed / 0 failed), clippy -D warnings rc=0, doc build rc=0. No baselines
exist to move, so nothing to ratify.

Drift resolved in this commit: the C14 ledger note still described the
casing normalization as deferred after #179 landed - rewritten to record
the landed house style (usage lines 'Usage: aura <verb> ...', refusal
diagnostics deliberately unprefixed).

Ephemeral cycle artifacts removed per convention: spec 0101, plan 0101.

refs #179
This commit is contained in:
2026-07-02 12:59:36 +02:00
parent 9402afe958
commit d7c935dd77
3 changed files with 3 additions and 434 deletions
+3 -1
View File
@@ -1087,7 +1087,9 @@ needed environment / recorded state is missing, or bad piped stdin data. The fou
dual-grammar subcommands (run/sweep/walkforward/mc) keep both grammars under one
token via an optional `[blueprint]` positional + a post-parse `is_file()`
dispatch; the execution layer is unchanged (arg-plumbing via thin `*_from`
adapters). Error-message casing normalization was deferred (#179); the
adapters). Error-message casing is normalized to the clap house style —
every hand-rolled usage line reads `Usage: aura <verb> …` (#179, cycle 0101);
refusal diagnostics stay unprefixed (diagnostics are not usage lines). The
machine-first help surface (JSON/manifest help, stdin op-scripts) stays on the
#157/C21 track, not this cycle (settled as human/GNU convention compliance).
@@ -1,223 +0,0 @@
# Normalize CLI usage-message casing — Implementation Plan
> **Parent spec:** `docs/specs/0101-normalize-cli-usage-casing.md`
>
> **For agentic workers:** REQUIRED SUB-SKILL: use the
> `implement` skill to run this plan. Steps use `- [ ]`
> checkboxes for tracking.
**Goal:** Normalize every hand-rolled CLI usage line to the single house
style `Usage: aura <verb> …` (10 literal edits) and flip the one
casing-sensitive test pin in lockstep — cosmetic only, no behaviour
change (issue #179).
**Architecture:** All edits are byte-substitutions inside existing
string literals on existing exit-2 usage paths; emission channels
(stderr via the `aura: ` convention), exit codes, and control flow stay
byte-identical. The lockstep unit is indivisible: the mc built-in
literal (site #6) and the `cli_run.rs` pin must move together or the
suite goes red, so this plan is one task.
**Tech Stack:** `crates/aura-cli` (clap v4 derive CLI), Rust string
literals, `cargo test` integration suite `cli_run.rs`.
---
**Files this plan creates or modifies:**
- Modify: `crates/aura-cli/src/graph_construct.rs:191` — site #1 casing flip
- Modify: `crates/aura-cli/src/main.rs:3991,4187,4272,4288,4346,4386,4424,4465,4503` — sites #2#10
- Test: `crates/aura-cli/tests/cli_run.rs:1409` — the single casing-sensitive pin flips lowercase `"usage"``"Usage"`
**Off-limits (do not touch):** every other string in `crates/aura-cli`
(refusal diagnostics, the already-conforming `run_args_from` literal at
`main.rs:4012`), all other test bytes, and the `fieldtests/` corpus
(its old exact-equality usage pins are out-of-workspace by design and
stay byte-identical).
---
### Task 1: House-style normalization + lockstep pin flip
**Files:**
- Modify: `crates/aura-cli/src/graph_construct.rs:191`
- Modify: `crates/aura-cli/src/main.rs:3991,4187,4272,4288,4346,4386,4424,4465,4503`
- Test: `crates/aura-cli/tests/cli_run.rs:1409`
Each edit below is exact: `old` is the complete current line (verified
unique in its file), `new` is the complete replacement line. Only the
shown bytes change. Note sites #7 and #9 contain a Unicode ellipsis
(`…`) inside `[--axis …]` — preserve it verbatim.
- [ ] **Step 1: Site #1 — `graph_construct.rs:191` (`introspect_cmd`)**
old:
```rust
"aura: usage: aura graph introspect --vocabulary | --node <T> | --unwired | --content-id"
```
new:
```rust
"aura: Usage: aura graph introspect --vocabulary | --node <T> | --unwired | --content-id"
```
- [ ] **Step 2: Site #2 — `main.rs:3991` (`run_data_from`, let-binding)**
old:
```rust
let usage = "usage: aura run <blueprint.json> [--params <json-cell-array>] [--seed <n>] [--real <SYMBOL> [--from <ms>] [--to <ms>]]";
```
new:
```rust
let usage = "Usage: aura run <blueprint.json> [--params <json-cell-array>] [--seed <n>] [--real <SYMBOL> [--from <ms>] [--to <ms>]]";
```
- [ ] **Step 3: Site #3 — `main.rs:4187` (`dispatch_run`, inline eprintln, verbatim twin of #2 with baked `aura: `)**
old:
```rust
eprintln!("aura: usage: aura run <blueprint.json> [--params <json-cell-array>] [--seed <n>] [--real <SYMBOL> [--from <ms>] [--to <ms>]]");
```
new:
```rust
eprintln!("aura: Usage: aura run <blueprint.json> [--params <json-cell-array>] [--seed <n>] [--real <SYMBOL> [--from <ms>] [--to <ms>]]");
```
- [ ] **Step 4: Site #4 — `main.rs:4272` (`dispatch_runs`)**
old:
```rust
eprintln!("aura: usage: aura runs family <id> [rank <metric>]");
```
new:
```rust
eprintln!("aura: Usage: aura runs family <id> [rank <metric>]");
```
- [ ] **Step 5: Site #5 — `main.rs:4465` (`dispatch_mc`, blueprint branch; gains the program name)**
old:
```rust
let usage = "usage: mc <blueprint.json> --seeds <n> [--name <n>]";
```
new:
```rust
let usage = "Usage: aura mc <blueprint.json> --seeds <n> [--name <n>]";
```
- [ ] **Step 6: Site #6 — `main.rs:4503` (`dispatch_mc`, built-in branch; BOTH ` | `-separated alternatives gain the program name)**
old:
```rust
let usage = || "usage: mc [--name <n>|--trace <n>] | mc --strategy r-sma [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--fast <csv>] [--slow <csv>] [--stop-length <csv>] [--stop-k <csv>] [--block-len <n>] [--resamples <n>] [--seed <n>]".to_string();
```
new:
```rust
let usage = || "Usage: aura mc [--name <n>|--trace <n>] | aura mc --strategy r-sma [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--fast <csv>] [--slow <csv>] [--stop-length <csv>] [--stop-k <csv>] [--block-len <n>] [--resamples <n>] [--seed <n>]".to_string();
```
- [ ] **Step 7: Site #7 — `main.rs:4288` (`dispatch_sweep`, blueprint branch; bare → prefixed; keep the `…` byte)**
old:
```rust
let usage = || "sweep <blueprint.json> --axis <name>=<csv> [--axis …] [--name <n> | --trace <n>] [--real <SYM> [--from <ms>] [--to <ms>]]".to_string();
```
new:
```rust
let usage = || "Usage: aura sweep <blueprint.json> --axis <name>=<csv> [--axis …] [--name <n> | --trace <n>] [--real <SYM> [--from <ms>] [--to <ms>]]".to_string();
```
- [ ] **Step 8: Site #8 — `main.rs:4346` (`dispatch_sweep`, built-in branch; bare → prefixed)**
old:
```rust
let usage = || "sweep [--strategy <sma|momentum|r-sma|r-breakout|r-meanrev>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n> | --trace <n>] [--fast <csv>] [--slow <csv>] [--stop-length <csv>] [--stop-k <csv>] [--channel <csv>] [--window <csv>] [--band-k <csv>]".to_string();
```
new:
```rust
let usage = || "Usage: aura sweep [--strategy <sma|momentum|r-sma|r-breakout|r-meanrev>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n> | --trace <n>] [--fast <csv>] [--slow <csv>] [--stop-length <csv>] [--stop-k <csv>] [--channel <csv>] [--window <csv>] [--band-k <csv>]".to_string();
```
- [ ] **Step 9: Site #9 — `main.rs:4386` (`dispatch_walkforward`, blueprint branch; bare → prefixed; keep the `…` byte)**
old:
```rust
let usage = || "walkforward <blueprint.json> --axis <name>=<csv> [--axis …] [--select <argmax|plateau:mean|plateau:worst>] [--name <n>]".to_string();
```
new:
```rust
let usage = || "Usage: aura walkforward <blueprint.json> --axis <name>=<csv> [--axis …] [--select <argmax|plateau:mean|plateau:worst>] [--name <n>]".to_string();
```
- [ ] **Step 10: Site #10 — `main.rs:4424` (`dispatch_walkforward`, built-in branch; bare → prefixed)**
old:
```rust
let usage = || "walkforward [--strategy <sma|momentum|r-sma|r-breakout|r-meanrev>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n> | --trace <n>] [--fast <csv>] [--slow <csv>] [--stop-length <csv>] [--stop-k <csv>] [--select <argmax|plateau:mean|plateau:worst>]".to_string();
```
new:
```rust
let usage = || "Usage: aura walkforward [--strategy <sma|momentum|r-sma|r-breakout|r-meanrev>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n> | --trace <n>] [--fast <csv>] [--slow <csv>] [--stop-length <csv>] [--stop-k <csv>] [--select <argmax|plateau:mean|plateau:worst>]".to_string();
```
- [ ] **Step 11: Lockstep pin flip — `cli_run.rs:1409` (test `mc_rejects_real_flag_with_usage_exit_2`)**
Only the predicate substring flips; the panic-message argument keeps its
lowercase "usage" verbatim.
old:
```rust
assert!(stderr.contains("usage"), "mc --real stderr must carry usage: {stderr:?}");
```
new:
```rust
assert!(stderr.contains("Usage"), "mc --real stderr must carry usage: {stderr:?}");
```
- [ ] **Step 12: Build gate**
Run: `cargo build --workspace`
Expected: clean compile, 0 errors, 0 warnings introduced.
- [ ] **Step 13: Targeted pin test**
Run: `cargo test -p aura-cli --test cli_run mc_rejects_real_flag_with_usage_exit_2`
Expected: `1 passed; 0 failed` (exactly one test matches the filter).
- [ ] **Step 14: Full-suite gate**
Run: `cargo test --workspace`
Expected: green, 0 failures across all targets. Any failure other than
a test this plan did not touch going red means an edit strayed outside
the normative table — fix the edit, never a pin.
- [ ] **Step 15: Lint gate**
Run: `cargo clippy --workspace --all-targets -- -D warnings`
Expected: clean, 0 warnings.
- [ ] **Step 16: Literal grep gates**
Run: `grep -rn '"usage:' crates/aura-cli/src/`
Expected: no output (exit 1 — zero hits).
Run: `grep -rn 'aura: usage:' crates/aura-cli/src/`
Expected: no output (exit 1 — zero hits).
Run: `grep -rn 'Usage: aura' crates/aura-cli/src/ | wc -l`
Expected: `11` (the 10 edited sites + the untouched conforming
`run_args_from` literal at `main.rs:4012`).
- [ ] **Step 17: Diff-shape gate**
Run: `git diff --stat`
Expected: exactly 3 files changed — `crates/aura-cli/src/main.rs`,
`crates/aura-cli/src/graph_construct.rs`,
`crates/aura-cli/tests/cli_run.rs` (plus this plan/spec under `docs/`
if listed); no `fieldtests/` path, no other test file.
- [ ] **Step 18: Smoke (worked example from the spec)**
Run: `cargo run -q -p aura-cli -- sweep --strategy bogus; echo "exit=$?"`
Expected stderr line:
`aura: Usage: aura sweep [--strategy <sma|momentum|r-sma|r-breakout|r-meanrev>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n> | --trace <n>] [--fast <csv>] [--slow <csv>] [--stop-length <csv>] [--stop-k <csv>] [--channel <csv>] [--window <csv>] [--band-k <csv>]`
Expected exit code line: `exit=2`.
@@ -1,210 +0,0 @@
# Normalize CLI usage-message casing — Design Spec
**Date:** 2026-07-02
**Status:** Draft — awaiting sign-off (grounding-check gate; /boss auto-sign)
**Authors:** orchestrator + Claude
## Goal
Erase the three-way inconsistency in the aura CLI's hand-rolled usage
messages (issue #179). After the clap adoption (#175), the binary speaks
three styles at once: clap's own parse errors and one hand-rolled site say
`Usage:` (capital), six hand-rolled sites say `usage:` (lowercase), and
four hand-rolled closures carry no prefix word at all. This cycle
normalizes every hand-rolled usage line to the single house style clap
already speaks — **cosmetic only, no behaviour change**: exit codes,
emission channels (stderr), and control flow are byte-for-byte preserved;
only the usage-string literals and their casing-sensitive test pins move,
in lockstep.
Decision log (house-style shape, bare-closure inclusion, refusal
exclusion, no de-dup refactor): issue #179, comment "Design
reconciliation (specify)".
## Architecture
### The house style (normative)
One rule: **every hand-rolled usage line reads `Usage: aura <verb> …`**
capital `Usage:` prefix and the program name included in the grammar,
exactly the shape of the two already-conforming producers:
- clap itself (derive API, `#[command(name = "aura")]`) renders
`Usage: aura <verb> [OPTIONS]` on parse errors and `--help`;
- the one already-capital hand-rolled site, the built-in `run` branch
(`run_args_from`, `main.rs:4012`): `"Usage: aura run [--harness …] …"`.
The emission convention around the literal is untouched: hand-rolled
sites keep printing through the existing `eprintln!("aura: {…}")` /
baked-in `aura: ` prefix, so the final stderr line reads
`aura: Usage: aura <verb> …` — which is already today's output shape of
the conforming `run_args_from` path. Exit codes keep the #175 partition
(usage = 2, runtime = 1) at every touched site.
### Scope boundary
**In scope (10 literal edits + 1 test-pin edit):** the 6 lowercase
`usage:` literals, the 4 bare usage closures, and the single
casing-sensitive test pin.
**Out of scope (bytes preserved verbatim):**
- The already-conforming site `run_args_from` (`main.rs:4012`) and all
clap-generated output.
- Every aura-specific refusal/diagnostic in the dispatch area — e.g.
`"no recorded geometry for symbol …"`, `"walkforward <blueprint.json>
requires >= 1 --axis to re-fit per window"`, the six `generalize`
refusals, `"cost flags require an R-evaluator harness …"`,
`"--harness is not valid with a blueprint file"`, `"--list-axes lists
axes and takes no other flags"`, `"run/mc requires a closed blueprint
…"`. A refusal is a diagnostic, not a usage line; clap itself keeps
the two apart (`error: …` vs the `Usage:` block).
- The duplicated run-blueprint usage literal (defined in `run_data_from`
at `main.rs:3991`, verbatim inline copy in `dispatch_run` at
`main.rs:4187`): both copies are normalized identically, but no shared
constant is extracted — a de-dup refactor exceeds the cosmetic
contract.
- Historical fieldtest corpus text quoting an old usage line
(`fieldtests/milestone-cost-model-graph/FINDINGS.md`) — the corpus is
a tracked record, never retro-edited.
- Rustdoc/comment prose saying "usage error" (no colon, not a message).
## Concrete code shapes
### Worked user-facing example (the acceptance evidence)
Before (bare closure, built-in sweep):
```console
$ aura sweep --strategy bogus
aura: sweep [--strategy <sma|momentum|r-sma|r-breakout|r-meanrev>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n> | --trace <n>] [--fast <csv>] [--slow <csv>] [--stop-length <csv>] [--stop-k <csv>] [--channel <csv>] [--window <csv>] [--band-k <csv>]
$ echo $?
2
```
After (house style; exit code unchanged):
```console
$ aura sweep --strategy bogus
aura: Usage: aura sweep [--strategy <sma|momentum|r-sma|r-breakout|r-meanrev>] [--real <SYMBOL> [--from <ms>] [--to <ms>]] [--name <n> | --trace <n>] [--fast <csv>] [--slow <csv>] [--stop-length <csv>] [--stop-k <csv>] [--channel <csv>] [--window <csv>] [--band-k <csv>]
$ echo $?
2
```
And a lowercase site (mc, loaded-blueprint branch):
```console
# before
aura: usage: mc <blueprint.json> --seeds <n> [--name <n>]
# after
aura: Usage: aura mc <blueprint.json> --seeds <n> [--name <n>]
```
### Normative literal edits (before → after, exact bytes)
All in `crates/aura-cli` sources. Only the leading bytes of each literal
change; the grammar tails (`…` below) are preserved verbatim from the
current tree.
| # | Site | Before (leading bytes) | After (leading bytes) |
|---|------|------------------------|-----------------------|
| 1 | `graph_construct.rs:191` (`introspect_cmd`) | `"aura: usage: aura graph introspect …"` | `"aura: Usage: aura graph introspect …"` |
| 2 | `main.rs:3991` (`run_data_from`) | `"usage: aura run <blueprint.json> …"` | `"Usage: aura run <blueprint.json> …"` |
| 3 | `main.rs:4187` (`dispatch_run`, inline copy of #2) | `"aura: usage: aura run <blueprint.json> …"` | `"aura: Usage: aura run <blueprint.json> …"` |
| 4 | `main.rs:4272` (`dispatch_runs`) | `"aura: usage: aura runs family <id> [rank <metric>]"` | `"aura: Usage: aura runs family <id> [rank <metric>]"` |
| 5 | `main.rs:4465` (`dispatch_mc`, blueprint) | `"usage: mc <blueprint.json> …"` | `"Usage: aura mc <blueprint.json> …"` |
| 6 | `main.rs:4503` (`dispatch_mc`, built-in) | `"usage: mc [--name <n>\|--trace <n>] \| mc --strategy r-sma …"` | `"Usage: aura mc [--name <n>\|--trace <n>] \| aura mc --strategy r-sma …"` |
| 7 | `main.rs:4288` (`dispatch_sweep`, blueprint) | `"sweep <blueprint.json> --axis …"` | `"Usage: aura sweep <blueprint.json> --axis …"` |
| 8 | `main.rs:4346` (`dispatch_sweep`, built-in) | `"sweep [--strategy …"` | `"Usage: aura sweep [--strategy …"` |
| 9 | `main.rs:4386` (`dispatch_walkforward`, blueprint) | `"walkforward <blueprint.json> --axis …"` | `"Usage: aura walkforward <blueprint.json> --axis …"` |
| 10 | `main.rs:4424` (`dispatch_walkforward`, built-in) | `"walkforward [--strategy …"` | `"Usage: aura walkforward [--strategy …"` |
Site #6 carries two grammar alternatives separated by ` | `; **both**
gain the program name (`… | aura mc --strategy r-sma …`), so the line
stays internally consistent.
### Test-pin edit (lockstep, exactly one casing-sensitive pin)
`crates/aura-cli/tests/cli_run.rs:1409` (test `mc_rejects_real_flag`, pinning
site #6):
```rust
// before
assert!(err.contains("usage"), );
// after
assert!(err.contains("Usage"), );
```
(The exact assertion text at that line is preserved except for the
pinned substring's casing; if the assertion carries a message argument,
it is left untouched.)
All other pins are casing-neutral and stay byte-identical, verified
against the current suite: `cli_run.rs:116` and `:669` already require
capital `Usage` (satisfied by site `main.rs:4012` and by clap,
respectively — both unedited); `cli_run.rs:1444/1445` pin the verbs
`sweep`/`walkforward` and the flag `--real` (still substrings after the
prefix is prepended); `cli_run.rs:3192/3628/3876` pin out-of-scope
refusal texts (unedited); `tests/graph_construct.rs:294-297` pins only
the exit code and an echo of the bogus node name.
## Components
| File | Change |
|------|--------|
| `crates/aura-cli/src/main.rs` | 9 usage-literal edits (sites #2#10) |
| `crates/aura-cli/src/graph_construct.rs` | 1 usage-literal edit (site #1) |
| `crates/aura-cli/tests/cli_run.rs` | 1 pin flip (`:1409`, lowercase `usage``Usage`) |
No new files, no signature changes, no dependency changes.
## Data flow
Unchanged. Every touched literal keeps its current path to the user:
defined in its dispatch branch (as `&str`, `String` closure, or inline
`eprintln!`), printed to **stderr** with the `aura: ` program prefix,
followed by `exit(2)`. No emission moves between stdout/stderr, no exit
code changes, no message is added or removed — only bytes inside
existing literals change.
## Error handling
The #175 exit-code partition is the invariant to preserve: usage errors
exit 2, runtime failures exit 1. All twelve edited sites are on exit-2
paths today and stay there. The suite's exit-code pins
(`exit_codes_partition_usage_two_from_runtime_one`, the per-command
rejection tests) run unmodified except for the single casing pin above.
## Testing strategy
No new tests: the change is cosmetic and the existing suite already pins
the touched surface. The gate is the suite itself:
1. `cargo build --workspace` clean.
2. `cargo test --workspace` green with **exactly one** test-file edit
(the `cli_run.rs:1409` casing flip). Any other failing pin means an
edit strayed outside the normative table — fix the edit, not the pin.
3. `cargo clippy --workspace --all-targets -- -D warnings` clean.
4. Literal grep gates over `crates/aura-cli/src/`:
- `grep -rn '"usage:' crates/aura-cli/src/` → 0 hits;
- `grep -rn 'aura: usage:' crates/aura-cli/src/` → 0 hits;
- every hand-rolled usage literal now starts `Usage: aura ` (or
`aura: Usage: aura ` where the program prefix is baked into the
literal).
5. Smoke: `aura sweep --strategy bogus` prints the house-style line to
stderr and exits 2 (the worked example above).
## Acceptance criteria
- [ ] All 10 normative literal edits applied exactly as tabled (11
grammar alternatives counting site #6's two; sites #2/#3 remain
verbatim twins).
- [ ] `cli_run.rs:1409` pins capital `Usage`; no other test bytes change.
- [ ] Grep gates (Testing strategy #4) pass: no lowercase `usage:`
literal survives in `crates/aura-cli/src/`.
- [ ] `cargo build` / `cargo test --workspace` / clippy `-D warnings`
all green.
- [ ] Exit codes unchanged at every touched site (usage = 2).
- [ ] Out-of-scope surfaces byte-identical: refusal diagnostics,
`run_args_from` literal, clap output, fieldtests corpus, README /
design-ledger prose.