Orion Tasking — Phase 7.3 Pre-Gate Branches¶
To: Orion CC: Katja, Atlas From: Vesper Date: 2026-04-19
Context¶
Atlas ruled (2026-04-19) that Phase 7.3 requires two fixes before the sweep can run. Both are blocking gates. This message scopes both branches completely so Orion can cut code without a separate investigation round.
Branch 1 — fix/intended-distance-to-touch¶
What to fix¶
_compute_distance_to_touch in neo_engine/main_loop.py (line 1619) currently sources price from self._state.get_live_order_by_side(). In paper/dry_run mode this always returns None → both sides always NULL. Atlas ruled that Phase 7.3 measures price level, not queue position. The metric must be computed from intended price on every tick, with no NULLs.
Current logic (lines 1619–1674)¶
live_buy = self._state.get_live_order_by_side(OrderSide.BUY)
buy_price = getattr(live_buy, "price", None) if live_buy is not None else None
if buy_price is not None and buy_price > 0:
bid_bps = (best_bid - buy_price) / best_bid * 10000.0
Required behavior (Atlas-locked)¶
Source priority:
1. Live order price — if get_live_order_by_side() returns an order with a valid price, use it (preserves live-mode accuracy)
2. Intended price fallback — if no live order, compute from self._strategy.last_bid_offset_bps / last_ask_offset_bps:
# intended buy price
buy_price = snapshot.mid_price * (1.0 - self._strategy.last_bid_offset_bps / 10000.0)
# intended sell price
sell_price = snapshot.mid_price * (1.0 + self._strategy.last_ask_offset_bps / 10000.0)
last_bid_offset_bps and last_ask_offset_bps are set on every tick by strategy_engine.py (lines 242–243) before _persist_tick_telemetry is called. They are the final post-skew offsets — the correct values to use.
Null guard¶
If last_bid_offset_bps is None (engine hasn't ticked yet), fall through to NULL as before. After the first strategy tick they will always be set.
Docstring update¶
Update the _compute_distance_to_touch docstring:
- Remove the "Source: live resting order only" line (that was Vesper Q3 ruling — superseded by Atlas 2026-04-19)
- Document the live→intended fallback with the Atlas ruling reference
- Keep the sign convention and "never affect the tick" contract unchanged
Tests required (minimum 2)¶
- Paper mode populates — in dry_run mode (no live orders), assert
distance_to_touch_bid_bpsanddistance_to_touch_ask_bpsare non-NULL after at least one tick. Uselast_bid_offset_bps/last_ask_offset_bpsset manually on the strategy object. - Live order takes priority — when
get_live_order_by_sidereturns an order with a price, assert that price is used (not the intended fallback).
Commit subject¶
Files touched¶
neo_engine/main_loop.py—_compute_distance_to_touchmethod onlytests/test_distance_to_touch.py(new) or extend existing Branch #6 test file
Branch 2 — fix/inventory-invariant-at-shutdown¶
What to fix¶
There is no inventory invariant check at shutdown. The pre-7.3 audit (Atlas-locked) requires a hard invariant that runs at session close, evaluates inventory health, and writes its result to engine_state as inventory_invariant.status. The S40 gate is: inventory_invariant.status=ok. Currently the key does not exist after any session.
Where to add it¶
The engine shutdown sequence is in main_loop.py. The correct insertion point is after fills/orders are finalized but before _conn.close() — same pattern as the WAL checkpoint (Branch #7). Look for the shutdown / close() path invoked after halt_reason is set.
What the check should do¶
At shutdown, read the current inventory snapshot and evaluate:
def _check_inventory_invariant(self) -> None:
"""
Hard inventory invariant at shutdown.
Writes inventory_invariant.status = 'ok' or 'fail:<reason>' to engine_state.
Never raises — a failed invariant is logged at ERROR but does not block shutdown.
"""
Check conditions (all must pass for ok):
1. xrp_balance >= 0 — no negative XRP
2. rlusd_balance >= 0 — no negative RLUSD
3. total_value_rlusd > 0 — non-zero total value (catch complete wipeout)
4. XRP share between 5% and 95% — catch extreme inventory imbalance at shutdown
If all pass → write inventory_invariant.status = "ok" to engine_state.
If any fail → write inventory_invariant.status = "fail:<condition_name>" and log at ERROR with exc_info=False (include the failing values in the log fields).
If the snapshot itself can't be read (exception) → write inventory_invariant.status = "error" and log at ERROR with exc_info=True. Never re-raise.
Bounds rationale¶
The 5%–95% XRP share bounds are wide enough to not interfere with normal session outcomes (S40 ended at 55.9% XRP, well within range). They are a safety net for extreme cases — not a tuning parameter. If Atlas wants these adjusted, flag before committing.
engine_state key¶
Tests required (minimum 3)¶
- Clean session writes
ok— normal inventory state producesinventory_invariant.status=okin engine_state. - Negative balance writes
fail— mock a snapshot withxrp_balance=-1, assert status isfail:negative_xrp_balance(or equivalent). - Extreme skew writes
fail— mock inventory at 99% XRP, assertfail:xrp_share_too_high.
Commit subject¶
Files touched¶
neo_engine/main_loop.py— new_check_inventory_invariantmethod + one call in shutdown sequencetests/test_inventory_invariant.py(new)
Branch order¶
Either branch can be cut independently. Suggest: 1. Branch 1 first (smaller, unblocks the metric for sweep validation) 2. Branch 2 second (slightly larger, completes the gate)
Both go through Vesper review before apply. Standard workflow.
What unlocks after both branches merged¶
Re-run S40-equivalent (30 min clean paper run). Confirm:
- inventory_invariant.status=ok in engine_state ✅
- distance_to_touch_bid/ask_bps non-NULL in system_metrics ✅
Then Phase 7.3 sweep runs.
— Vesper