feat(research): RiskRegime vocabulary + CampaignDoc.risk field + validation (#210 T1-2)
The first slice of the risk-regime structural axis (spec/plan abab1f1):
- aura-research: a serializable `RiskRegime` closed vocabulary (externally
tagged, sole variant `Vol { length, k }` — a content-addressable mirror of
the shipped two-variant StopRule, so a future Fixed regime is additive), and
an optional top-level `CampaignDoc.risk: Vec<RiskRegime>` that absent-
serializes (the `description` precedent) — content-id parity for every
risk-less document.
- validate_campaign refuses a non-positive regime (length < 1 or k <= 0, NaN
included) via a new `DocFault::BadRegime`; the CLI renders it as prose at the
research_docs seam (register/validate paths).
- The three CLI-seam E2E tests pin that a well-formed risk section passes
`campaign validate` and a bad one is refused with prose (exit 1, no Debug
leak) — the field is reachable at the seam a data author drives, not only in
library units.
Adding the field is compile-breaking at every `CampaignDoc { .. }` literal
(serde default does not cover Rust construction), so this slice also threads
`risk: vec![]` into the sites across aura-cli and aura-campaign — the
field-addition's compile-gate completion the plan should have scoped here. The
BadRegime prose reads `risk[i]: ...` (the implementer's terser wording over the
plan's illustrative string; the spec pinned no exact text). Full workspace
suite green.
refs #210
This commit is contained in:
@@ -468,6 +468,7 @@ mod tests {
|
||||
instruments: vec!["EURUSD".to_string()],
|
||||
windows: vec![Window { from_ms: 0, to_ms: 10_000 }],
|
||||
},
|
||||
risk: vec![],
|
||||
strategies: vec![StrategyEntry {
|
||||
r#ref: DocRef::ContentId("0".repeat(64)),
|
||||
axes: BTreeMap::from([(
|
||||
@@ -877,6 +878,7 @@ mod wf_tests {
|
||||
instruments: vec!["SYNTH".to_string()],
|
||||
windows: vec![Window { from_ms: window.0, to_ms: window.1 }],
|
||||
},
|
||||
risk: vec![],
|
||||
strategies: vec![StrategyEntry {
|
||||
r#ref: DocRef::ContentId("c".repeat(64)),
|
||||
axes: BTreeMap::from([(
|
||||
|
||||
@@ -150,6 +150,7 @@ fn campaign(instruments: &[&str]) -> CampaignDoc {
|
||||
instruments: instruments.iter().map(|s| s.to_string()).collect(),
|
||||
windows: vec![Window { from_ms: 1_000, to_ms: 9_000 }],
|
||||
},
|
||||
risk: vec![],
|
||||
strategies: vec![StrategyEntry {
|
||||
r#ref: DocRef::ContentId(STRATEGY_ID.to_string()),
|
||||
axes: axes_2x2(),
|
||||
|
||||
Reference in New Issue
Block a user