Vesper Ruling — Wallet Truth Reconciliation D2 Blockers¶
To: Orion (he/him) From: Vesper (she/her) CC: Atlas, Katja (Captain) Date: 2026-04-19 Re: D1 accepted. Rulings on four blocking questions. D2 green light at end.
D1 Accepted¶
Root cause is confirmed and reproduced to within rounding. The structural framing is correct: one cold-start read, never refreshed. Primary driver: reconciler phantom-fill heuristic. Secondary: zero-qty fill dust. The 7.40 XRP gap reconstructed exactly from first principles. Accepted without further questions.
Ruling 1 — Threshold Defaults¶
Use the spec defaults. Do not tighten.
WARN: |delta_xrp| > 1.0 OR |delta_total_rlusd| > 2.0
HALT: |delta_xrp| > 5.0 OR |delta_total_rlusd| > 10.0
Reasoning: these thresholds are for detecting NEW divergence after the baseline is corrected. The phantom-fill bug accumulated 6.71 XRP across S1–S32 (~750 fills, ~0.009 XRP per fill average). At 1.0 XRP warn, a new drift episode would be flagged within roughly the first 100 fills — early enough to catch before it compounds. Tightening to 0.5 / 2.0 risks alert fatigue from normal rounding and node-snapshot variance on a small portfolio. Spec defaults stand.
Both WARN and HALT thresholds must be config-tunable per the spec (warn_delta_xrp, halt_delta_xrp, etc.). We can tighten in production once we have data on normal variance.
Ruling 2 — API Failure Policy¶
unverified_halt_count = 3 is the production value.
Reasoning: account_info RPC is indeed reliable on standard XRPL public nodes. Three consecutive failures means something is genuinely wrong with connectivity or the node, not transient jitter. A single failure sets status = unverified and logs ERROR but does not halt. Two failures in a row escalate logging. Three triggers halt.
One important addition to the spec: the three-consecutive-failure counter must reset on any successful verification. A transient blip followed by recovery should not accumulate toward halt. Implement as consecutive_unverified_count that resets to zero on status = ok or status = warn.
Ruling 3 — Backfill Strategy for the Existing 43.87 XRP Gap¶
The branch must ship with a one-shot realignment tool. Manual DB edits are not acceptable.
When feat/wallet-truth-reconciliation lands and the first startup truth check runs, it will see the 43.87 XRP gap and halt immediately. This is correct behavior. But we need a clear, auditable remediation path — not manual SQL.
Required: tools/realign_inventory_to_onchain.py
This standalone script (not part of the engine runtime) must:
- Connect to
neo_engine.dband the XRPL node (reads config from standard config file) - Fetch on-chain
account_info.Balance(XRP) andaccount_lines(RLUSD) — live query - Compute internal engine balance the same way
rebuild()would:fills_only_ledger_tip + capital_overlay - Print a dry-run summary:
- Require explicit
--confirmflag to proceed - On confirm: write a
capital_eventsrow withevent_type='realignment',asset='XRP',amount=-43.87, a comment field noting this is a one-time inventory reconciliation to on-chain truth - Log clearly to stdout and to a timestamped file in
logs/
After running the tool, the engine's next rebuild() will incorporate the realignment entry in the capital overlay, making internal state match on-chain. The startup truth check will then pass.
The tool must NOT be runnable while the engine is live. Add a lock check: if engine_state contains an active session (started_at but no ended_at), refuse with an error.
WAC implications (Q4 preempts here): after the realignment entry is written, WAC will still be wrong until the phantom-fill fix lands. That is acceptable — WAC is a display metric, not a safety gate. The truth check does not use WAC.
Ruling 4 — WAC Correction¶
Out of scope for feat/wallet-truth-reconciliation. Flagged separately.
The WAC distortion is real: _rebuild_wac replays from fills, which includes phantom fills. Fixing WAC correctly requires first eliminating the phantom-fill source (FLAG-037 / fix/reconciler-disappeared-order-conservative). Once that branch lands, a WAC rebuild pass can follow. Attempting WAC correction before the phantom-fill source is patched would produce a corrected-but-still-drifting WAC.
This is filed as FLAG-040. Not a gate for D2.
D2 Green Light¶
All four blockers are ruled. Orion is cleared to start feat/wallet-truth-reconciliation.
Scope is exactly as specified in the tasking, with these addenda:
consecutive_unverified_countresets on successful verification (Ruling 2)tools/realign_inventory_to_onchain.pymust ship as part of this branch (Ruling 3)- WAC correction is explicitly out of scope (Ruling 4)
- Thresholds per spec defaults (Ruling 1)
Deliver in standard format. Vesper reviews before merge.
Reminder: the phantom-fill root cause (ledger_reconciler.py:675–687) is intentionally NOT in this branch. The detector lands first. The fix to what the detector will catch lands in fix/reconciler-disappeared-order-conservative (FLAG-037). That sequence is correct.
— Vesper