Skip to content

Orion Delivery — D2 feat/wallet-truth-reconciliation

To: Vesper From: Orion Date: 2026-04-19 Branch: feat/wallet-truth-reconciliation Commits: 7 (910f765 → 826209a) Scope: FLAG-036 (D2) — on-chain wallet truth reconciliation + DEGRADED mode + realignment tool Status: Ready for review. All 16 tests green. Patch bundle attached.


Summary

D2 closes the core invariant gap exposed by the S33–S39 wallet drain investigation: engine state could silently diverge from on-chain reality by 43.87 XRP because there was no runtime proof of alignment. This branch adds the proof, the response machinery when proof fails, and the manual correction path when the engine must be brought back in line.

Per Atlas-locked invariant (2026-04-19): engine state must never diverge from on-chain truth beyond tolerance. If the engine cannot prove alignment with reality, it does not act.

Three surfaces land here:

  1. Continuous proofInventoryTruthChecker compares on-chain XRP + RLUSD balances against the engine's internal balances on a fixed cadence, classifies the delta as OK / WARN / HALT, and persists every snapshot.
  2. Response machinery — new DEGRADED engine state (cancel all, stop quoting, keep reconciling, recoverable without restart) plus pre-trade gate in submit_intent that refuses to place orders while truth is not green.
  3. Manual correctiontools/realign_inventory_to_onchain.py with new realignment event type in capital_events so the engine's internal balance can be brought back to on-chain truth without perturbing basis (FLAG-031) or deposits (FLAG-030) accounting.

Commit-by-commit

C1 — 910f765 feat(db): schema + config

  • New table inventory_truth_snapshots (checked_at, on-chain XRP/RLUSD, internal XRP/RLUSD, deltas, status, unverified_counter, note).
  • New config block wallet_reconciliation with keys: enabled, check_interval_ticks, warn_threshold_xrp, halt_threshold_xrp, warn_threshold_rlusd, halt_threshold_rlusd, unverified_halt_after_ticks, degraded_recheck_interval_ticks.
  • config.example.yaml extended with documented defaults.

C2 — 47e0cda feat(truth): core module

  • neo_engine/inventory_truth_checker.py — 406 lines, dependency-injected (fetch_xrp_balance, fetch_rlusd_balance, get_internal_balances, persist_snapshot, set_engine_state, now_iso).
  • Strict wrappers get_on_chain_xrp_balance / get_on_chain_rlusd_balance on XRPLGateway — raise rather than returning stale/zero on RPC failure.
  • Unverified counter resets to 0 on any successful check (Vesper Ruling 2).
  • Classification is per-asset-then-combine: HALT if either hits halt threshold, WARN if either hits warn.

C3 — 316a96b feat(halt): DEGRADED state machine

  • EngineStatus.DEGRADED added to models + state_manager halt_reason plumbing.
  • Mode transitions: RUNNING → DEGRADED on WARN; DEGRADED → RUNNING on next OK; DEGRADED/RUNNING → HALTED on HALT or unverified escalation.
  • halt_reason='inventory_truth' threaded through to shutdown path.

C4 — db21372 feat(engine): startup/runtime/shutdown wiring

  • Startup check: refuses to start if truth is not OK (unless --force-start override, logged as FLAG-036 override).
  • Runtime check: every check_interval_ticks in main loop.
  • Shutdown check: one final snapshot persisted at session close so the last recorded truth is always a real measurement, not a stale tick.
  • engine_state keys populated: inventory_truth_status, inventory_truth_delta_xrp, inventory_truth_delta_rlusd, inventory_truth_unverified_counter, inventory_truth_last_checked_at.

C5 — d5a5650 feat(execution): pre-trade gate

  • submit_intent reads engine_state['inventory_truth_status'] before every order submission.
  • Gate: only OK permits placement. WARN/DEGRADED/HALT/missing → refuse with structured TruthGateRefused result, counter increments on execution_engine.truth_refusals.
  • Does NOT rely on halt signal alone — independent check prevents race between classifier firing and halt manager tearing down.

C6 — 6f495e5 feat(tools): realignment CLI + event type

  • New event_type='realignment' in capital_events — the ONLY event type permitted to carry a signed amount (FLAG-008 carve-out, documented inline).
  • Guarantees: basis_delta_rlusd locked to 0.0, XRP requires positive finite price_rlusd, RLUSD must not carry price_rlusd.
  • get_net_basis_rlusd and get_net_deposits_rlusd unchanged — FLAG-031 invariants preserved.
  • get_capital_delta_total aggregation extends CASE with WHEN event_type='realignment' THEN amount so balance overlay reflects the correction.
  • _rebuild_wac explicitly skips realignment events (FLAG-040 deferred — no cost basis to attribute).
  • tools/realign_inventory_to_onchain.py — dry-run default, --confirm required for writes, --db / --config / --source-note / --session-tag / --price-rlusd flags.
  • Active-session lock: refuses with exit code 2 if engine_status='RUNNING'. DB-based lock survives machine reboots.
  • Two-row writes wrapped in a single _transaction(state._conn) — atomic, no partial-write possible.

C7 — 826209a test(flag-036): 16-test suite

  • Part A (10): InventoryTruthChecker — classification, unverified escalation, counter reset, snapshot+engine_state side effects, persister-raise non-propagation.
  • Part B (3): record_capital_event with realignment — signed amount accepted, validation rejections, no perturbation of basis/deposits.
  • Part C (3): CLI tool — active-session lock, dry-run no-op, --confirm exact-row write.
  • All 16 pass in 0.36s. No production code touched in C7.

Files changed

 config/config.example.yaml                         |  22 +
 neo_engine/config.py                               | 115 ++++-
 neo_engine/execution_engine.py                     | 110 ++++
 neo_engine/inventory_manager.py                    |   9 +
 neo_engine/inventory_truth_checker.py              | 406 +++++++++++++++
 neo_engine/main_loop.py                            | 494 +++++++++++++++++-
 neo_engine/state_manager.py                        | 185 ++++++-
 neo_engine/xrpl_gateway.py                         |  44 ++
 tests/test_flag_036_wallet_truth_reconciliation.py | 553 +++++++++++++++++++++
 tools/realign_inventory_to_onchain.py              | 421 ++++++++++++++++
 10 files changed, 2338 insertions(+), 21 deletions(-)

Open questions for Vesper

  1. Startup override flag naming — C4 uses --force-start as the escape hatch for when truth is not OK at boot. Want to rename to --accept-truth-divergence to make the override intent explicit in session logs, or keep short?
  2. DEGRADED recheck cadence — default is degraded_recheck_interval_ticks=1 (every tick). Fine for short paper sessions; may be excessive for long livenet runs. OK to ship default, tune later?
  3. Pre-trade gate log verbosity — every refusal emits a WARNING with delta values. Under sustained DEGRADED mode this could flood logs. Want rate-limiting (e.g. log first refusal + every 100th) or leave loud for now?
  4. FLAG-040 sequencing — realignment is explicitly skipped in _rebuild_wac. When we pick up FLAG-040, do we backfill WAC for any realignment rows written in the meantime, or leave them as historical "basis-neutral" markers forever?

Apply instructions (Windows)

Patches are in 02 Projects/NEO Trading Engine/patches/feat-wallet-truth-reconciliation/ (7 files, numbered 0001–0007).

From C:\Users\Katja\Documents\NEO GitHub\neo-2026\:

git checkout -b feat/wallet-truth-reconciliation main
git am "C:\Users\Katja\Documents\Claude Homebase Neo\02 Projects\NEO Trading Engine\patches\feat-wallet-truth-reconciliation\*.patch"
python -m pytest tests/test_flag_036_wallet_truth_reconciliation.py -v

Expected: 16 passed in ~0.4s. Merge to main after Vesper review.


What's NOT in this branch (intentionally deferred)

  • FLAG-037 fix/reconciler-disappeared-order-conservative — phantom-fill heuristic root cause. Next branch per Atlas priority order.
  • FLAG-040 proper WAC treatment of realignment deltas — deferred by design. Realignment rows are currently basis-neutral in the WAC rebuild.
  • Anchor saturation guard / corridor guard / drift guard — Phase 7.3 pre-gate items, separate branches.

— Orion 2026-04-19, Phase 7.3 gate 2 of 7