RWG-1 — the runaway-order guard: phantom turnover-blend base on a HALT, and a blocked drawdown liquidation
status: open · raised panel run 11 (2026-08-20) · migrated 2026-08-24 (body verbatim below) · class: loudness & safety (live path) · judgement: YES · effort ~0.5–1 pd · leg 1 was resolved by the owner 2026-08-20 — see the dated triage note at the foot
15. RWG-1 — the runaway-order guard has halted the meanrev control sleeve two consecutive days (zero orders; the sell-count floor rose 44→149), the halt path advances its own turnover-blend base while nothing executes (unruled semantics), and a drawdown kill-switch liquidation of the current 196-name book would be blocked by the same guard — armed today, not latent. · judgement: YES · effort ~0.5–1 pd · horizon: live now (the control is not trading; the phantom blend base compounds each halted day)
Ground truth (data/state/meanrev/order_log.jsonl): 08-19
safety_halted: true, "205 orders exceeds max 150 (runaway guard)",
n_targets 209, n_submitted 0; 08-20 same at 158 > 150, n_targets 161, n_submitted 0; selection_completed: false both days; equity marks
continue on a frozen book (196 names, portfolio_snapshots 08-17→08-20:
173→185→196→196).
Leg 1 — calibration is a policy call, and it is the owner's. The guard
counts the entire batch with no de-risking exemption
(safety.py:245-250); the only de-risking exemption in the file
(all_de_risking, safety.py:225) gates the daily-loss breaker alone — so
CLAUDE.md's "de-risking is never blocked" is true only there and for
per-order REJECTs. config/meanrev.yaml:128 pins max_orders_per_run: 150
as a bare copied value; the calibration comment behind 150 ("a full rebuild
is ~50-100 orders") lives in momentum's config (settings.yaml:238) —
a 50-name-sleeve number applied unmodified to a daily-churn sleeve holding
196 names against a 50-name selection (PC-1's unbounded growth, peak 2.92x).
Options, none pre-decided: (a) exempt all-sell batches from the count
guard (the guard's Knight-Capital rationale is amplification, mostly
buy-side — but a runaway-sell loop is a real class; this trades that
protection for guaranteed de-risking); (b) scale meanrev's
max_orders_per_run to its book (config VALUE — owner-only, the panel
proposes nothing here); (c) accept the wedge for the never-promotable
control and record that it trades only on sub-150-order days. Every code
path here is the fail-closed safety layer: the panel does not touch it.
Leg 2 — the blend base advanced while nothing executed; rule the semantics
before the burst arrives. daily.py:1623-1634 persists last_targets
(the next day's turnover-blend base) before execute_orders
(:1692), guarded only by dry_run — no halt guard. Verified consequence:
kelly_ledger.json last_targets is dated 2026-08-20 with 161 weights
despite zero submissions, and weighted_turnover read exactly 0.5000 =
the cap on both halted days — measured against the phantom base, so the
intended book has walked two full cap-steps away from the real one; the
clearing day's realized weighted churn against the REAL book can approach
~1.0, far past the daily cap. (The 205→158 order-count decline is
phantom-target decay, not book convergence — sells rose 44→149 while
resizes shrank.) This is a semantics divergence to rule, not a plain
bug: the engine's own nearest analog retains the intended book in-cash
and re-enters uncapped (engine.py:868-873, :657-666), and the live
comment shows deliberate mimicry — but a safety HALT was unmodeled. Either
gate the persist on execution success, or record intended-book semantics
(and the post-halt burst) as deliberate; pin whichever ruling the owner
records with a test.
Leg 3 — the same guard blocks the emergency exit, and on meanrev it is
armed now. The drawdown kill-switch flat-to-cash path
(daily.py:1089-1105) routes through pipeline.execute_orders →
_safety_gate → the count guard, which exempts nothing: a liquidation of
any >150-name book HALTs. For meanrev's current 196-name book this is not
latent — its own kill switch firing today would be blocked (momentum at 63
names is clear). This contradicts the safety layer's own stated intent
("blocking a de-risking trade during a crash would leave the book exposed,
the opposite of fail-closed", safety.py:216-219) precisely in the
emergency it exists for. Compounding, same persist-before-execute class:
the kill-switch path wipes the Kelly holding-return snapshot at
daily.py:1101-1103 before execute_orders — a halted liquidation
clears the snapshot while the book remains fully held. Legs 2+3 resolve in
the same fix-sitting as leg 1's policy call.
Test design. Leg 1 (if (a)): a 196-sell batch passes the count guard, a
196-mixed batch still halts; revert → red; regression: a simulated
kill-switch liquidation of a >150-name book reaches the broker. Leg 2: pin
the recorded ruling (halt → last_targets unmoved, or intended-book
semantics asserted with the burst documented); revert → red. Leg 3's
snapshot wipe: on a halted liquidation, the Kelly snapshot survives.
Kill criterion — pre-registered. If by 2026-09-04 (10 td) meanrev has resumed submitting with NO config or code change, the wedge-persistence claim for this instance is falsified — record that, and the row narrows to legs 2+3, which stand independently of whether this halt self-clears. If the owner rules (c) and the leg-2 ruling is pinned, the row closes with the wedge accepted-as-recorded. Zero registry rows, zero DSR debt, no pinned value touched.
Coupling flags (for triage, not edits): PC-1's 08-31 dismissal default
rests on pre-halt evidence (expiry watch above). The AVB/BRK-B failed-pair
day-3 tripwire is masked, not resolved — with n_submitted 0 the two
per-symbol failures cannot occur; it re-arms the day the halt clears.
Triage note — 2026-08-24 (annotation only; the body above is untouched)
Leg 1 is DECIDED and the row narrows to legs 2+3. The owner took option
(b) on 2026-08-20 in 955db93: meanrev's safety.max_orders_per_run 150→300
(config + keystone, the deliberate two-touch); momentum and vrp stay at 150.
Re-verified from data/state/meanrev/order_log.jsonl: 08-19 n_submitted 0
of 209 targets, 08-20 0 of 161, then 08-21 133 of 149 and 08-24 96 of
73 — the sleeve is submitting again.
The item's own 09-04 falsifier is therefore already answered, and in the direction that CONFIRMS the row, not the one that narrows it. The pinned wording was "if by 2026-09-04 meanrev has resumed submitting with NO config or code change, the wedge-persistence claim is falsified". A config change was required to clear the wedge, so wedge-persistence stands as claimed. Legs 2 and 3 stand independently either way, as the item said.
Leg 2 has since been measured, not just predicted. The daily audit of
2026-08-21 recorded the clearing-day churn against the phantom base —
realized cap-accounted churn 67.2% two-sided vs the 0.5/day cap (97.4% gross
incl. cap-exempt emergency exits), with last_targets dated 2026-08-20
carrying 161 weights against n_submitted 0. Durable record:
research/2026-08-21_meanrev_clearing_day_churn.md (PR #113, merged 9b2e268).
Attribution — legal frequency-scaled catch-up vs phantom-base artifact — was
deliberately left to this row and is still open.
Leg 3 is temporarily de-armed on meanrev and re-arms on its own. With the cap at 300 a liquidation of today's book passes the count guard; the book is 219 names as of 2026-08-24 and rising (173→185→196→196→196→219 since 08-17), so the guard re-arms against the kill-switch path as the book approaches 300. The structural point the item makes — the count guard exempts nothing, including an all-sell de-risking batch — is unchanged by the recalibration.
Triage note — 2026-09-07 (annotation only; the body above is untouched)
Read this first: PR #154's "leg 3" is IGD-1's leg 3, not this row's. #154
(ee68ebe, 2026-09-06) is titled "IGD-1 leg 3 (owner ruling) + FOS-1" and
rules the failed-order escalation shape (exit 4 on a NEW de-risking failure).
It does not touch the runaway-order count guard. Recorded because the titles
collide and a reader scanning git log would reasonably conclude otherwise.
Leg 2 — STILL LIVE, verbatim. daily.py:1795-1803 persists
ledger["last_targets"] guarded only by if not self.pipeline.dry_run:
(:1796); execute_orders runs at :1862. No halt guard, no recorded
semantics ruling, no pinning test.
Leg 3 — the core is STILL LIVE; only its compounding facet closed. KSP-1
(#151, 47ea024) fixed the side-effects this row named: _liquidate_to_cash
now reads the halt state (daily.py:1222-1223) and on a halt advances
nothing, the kill-switch active: True publish is deferred through
_kill_switch_pending (:1103-1106 → :1227-1230), and the Kelly snapshot
is cleared only in the non-halt branch (:1231-1234). The blockage itself
is untouched: safety.py:261-267 still counts len(orders) with no
exemption, and the only all_de_risking exemption remains scoped to the
daily-loss breaker (safety.py:225-232). The code's own comment at
daily.py:1213 names "RWG-1 leg 3: the count guard blocks any >150-name
book" as a still-live premise — so the fix that landed knows it did not
close this.
Arming status re-measured, and it moved the wrong way. The 08-24 note
predicted leg 3 would re-arm as the book approached the 300 cap; the 08-31
note recorded the book falling. It then climbed:
203 (08-28) → 233 → 250 (09-01) → 248 → 243 → 239 (09-04). On 2026-09-01
meanrev submitted 241 orders against its 300-order cap — the closest it
has come since the 08-19/20 halt that needed an owner config change to clear
— and a kill-switch liquidation of that day's 250-name book would have been
250 sells, 50 short of a HALT. Momentum is clear (67 names against 150).
Consequence for sequencing. The row's own text says legs 2 and 3 resolve in one sitting with a ruling; SAC-1's cap note asks to be sequenced first so the ruling is made once. Triage carries both into this week's decide-list as one item on that basis, and makes no ruling itself — every path here is the fail-closed safety layer.