audit: trace-handle cycle close — refusal parity, measurement pin, ledger lockstep

Architect review over 9636b00..9221bcd. What holds, confirmed against the
diff rather than the commit body: no stored record shape moved (neither
`aura-engine/src/report.rs` nor the registry compat mirror appears in the
change at all, and the byte pins pass unedited); the handle travels the
beside-the-report route C27/#297 established for the unbound-tap names, with
the library still printing nothing; trace enumeration landed inside
`aura-registry` where C22 puts trace file I/O; no C14 exit class moved, both
refusal arms falling through to the same exit 1.

Two high drift items, both fixed here:

- The corrected refusal claimed a campaign run prints its handle as
  `trace_name` on stdout. It prints `campaign_run.trace_name` — the campaign
  leg wraps its record, as the glossary states outright — so the chain the
  refusal advertised returns null there. This is the third instance of one
  error class in this cycle: a false claim inside the very prose meant to
  stop misdirecting callers. Grounding caught the first two, review the
  third.
- The measurement leg shipped without the handle pin the spec asked for. All
  three new pins drove the strategy path, so the measurement leg emitted a
  handle nothing asserted. It has its own test now, on the shared bind pair
  the two legs cannot drift across.

Ledger and vocabulary brought into lockstep: C27's current state records the
`RunOutcome` carrier that replaced the pair; the glossary's tap entry names
the single-run handle and warns that a family id is not one; the authoring
guide's own single-run tap example now says the name is printed rather than
guessed. The suggestion line gained the `aura:` prefix every other stderr
line carries.

Bench: all five fingerprints OK — the decisive signal, since they hang on the
record bytes this cycle was required not to move. Timing deltas are load
noise (loadavg 8.7 under concurrent agents), not regressions.

refs #309
This commit is contained in:
2026-07-26 23:22:17 +02:00
parent 9221bcd167
commit 9f87e5a583
5 changed files with 43 additions and 7 deletions
+28
View File
@@ -138,3 +138,31 @@ fn run_refuses_a_hand_crafted_envelope_with_a_bad_root_name_before_any_trace_wri
"no trace directory of any shape is written on a refused run"
);
}
/// #309: the measurement leg reports its trace handle exactly as the strategy
/// leg does — both bind through one shared tap-plan pair, so a handle present
/// on one and absent on the other would mean the seam had drifted.
#[test]
fn measurement_run_reports_its_trace_handle_on_stdout() {
let cwd = temp_cwd("measurement-trace-handle");
let bp_path = cwd.join("measurement.json");
std::fs::write(&bp_path, measurement_blueprint_json()).expect("write measurement blueprint");
let out = Command::new(BIN)
.args(["exec", bp_path.to_str().expect("utf-8 path")])
.current_dir(&cwd)
.output()
.expect("spawn exec");
assert!(out.status.success(), "stderr: {}", String::from_utf8_lossy(&out.stderr));
let line = String::from_utf8_lossy(&out.stdout);
let report: serde_json::Value =
serde_json::from_str(line.trim()).expect("stdout is one JSON object");
let handle = report["trace_name"].as_str().expect("trace_name is present and a string");
assert!(
cwd.join("runs/traces").join(handle).join("fast_tap.json").exists(),
"the reported handle must name the directory the tapped series landed in; got {handle}"
);
let _ = std::fs::remove_dir_all(&cwd);
}