Skip to content

[C] Orion Message — Post Injection Regression Audit

TL;DR

  1. No guard is using fills-only state. All real balance gates in the hot path read InventorySnapshot, which is post-overlay TOTAL. Verified by tracing every reference.
  2. max_inventory_usd is dead config. It is referenced in exactly two places: a config echo in StrategyEngine.__init__ and a diagnostic log.info in main_loop._log_no_intents_reason. It does NOT gate intent generation anywhere in the current code. The live diagnostic field buy_inventory_guard_blocked is a misleading log artifact, not an actual gate.
  3. FLAG-034 CONFIRMED. summarize_paper_run.py:_get_inventory_balance reads inventory_ledger.new_balance (fills-only; apply_fill() strips the overlay before writing). Session summary Ending inventory XRP: 41.71 is fills-only, not total. One-line fix available, not applied.
  4. Working hypothesis for S33–S35 zero fills: dedupe + anchor-cap displacement, not a state bug. Details below. I do not recommend code changes to the buy path today.

Priority 1 — Matrix

Exact variable names shown, post-FLAG-030 semantics.

Component Source expression Expected Actual Bug?
BUY guard — _maybe_buy_intent inventory.rlusd_balance (strategy_engine.py:449) TOTAL TOTAL (post-overlay, via InventoryManager.get_snapshot()) NO
SELL guard — _maybe_sell_intent inventory.xrp_balance (strategy_engine.py:487) TOTAL TOTAL NO
Skew inventory.drift_pct * _SKEW_BPS_PER_DRIFT_PCT (strategy_engine.py:210) TOTAL TOTAL (drift computed from total balances) NO
Size skew inventory.drift_pct * _SIZE_SKEW_PER_DRIFT_PCT (strategy_engine.py:280) TOTAL TOTAL NO
Size clamp — portfolio_value inventory.total_value_in_rlusd (strategy_engine.py:258) TOTAL TOTAL NO
Risk halt — max_xrp_exposure pre_trade_inventory.xrp_value_in_rlusd (main_loop.py:787) TOTAL TOTAL NO
max_inventory_usd config.strategy.max_inventory_usd (echo at strategy_engine.py:116; comparison at main_loop.py:1102) NOT ENFORCED — comparison lives only inside a diagnostic log.info(extra={…}) block; no branch, no return, no suppression N/A — dead config. The diagnostic field buy_inventory_guard_blocked is true whenever inventory.xrp_value_in_rlusd >= 20, which is trivially true post-injection; it does not gate anything.
Quote generation (BUY path) momentum_suppressed_side, bid_protection_suppressed, dedupe at strategy_engine.py:462-463 (_state.get_live_order_by_side(OrderSide.BUY) is not None → return None) ACTIVE whenever no live BUY exists and momentum/bid-protection allow ACTIVE — but short-circuits to None when a live BUY is already resting NO (by design)
Dashboard — Ending inventory XRP summarize_paper_run._get_inventory_balance('XRP', …)SELECT new_balance FROM inventory_ledger WHERE asset='XRP' ORDER BY id DESC LIMIT 1 (summarize_paper_run.py:73-87) TOTAL (post-overlay, live portfolio) FILLS-ONLY (apply_fill() strips the overlay before writing the ledger row) YES — FLAG-034

Priority 2 — Order displacement trace

Anchor cap is the only displacement factor I can find in live config. Config says: - anchor_mode: "capped_amm" - anchor_max_divergence_bps: 10.0 - base_size_rlusd: 15.0

Trace of capped_amm in strategy_engine.py:171-188:

raw_divergence_bps = ((amm_price - mid_price) / mid_price) * 10000.0
cap_frac = 10.0 / 10000.0            # 0.001 = 10 bps
upper_bound = mid_price * 1.001
lower_bound = mid_price * 0.999
if amm_price > upper_bound:   quote_anchor_price = upper_bound   # clamped above mid
elif amm_price < lower_bound: quote_anchor_price = lower_bound   # clamped below mid
else:                          quote_anchor_price = amm_price

Consequences when cap binds (AMM diverges > 10 bps from mid): - If AMM is significantly above mid (trending up), quote anchor pins at mid × 1.001 → BUY placement is anchored ABOVE where it would be under amm_or_mid, which in a rising-AMM regime helps fills. Good. - If AMM is significantly below mid (trending down), quote anchor pins at mid × 0.999 → BUY placement is anchored BELOW where it would be, which in a falling market puts BUY deeper in the book and reduces fill probability. - This is the same mechanism Atlas cited. I did not find any additional displacement factor in live config (no participation filter, no toxicity-based widening live, no momentum widening — only momentum SUPPRESSION of intents).

Displacement = anchor cap only. Confirmed.

Priority 3 — Quote presence vs guard state

For S35 specifically I cannot read the log because that session's DB state is in the currently-live DB and I've been instructed not to touch the live DB. What I can assert from the code:

  1. _maybe_buy_intent returns None in exactly three cases: momentum filter trip, RLUSD < order_size, OR a non-terminal BUY already exists in _state.
  2. Post-injection, RLUSD balance is 97.61 (TOTAL), order size is 15 → RLUSD check passes with huge margin. Not a state bug.
  3. The S31 log line Katja captured (session31.log:67) shows "buy_inventory_guard_blocked": true AND "buy_live_order_exists": true in the same record. That is the _log_no_intents_reason diagnostic block. The reason intents was empty that tick was the dedupe at line 463 (live BUY already exists), NOT the max_inventory_usd comparison. The two log fields are independent booleans in the same dict; the _guard_blocked one is not a causal gate.
  4. At-touch BUY with zero fills is consistent with microstructure queue position + anchor-cap displacement during a downtrend, not with BUYs being suppressed by a state bug.

Was BUY intent live during at-touch events? Not determinable from code alone. Needs engine_state or log inspection from the actual S33–S35 runs. My reading of the architecture says yes — BUY intent should have been emitted, an order should have been placed, and zero fills is a placement/queue issue.

Priority 4 — Config safety review

Post-injection config values on disk:

Key Value Notes
base_size_rlusd 15.0 ↑ from 10.0 (scale validation)
max_xrp_exposure 150.0 ↑ from 100 — OK; live XRP is ~67, headroom 83
max_rlusd_exposure 120.0 ↑ from 100 — OK; live RLUSD is ~97.6, headroom 22
max_inventory_usd 20.0 ↑ from 10 — cosmetic, dead config
anchor_mode "capped_amm" unchanged
anchor_max_divergence_bps 10.0 unchanged — this is the tight one

Interactions I can flag: - base_size_rlusd = 15 × 2 quotes ≈ 30 RLUSD per round → RLUSD headroom above max_rlusd_exposure is 22. One filled SELL + one filled BUY pair would breach it. Not causing S35 zero fills, but sits close to the ceiling. - max_xrp_exposure = 150 is comfortable for one scale-up tier but not two. - anchor_max_divergence_bps = 10.0 is the single parameter most likely to be over-tight under FLAG-030 overlay + size=15. Do NOT loosen yet — state-consistency first, per Vesper.

Priority 5 — FLAG bundle status

  • FLAG-033 (PRAGMA quick_check at startup): queued, ~10 LOC, not yet started. Will land on a fresh branch off main after 031 merges.
  • FLAG-034 (session summary fills-only): confirmed real. Proposed fix below, not applied.
  • FLAG-028 (idx_fills_session_id): remainder queued.

FLAG-034 proposed fix

Affected lines: summarize_paper_run.py:73-87 and summarize_paper_run.py:170-173.

Current:

def _get_inventory_balance(conn, asset, fallback_key) -> float:
    row = conn.execute(
        "SELECT new_balance FROM inventory_ledger WHERE asset = ? ORDER BY id DESC LIMIT 1",
        (asset,),
    ).fetchone()
    if row:
        return float(row["new_balance"])
    fallback = _get_float_state(conn, fallback_key)
    return fallback if fallback is not None else 0.0

Proposed:

def _get_inventory_balance(conn, asset, fallback_key) -> float:
    row = conn.execute(
        "SELECT new_balance FROM inventory_ledger WHERE asset = ? ORDER BY id DESC LIMIT 1",
        (asset,),
    ).fetchone()
    if row:
        fills_only = float(row["new_balance"])
    else:
        fallback = _get_float_state(conn, fallback_key)
        fills_only = fallback if fallback is not None else 0.0
    # FLAG-034: add capital-events overlay so the displayed balance matches
    # the live total held by InventoryManager (fills + capital deltas).
    overlay = conn.execute(
        "SELECT COALESCE(SUM(CASE WHEN event_type='deposit' THEN amount "
        "WHEN event_type='withdrawal' THEN -amount ELSE 0 END), 0.0) AS o "
        "FROM capital_events WHERE asset = ?",
        (asset,),
    ).fetchone()["o"]
    return fills_only + float(overlay)

Notes: - Mirrors InventoryManager.rebuild() semantics. - Excludes basis_commit via the CASE — those are RLUSD basis-only and don't move asset balances. - Read-only, no schema change, no config change. - Needs unit test before merge.

Not applying. This touches display logic that feeds every dashboard render and the _log_session_summary output at shutdown. Flag for Atlas review; I want alignment before the one-liner lands.

What I did NOT do

  • No live session started.
  • No config changes.
  • No code edits.
  • No loosening of anchor_max_divergence_bps.

Recommendation to Atlas

State-consistency audit finds one real bug (FLAG-034, display-only) and one piece of dead config (max_inventory_usd). No guard is using fills-only. The S33–S35 zero-fills pattern is most likely anchor-cap displacement under the new base_size_rlusd = 15 regime, not a state bug.

Suggested next step before the scale validation run resumes: 1. Approve FLAG-034 fix to land on its own branch (not bundled with 031). 2. Decide whether to (a) retire max_inventory_usd as dead code or (b) wire it into _maybe_buy_intent as a real gate. Don't ship both paths. 3. Review whether anchor_max_divergence_bps = 10.0 is still the right cap at size=15, or whether to widen it to ~15 bps for the next session. I'll wait for the ruling.

— Orion