feat(research,registry,campaign): tap vocabulary + trace_name record contract (0109 tasks 1-2)
Task 1: the tap namespace is a closed vocabulary — tap_vocabulary()
(the wrap convention's four sink names; escalation = new entry or an
authored blueprint sink, never an open node-path namespace) with
DocFault::UnknownTap in validate_campaign (index-addressed, prose
enumerating the vocabulary via the single source), SlotKind::TapKinds
on the persist_taps slot, open-slot hint naming the taps. The 0107
deferral seam test split into its two 0109 pins (unknown tap refuses
at validate; a valid tap passes validate and hits the member-data
seam) — the deferral eprintln itself survives until task 3.
Task 2: CampaignRunRecord.trace_name lands serde-default sparse; the
claim contract holds across the seam — execute stamps the sentinel iff
persist_taps is non-empty, append_campaign_run composes
Some("{campaign8}-{run}") onto the stored line (safe prefix take at
the registry seam), execute mirrors the same derivation onto the
returned copy; None stays None; the hand-seeded byte-identity dump pin
survives (absent -> skipped).
Gates: workspace 1037/0, clippy -D warnings clean.
refs #201
This commit is contained in:
@@ -8,8 +8,8 @@ use std::path::PathBuf;
|
||||
use aura_research::{
|
||||
campaign_to_json, campaign_vocabulary, describe_block, open_slots_campaign,
|
||||
open_slots_process, parse_campaign, parse_process, process_to_json, process_vocabulary,
|
||||
slot_kind_label, validate_campaign, validate_process, CampaignDoc, DocError, DocFault,
|
||||
DocKind, ProcessDoc, StageBlock,
|
||||
slot_kind_label, tap_vocabulary, validate_campaign, validate_process, CampaignDoc, DocError,
|
||||
DocFault, DocKind, ProcessDoc, StageBlock,
|
||||
};
|
||||
use aura_registry::RefFault;
|
||||
|
||||
@@ -147,6 +147,10 @@ pub(crate) fn doc_fault_prose(f: &DocFault) -> String {
|
||||
format!("strategies[{strategy}].axes.{axis}: an axis is a non-empty finite set")
|
||||
}
|
||||
DocFault::UnknownEmitKind(kind) => format!("presentation.emit: unknown kind \"{kind}\""),
|
||||
DocFault::UnknownTap { index, tap } => format!(
|
||||
"presentation.persist_taps[{index}]: unknown tap \"{tap}\" (taps: {})",
|
||||
tap_vocabulary().join(" | ")
|
||||
),
|
||||
DocFault::ProcessRefMustBeContentId => {
|
||||
"process.ref: a process is referenced by content id in this version".into()
|
||||
}
|
||||
@@ -593,4 +597,20 @@ mod tests {
|
||||
assert_eq!(prose, "pipeline[2]: walk_forward step_ms must be > 0");
|
||||
assert!(!prose.contains("ZeroWalkForwardLength"), "Debug leak: {prose}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// #201 decision 1 (spec 0109): the unknown-tap refusal is path-addressed
|
||||
/// (`presentation.persist_taps[i]`) and enumerates the closed vocabulary
|
||||
/// inline — four names are small enough to print, so no introspection
|
||||
/// pointer is needed (contrast the 17-name metric roster, which points at
|
||||
/// `aura process introspect --metrics` instead).
|
||||
fn unknown_tap_prose_is_path_addressed_and_enumerates_the_vocabulary() {
|
||||
let prose = doc_fault_prose(&DocFault::UnknownTap { index: 0, tap: "bias".into() });
|
||||
assert_eq!(
|
||||
prose,
|
||||
"presentation.persist_taps[0]: unknown tap \"bias\" \
|
||||
(taps: equity | exposure | r_equity | net_r_equity)"
|
||||
);
|
||||
assert!(!prose.contains("UnknownTap"), "Debug leak: {prose}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user