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:
- Continuous proof —
InventoryTruthCheckercompares 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. - Response machinery — new
DEGRADEDengine state (cancel all, stop quoting, keep reconciling, recoverable without restart) plus pre-trade gate insubmit_intentthat refuses to place orders while truth is not green. - Manual correction —
tools/realign_inventory_to_onchain.pywith newrealignmentevent type incapital_eventsso 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_reconciliationwith 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.yamlextended 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_balanceonXRPLGateway— 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.DEGRADEDadded 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-startoverride, logged as FLAG-036 override). - Runtime check: every
check_interval_ticksin 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_statekeys 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_intentreadsengine_state['inventory_truth_status']before every order submission.- Gate: only
OKpermits placement. WARN/DEGRADED/HALT/missing → refuse with structuredTruthGateRefusedresult, counter increments onexecution_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'incapital_events— the ONLY event type permitted to carry a signed amount (FLAG-008 carve-out, documented inline). - Guarantees:
basis_delta_rlusdlocked to 0.0, XRP requires positive finiteprice_rlusd, RLUSD must not carryprice_rlusd. get_net_basis_rlusdandget_net_deposits_rlusdunchanged — FLAG-031 invariants preserved.get_capital_delta_totalaggregation extendsCASEwithWHEN event_type='realignment' THEN amountso balance overlay reflects the correction._rebuild_wacexplicitly skips realignment events (FLAG-040 deferred — no cost basis to attribute).tools/realign_inventory_to_onchain.py— dry-run default,--confirmrequired for writes,--db / --config / --source-note / --session-tag / --price-rlusdflags.- 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_eventwithrealignment— signed amount accepted, validation rejections, no perturbation of basis/deposits. - Part C (3): CLI tool — active-session lock, dry-run no-op,
--confirmexact-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¶
- Startup override flag naming — C4 uses
--force-startas the escape hatch for when truth is not OK at boot. Want to rename to--accept-truth-divergenceto make the override intent explicit in session logs, or keep short? - 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? - 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?
- 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