audit: net-r cycle close — ledger reconciled, drift items resolved

Architect review over dd23ea3..HEAD (the #234/#152 cycle, 6 commits).

What holds (architect-confirmed): CostSpec is a closed, deny-unknown-
fields vocabulary with typed slots mirroring RiskRegime, field names
conforming to the builders' ParamSpec names; cost-less docs hash
byte-identically (C18); cost threads through the single MemberRunner
seam so every campaign stage nets uniformly; costed families reproduce
bit-identically incl. Carry; the #221-deleted leg is rebuilt optional
(net = gross under the empty model); both cost_graph leaks replaced by
the interned single source (#152).

Resolved this close: [high] the C10 realization notes contradicted
shipped reality — the two 'wired on the run path via --cost-*' claims
carry superseded-annotations, the 0084 carried-debt note a discharged-
annotation, and a new cycle-net-r realization documents the campaign
cost block, the net-by-default decision, the manifest/reproduce
round-trip, and the returned net_r_equity tap; [medium] two dangling
persist_traces_r docstring references reworded to what exists;
[medium] the one-knob-per-cost-node invariant behind the manifest
round-trip is now unit-pinned (exactly one distinctly-named knob per
shipped builder).

Cycle spec and plan (git-ignored working files) discarded per
convention.

refs #234
This commit is contained in:
2026-07-11 12:28:15 +02:00
parent c32c01a63c
commit aaca18c6f6
2 changed files with 59 additions and 5 deletions
+28 -4
View File
@@ -633,7 +633,7 @@ fn present_campaign(
}
/// Which drained wrap-convention channel a requested tap persists from on a
/// campaign trace re-run. The routing mirrors `persist_traces_r` (main.rs):
/// campaign trace re-run. The routing follows the wrap-convention channels:
/// equity <- the SimBroker equity recorder (tx_eq), exposure <- the Bias
/// recorder (tx_ex), r_equity <- the cum_realized_r + unrealized_r recorder
/// (tx_req), net_r_equity <- the cost leg's LinComb(4) net-curve recorder
@@ -747,9 +747,8 @@ fn cell_member_fanout(cell_out: &CellOutcome) -> Vec<(Option<String>, &RunReport
/// drift alarm — manifest fields are fresh-context and not compared), and
/// writes the requested-AND-producible taps through the sweep verbs'
/// member-dir mechanism: a slash-joined `"{name}/{key}"` handed to
/// `TraceStore::write` (the `persist_traces_r(&format!("{name}/{key}"), ..)`
/// layout — the fn itself is not reused: it writes a fixed tap set and
/// process-exits on error). The written index manifest is the RECORDED
/// `TraceStore::write` (the slash-joined member-dir layout the sweep verbs
/// established). The written index manifest is the RECORDED
/// member's — the trace documents that run's provenance, not a re-derived
/// fresh-context one. Loud stderr per no-candidate cell (neither a nominee
/// nor a non-empty terminal family) and ONCE per unproducible requested tap
@@ -1309,4 +1308,29 @@ mod tests {
);
assert!(cost_nodes_for(&[]).is_empty(), "an empty model binds no nodes");
}
#[test]
/// #234: the manifest-stamp/reproduce round-trip (`cost[k].<knob>` ->
/// `cost_specs_from_params`) reconstructs a component from its knob NAME —
/// sound only while every shipped cost node declares exactly one,
/// distinctly-named knob. A second knob (or a name collision) would break
/// variant reconstruction with no compiler error; this pin makes it loud.
fn every_cost_builder_declares_exactly_one_distinct_knob() {
let knobs: Vec<String> = [
aura_std::ConstantCost::builder(),
aura_std::VolSlippageCost::builder(),
aura_std::CarryCost::builder(),
]
.iter()
.map(|b| {
let params = b.params();
assert_eq!(params.len(), 1, "one knob per cost node: {}", b.label());
params[0].name.clone()
})
.collect();
let mut dedup = knobs.clone();
dedup.sort();
dedup.dedup();
assert_eq!(dedup.len(), knobs.len(), "knob names must be pairwise distinct: {knobs:?}");
}
}
+31 -1
View File
@@ -741,7 +741,10 @@ cost = 0 baseline on an empty stream. The headline sink is **`net_r_equity`** =
(C8/C18), a sibling of `r_equity`, emitted only when a cost is authored. Wired on the
**run path** via `--cost-per-trade` (`r_sma_graph`); sweep / walk-forward / mc pass
`None` (cost on the reduce-mode sweep path and cost in OOS pooling deferred — the
positional join holds only while one cost node fires in lockstep with PM). Deferred to
positional join holds only while one cost node fires in lockstep with PM).
[Superseded 2026-07-11 (#234): the `--cost-*` run-path flags are gone (#221 removed
that surface); cost is authored as the campaign document's `cost` block and reaches
every family/campaign member — see the cycle-net-r realization below.] Deferred to
later milestone cycles: the general `CostNode` trait + multi-node cost-graph
composite-builder, data-grounded factors (realized-vol → slippage, recorded-rate →
swap), per-cycle-held accrual (carry / funding), and the conviction-weighting
@@ -770,6 +773,8 @@ composable with `--cost-per-trade` (their costs sum); sweep / walk-forward / mc
`None`. The 3-field cost triple is now restated by-convention across the two producers
+ `CostSum` (a compiler-unlinked lockstep) — to be unified by the still-deferred
general `CostNode` trait (now justified by two concrete nodes). Decision log: #148.
[Superseded 2026-07-11 (#234): the `--slip-vol-mult`/`--cost-per-trade` flags are gone;
authoring moved to the campaign `cost` block — see the cycle-net-r realization below.]
**Realization (cycle 0083 — CostNode trait + shared cost-record contract, cycle 3,
#148).** The deferred unifier ships. A new `aura-std/src/cost.rs` owns the cost-model
@@ -811,6 +816,8 @@ non-load-bearing). **Carried debt (#152, for the deferred sweep-cost cycle):** t
`cost_graph` `.leak()`s runtime port names per build — fine for one-shot run-path
construction, but to be interned (the `COL_PORTS` production pattern, not the test-only
`.leak()`) before cost reaches the per-member sweep path. Decision log: #148.
[Discharged 2026-07-11 (#152/#234): `cost_port`/`intern_port` in `aura-std/src/cost.rs`
are the process-global interned single source; both `cost_graph` `.leak()`s are gone.]
**Realization (cycle 0085 — per-cycle-held accrual, cycle 5, #148).** C10's
"per-trade factors deduct at close; **per-cycle-held factors accrue over the hold**"
@@ -844,6 +851,29 @@ integration test. **Deferred (each its own #148 cycle):** a notional-based carry
(rollover-boundary timing, 3× Wednesday, long/short asymmetry — deploy-edge realism), and
sweep-path cost. Decision log: #148.
**Realization (cycle net-r — cost reaches the family/campaign path, #234/#152,
2026-07-11).** The deferred sweep-path cost ships, delivered where C24 put experiment
intent: the campaign document gains an additive `cost: Vec<CostSpec>` block — a closed,
externally tagged vocabulary over the three shipped nodes (`constant` / `vol_slippage`
/ `carry`, field names = the builders' own `ParamSpec` names), mirroring the `risk`
block (serde `default` + skip-if-empty: cost-less docs hash byte-identically, C18).
Net is the **default**: an absent block is the explicit zero-cost model and
`summarize_r`'s net family equals gross under it — every result is net, no second
"gross-labelled" result kind. `cost_nodes_for` (beside `stop_rule_for_regime`) is the
one doc→builder binding, every component fully bound (the wrapped param space stays
cost-invariant); `wrap_r` carries an optional cost leg (the #221-deleted wiring
rebuilt: cost_graph off the executor's four geometry outputs, the vol proxy back in
production, a gated cost recorder in reduce mode as the `summarize_r` join input, the
`LinComb(4)` `net_r_equity` curve in trace mode). Member manifests stamp the
components; both re-run sides re-derive them (reproduce via `cost_specs_from_params`
the #233 stop pattern — and the persist re-run binds the same model, so the C1 drift
alarm compares like with like; costed families reproduce bit-identically, pinned incl.
`Carry`). `TapChannel::Net` routes `net_r_equity` to persisted curves; a cost-less doc
requesting it keeps a remedy-naming skip notice. The `--cost-*` run-path flags do not
return; the verb sugar passes no cost (docs carry it) — the same lean-flag call as the
C26 bindings block. #152's interning ships with it (`cost_port`/`intern_port`, both
`cost_graph` `.leak()`s gone). Decision log: #234.
**Realization (cost-flag harness scoping, #153).** Cost flags are defined only
against an R-evaluator harness (the gross-R → net-R chain). On a non-R harness
(`--harness sma`/`macd`, which produce no R) a cost flag is a **usage error