audit(0085): cycle close — drift-clean; C10 cycle-0085 realization note

Cycle 5 of milestone #148 (per-cycle-held accrual + CarryCost). Architect drift
review over 39f9387..f5e00a9: status clean, no code drift.

What holds (architect, evidence-of-review):
- C11 byte-identity: the AtClose eval arm is the pre-cycle-5 tokens verbatim
  (if closed { per } / if open { per }, the per + cum lines unchanged), so the
  cycle-0083/0084 net_expectancy_r goldens (-614.3134020253314, -615.0304388396047)
  stay byte-identical and the AtClose unit regressions are untouched.
- Accrual sound, no double-count: aura-analysis (summarize_r) is genuinely unchanged.
  During a hold the carry lives only in open_cost_in_r (cum=0); at close it moves to
  cum while open_cost->0 (open/closed mutually exclusive per cycle), so net_r_equity
  subtracts cum+open singly. summarize_r reads the close-row dumped total + the
  window-end accrued-so-far — one charge per trade, acc reset proven. The 3-field
  cost record's semantics generalize cleanly to accrual.
- C9/C16/C23: the diff touches only aura-std + aura-cli; aura-engine stays
  domain-free. CarryCost is a CostNode factor, CostRunner a plain Node, composed via
  cost_graph/CostSum. label() carries its param. All three run_stage1_r call sites
  threaded; the negative-rate guard is symmetric with the sibling cost flags.

Resolved this commit (the cycle-close ledger sync):
- C10 realization note (cycle 0085) added under docs/design/INDEX.md — C10's
  "per-cycle-held factors accrue over the hold" clause is now first realized (the
  prior 0084 note covered the cost-graph composite-builder).

Regression gate: cargo test --workspace (0 failures), cargo build --workspace, cargo
clippy --workspace --all-targets -- -D warnings clean — the architect is the primary
gate (no dedicated regression script). Ephemera (spec 0085 + plan 0085) git rm'd.

Milestone "Cost-model graph (in R)" remains OPEN.

refs #148
This commit is contained in:
2026-06-29 01:06:50 +02:00
parent f5e00a9c72
commit 84ec2ab5d1
3 changed files with 32 additions and 1056 deletions
+32
View File
@@ -798,6 +798,38 @@ non-load-bearing). **Carried debt (#152, for the deferred sweep-cost cycle):** t
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.
**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**"
clause is first realized. A cost factor now declares *when* it charges via
`ChargeMode { AtClose, PerHeldCycle }` (a defaulted `CostNode::charge_mode()`, default
`AtClose`), read by the **one shared `CostRunner`** — not a second runner type (a
commission is intrinsically at-close, a carry intrinsically per-held-cycle; the timing
belongs to the factor, preserving the cycle-0083 "skeleton written once" win). The
`PerHeldCycle` arm accrues `per` into a per-position `acc` every held cycle, dumps the
accrued total into `cum` at close (resetting `acc`), and marks the open position via a
**growing `open_cost_in_r`**. The first accrual node, **`CarryCost`** (`aura-std`,
a `ConstantCost` twin differing only in `charge_mode()`), is a labelled stress
parameter — the flat base of the accrual family; a run-path `--carry-per-cycle` flag
pushes it into the existing `cost_graph`/`CostSum` aggregation (no new wiring; a
per-trade and a per-held-cycle node compose, the costs summing per-field). **Approach B
(honest bleed), achieved without a `summarize_r` fold change:** the headline
`net_r_equity` curve bleeds continuously over the hold because the bleed lives in
`open_cost_in_r`, which the `net_r_equity` tap already subtracts — so `summarize_r` and
the CLI `net_eq` wiring are **untouched**, and the cycle-0083/0084 `net_expectancy_r`
goldens stay byte-identical (the `AtClose` arm is the pre-cycle-5 eval tokens verbatim).
The 3-field cost record's semantics generalize cleanly: `cost_in_r` = cost realized this
cycle (into `cum`); `open_cost_in_r` = the open position's cost marked-to-market
as-of-now (would-be-close for `AtClose`, accrued-so-far for `PerHeldCycle`) — singly
counted, no `cum`/`open` double-count (the two are mutually exclusive per cycle). Honours
C9 (a `CostRunner<CarryCost>` is an ordinary downstream `Node`), C11 (byte-identity), C16
(factor in `aura-std`, `aura-engine` domain-free), C23 (`label()` carries the rate). The
B-vs-A discriminator (a growing intra-hold `open_cost_in_r`, invisible to the scalar
`net_expectancy_r`) is pinned by unit B-proofs + a `net_r_equity`-bleeds-over-the-hold
integration test. **Deferred (each its own #148 cycle):** a notional-based carry
(`price × rate`, reads the price tap), the calendar-aware **overnight swap** proper
(rollover-boundary timing, 3× Wednesday, long/short asymmetry — deploy-edge realism), and
sweep-path cost. Decision log: #148.
**Reframe (2026-06-23, #117 — exposure → bias, R as the signal-quality unit).**
[HISTORY — its R spine survives into the 2026-06-28 contract; its Stage-2 currency /
realistic-broker / register / flat-1R-vs-compounding portions are SUPERSEDED by that