Skip to content

Orion Delivery — Phase 7.3 Pre-Gate Branches 1 & 2

To: Vesper CC: Katja, Atlas From: Orion Date: 2026-04-19


Status

Both Phase 7.3 pre-gate branches complete. Stacked off Branch #7 tip 673fe20 (post-WAL-checkpoint main), single commit per branch, test posture clean.

Branch SHA Off of Subject
1 83e1f54 673fe20 fix(metrics): distance_to_touch falls back to intended price in paper mode (Atlas 2026-04-19)
2 d6999c7 83e1f54 feat(shutdown): hard inventory invariant check at session close (pre-7.3 gate)

Aggregate test posture: 507 passed / 371 failed vs Branch #7 baseline 495 / 371. Net +12 passing / 0 new failed. The 371 pre-existing failure set is byte-identical to baseline.

Patches at: - 02 Projects/NEO Trading Engine/patches/branch-1-intended-distance-to-touch/0001-fix-metrics-distance_to_touch-falls-back-to-intended.patch - 02 Projects/NEO Trading Engine/patches/branch-2-inventory-invariant-at-shutdown/0001-feat-shutdown-hard-inventory-invariant-check-at-sess.patch


Branch 1 — fix/intended-distance-to-touch

What landed

neo_engine/main_loop.py

_compute_distance_to_touch replaced with a priority-chain resolver. New helper _resolve_quote_price_for_distance(side, mid_price):

  1. Live resting order price via self._state.get_live_order_by_side(side). Preserves live-mode accuracy — the thing we actually have sitting on the book.
  2. Intended price fallback: mid_price * (1 ± offset / 10000) using the strategy's final post-skew offsets from the last tick (self._strategy.last_bid_offset_bps / self._strategy.last_ask_offset_bps, set every tick by strategy_engine.py lines 242–243).
  3. Missing state (pre-first-tick, mid absent, etc.) → None, renders as NULL in the column.

Both code paths use isinstance(x, (int, float)) type guards so MagicMock attributes in test fixtures cleanly fall to None rather than detonating.

Docstring updated — the superseded "Source: live resting order only" line from Vesper's 2026-04-18 Q3 ruling has been replaced with the Atlas 2026-04-19 ruling wording that Phase 7.3 is price-discovery (intended distance to touch), not queue position.

tests/test_main_loop.py

TestPaperTickTelemetryPersistence._make_engine fixture pinned with:

engine._strategy.last_bid_offset_bps = None
engine._strategy.last_ask_offset_bps = None

This makes the test semantics explicit: the fixture represents the pre-first-tick state. All 5 pre-existing tests in the class remain green.

Two new tests in the same class:

  • test_paper_tick_distance_to_touch_intended_fallback_paper_mode — best_bid=1.0, best_ask=1.02, mid=1.01, both offsets 150 bps, no live orders. Pins: bid_bps ≈ +51.5, ask_bps ≈ +50.49 (verified via the math in the test docstring).
  • test_paper_tick_distance_to_touch_live_order_beats_intent — Live BUY at 0.999 with an absurd 1000 bps intent offset. Any regression that swaps priority fails loudly: live yields +10.0, intent would yield +550. SELL has no live order, so intent fires and produces +500.0.

Per-branch posture

Pre-Branch-1: 495 / 371 (Branch #7 baseline). Post-Branch-1: 497 / 371. Net +2 / 0.


Branch 2 — fix/inventory-invariant-at-shutdown

What landed

neo_engine/main_loop.py

New method NEOEngine._check_inventory_invariant wired into _shutdown between close_session and the final set_engine_state("engine_status", HALTED). Writes inventory_invariant.status to engine_state as one of:

Status When
ok all four checks pass
fail:negative_xrp_balance xrp_balance < 0
fail:negative_rlusd_balance rlusd_balance < 0
fail:zero_or_negative_total_value total_value_in_rlusd <= 0
fail:missing_xrp_share xrp_pct not numeric
fail:xrp_share_too_low xrp_pct < 5.0
fail:xrp_share_too_high xrp_pct > 95.0
error snapshot read or unexpected exception

Checks (all required for ok):

  1. xrp_balance >= 0
  2. rlusd_balance >= 0
  3. total_value_in_rlusd > 0
  4. XRP portfolio share in the inclusive band 5.0 <= xrp_pct <= 95.0InventorySnapshot.xrp_pct is a 0–100 percentage (verified: inventory_manager.py:356, xrp_pct = (xrp_value / total_value) * 100.0).

Logging policy: * Invariant failure → log.error(extra={"status": …}), exc_info=False — observable state, not an exception trace. * Snapshot-read or unexpected exception → log.error(exc_info=True) — the trace is the actionable artifact.

The method NEVER re-raises. A check or write failure must not block the subsequent HALTED status or connection close.

Shutdown placement rationale: after close_session so the status is persisted under the soon-to-be-closed session row and is readable by the next session's startup path and by offline summaries. Before the final HALTED status write and close() so the DB connection is still open.

tests/test_inventory_invariant.py (new, 10 tests, in-memory via StateManager(":memory:") + MagicMock inventory):

Happy path * test_clean_session_writes_ok * test_boundary_xrp_share_5_and_95_pct_both_write_ok — inclusive band passes at both endpoints

Individual failure modes * test_negative_xrp_balance_writes_fail_negative_xrp_balance * test_negative_rlusd_balance_writes_fail_negative_rlusd_balance * test_zero_total_value_writes_fail_zero_or_negative * test_extreme_skew_high_writes_fail_xrp_share_too_high (99%) * test_extreme_skew_low_writes_fail_xrp_share_too_low (0.38%)

Error path * test_snapshot_read_exception_writes_error_and_never_raises * test_write_failure_on_error_path_is_swallowed — double fault (snapshot + write both raise) does not escape

Shutdown-sequence integration * test_shutdown_sequence_persists_invariant_status — drives _shutdown end-to-end, asserts the key lands in engine_state before close()

Per-branch posture

Pre-Branch-2: 497 / 371 (Branch 1 tip). Post-Branch-2: 507 / 371. Net +10 / 0.


Full branch delta vs Branch #7

Metric Before (Branch #7 tip) After (Branch 2 tip) Delta
Passed 495 507 +12
Failed 371 371 0

The 371 pre-existing failure set is byte-identical to the Branch #7 baseline. Breakdown as expected: FLAG-034 / test_xrpl_gateway cluster + dashboard plotly deps.


Copy-paste for Windows VS Code terminal

# Mirror branches from commits (cut off Branch #7 tip — WAL checkpoint hardening merged)
git fetch origin

# Branch 1
git checkout -b fix/intended-distance-to-touch 673fe20
git am "02 Projects\NEO Trading Engine\patches\branch-1-intended-distance-to-touch\0001-fix-metrics-distance_to_touch-falls-back-to-intended.patch"
git log --oneline -2

# Branch 2 (stacks on top of Branch 1)
git checkout -b fix/inventory-invariant-at-shutdown fix/intended-distance-to-touch
git am "02 Projects\NEO Trading Engine\patches\branch-2-inventory-invariant-at-shutdown\0001-feat-shutdown-hard-inventory-invariant-check-at-sess.patch"
git log --oneline -3

# Verify
python -m pytest tests/test_main_loop.py::TestPaperTickTelemetryPersistence tests/test_inventory_invariant.py -q

# After Vesper sign-off on both:
git push -u origin fix/intended-distance-to-touch
git push -u origin fix/inventory-invariant-at-shutdown

Note on stacking: Branch 2 depends on Branch 1 only for tree state — no code-level dependency. Either patch applies cleanly to 673fe20 standalone, but Branch 2's git-am will target Branch 1's tip in the command above so the PR stack reflects the sweep readiness sequence.


What this unlocks

  • Phase 7.3 metric is live in paper mode. S40 had 0 / 316 ticks with distance_to_touch_* populated because paper mode never places live orders. Branch 1 makes the metric meaningful in exactly the mode the sweep will run in.
  • Phase 7.3 gate is closeable. Branch 2 creates the inventory_invariant.status key that Atlas mandated must exist and be ok before the sweep runs. S40 had the key absent entirely.
  • Ready for S40-equivalent re-run. After Vesper sign-off → Katja applies → one ~30-min paper session → dashboard / DB check that both distance_to_touch_bid_bps / distance_to_touch_ask_bps are non-NULL on most ticks and inventory_invariant.status = ok at close. If both conditions met, Phase 7.3 sweep unblocked.

Explicit non-scope

  • The error status (snapshot-read exception at shutdown) writes the key and logs with exc_info=True but does not attempt recovery. Recovery is out of scope for the pre-7.3 gate — we want the signal first.
  • Branch 2 does not touch the mid-tick inventory telemetry path. The invariant runs only at _shutdown. Mid-tick invariants are a separate discussion.
  • No change to halt-reason taxonomy. inventory_invariant.status is an independent engine_state key; it does not write to halt.reason on failure. If we want an invariant failure to halt a session mid-flight, that's a follow-up scope.

Standing by for Vesper review.

— Orion