feat(cli): aura campaign runs — read-back for stored realizations (fieldtest 0108 F11)
The recorded bootstrap/generalization evidence is no longer write-only:
'aura campaign runs' lists every stored record (campaign id, run
counter, cell count, first cell's stage signature); 'aura campaign
runs <id> [run]' dumps the BARE stored line(s) — the store form,
byte-identical, never the {"campaign_run": ...} run-emit wrapper (the
F10 parsing trap). A lookup, not an action: empty/unmatched notes and
exits 0 (the runs-family convention); outside a project the campaign
family's project refusal.
RED-first (tdd-author handoff): hermetic seed of one hand-written
store line into the fixture project, list + byte-identical dump pinned,
observed failing on clap's unknown-subcommand exit 2.
Gates: workspace 1027/0, clippy -D warnings clean.
closes #206
This commit is contained in:
@@ -845,6 +845,61 @@ fn campaign_run_unknown_id_refuses() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Property: the recorded campaign realizations are READABLE BACK. A read-back
|
||||
/// verb (`aura campaign runs`) both lists every stored campaign-run record on a
|
||||
/// scannable line carrying its campaign id, and — addressed by that id — dumps
|
||||
/// the BARE persisted store record (the `campaign_runs.jsonl` line form), NOT
|
||||
/// the `{"campaign_run": …}` stdout wrapper the `campaign run` emit uses (F10,
|
||||
/// fieldtest 0108). Today `runs` is an unrecognized campaign subcommand (clap
|
||||
/// exit 2) — the feature is absent.
|
||||
///
|
||||
/// Hermetic seed: one hand-written record line in the exact bare store form
|
||||
/// serde emits (mirroring the aura-registry pre-widening parse line —
|
||||
/// canonical field order, sparse-skip fields omitted — so a re-serialized dump
|
||||
/// is byte-identical). Appending a real record needs a full campaign run over
|
||||
/// data; hand-writing the store line is the only data-free path and pins the
|
||||
/// bare-store-line contract exactly.
|
||||
#[test]
|
||||
fn campaign_runs_lists_and_dumps_the_bare_stored_record() {
|
||||
let _fixture = project_lock();
|
||||
let dir = built_project();
|
||||
let runs_dir = dir.join("runs");
|
||||
std::fs::remove_dir_all(&runs_dir).ok();
|
||||
std::fs::create_dir_all(&runs_dir).expect("create runs dir");
|
||||
let _cleanup = ScratchGuard(vec![ScratchPath::Dir(runs_dir.clone())]);
|
||||
|
||||
let campaign_id = "deadbeef".repeat(8); // a 64-hex content id
|
||||
let record_line = format!(
|
||||
r#"{{"campaign":"{campaign_id}","process":"beef","run":0,"seed":42,"cells":[{{"strategy":"3f9c","instrument":"GER40","window_ms":[1725148800000,1727740799999],"stages":[{{"block":"std::sweep","family_id":"sweep-0"}},{{"block":"std::gate","survivor_ordinals":[0,1,2,3]}}]}}]}}"#
|
||||
);
|
||||
std::fs::write(runs_dir.join("campaign_runs.jsonl"), format!("{record_line}\n"))
|
||||
.expect("seed the campaign-run store");
|
||||
|
||||
// LIST mode: one scannable line per stored record, carrying the campaign
|
||||
// id (bare 64-hex or a prefix), exit 0.
|
||||
let (list_out, list_code) = run_code_in(dir, &["campaign", "runs"]);
|
||||
assert_eq!(list_code, Some(0), "list exits 0: {list_out}");
|
||||
assert!(
|
||||
list_out.contains(&campaign_id[..8]),
|
||||
"the list line carries the campaign id (bare or prefix): {list_out}"
|
||||
);
|
||||
|
||||
// DUMP mode: addressed by the campaign content id, prints the BARE stored
|
||||
// record line — the store form, NOT the `{{"campaign_run": …}}` run-emit
|
||||
// wrapper (F10) — byte-identical to the seeded line, exit 0.
|
||||
let (dump_out, dump_code) = run_code_in(dir, &["campaign", "runs", &campaign_id]);
|
||||
assert_eq!(dump_code, Some(0), "dump exits 0: {dump_out}");
|
||||
assert!(
|
||||
!dump_out.contains("\"campaign_run\""),
|
||||
"dump prints the bare store record, not the run-emit wrapper (F10): {dump_out}"
|
||||
);
|
||||
assert_eq!(
|
||||
dump_out.trim(),
|
||||
record_line,
|
||||
"dump is byte-identical to the bare stored line (F10): {dump_out}"
|
||||
);
|
||||
}
|
||||
|
||||
/// The v2 boundary, order side: `[sweep, monte_carlo, walk_forward]` is
|
||||
/// intrinsically valid — `process register` ACCEPTS it (asserted inside
|
||||
/// `register_process_doc`; the intrinsic-tier ground is the shipped
|
||||
|
||||
Reference in New Issue
Block a user