Skip to content

[C] Orion Report — FLAG 030 Halted Double Count Discovery

From: Orion (he/him) Date: 2026-04-17

TL;DR

Green light acknowledged. Code + 34 tests green on the branch. Did NOT commit. Live DB inspection proves the "apply ALL capital events unconditionally" rule will add +39.27 XRP and +85.00 RLUSD that are already baked into the current ledger via live.starting_balance_*. That's ~137 RLUSD of phantom inventory on next restart.


The numbers

From /tmp/live_post_s32.db:

capital_events (2 rows, both at 2026-04-13T00:18:19 UTC — pre-engine):

id asset event_type amount price_rlusd source_note
f9588349… XRP deposit 39.27 1.3314 stage1 opening baseline
192fdaae… RLUSD deposit 85.00 stage1 opening baseline

engine_state: - live.starting_balance_xrp = 40.472253 - live.starting_balance_rlusd = 85.56902376775649 - live.balances_seeded = 1

First inventory_ledger row (id=1, created_at 2026-04-13T01:00:30 — ~42 min AFTER capital_events): - XRP row: change +2.9314914, new_balance 43.40374441887616 → implied prior = 40.472253 ✅ matches starting_balance_xrp - RLUSD row: change −3.9, new_balance 81.66902376775649 → implied prior = 85.56902376775649 ✅ matches starting_balance_rlusd

Last inventory_ledger row (id=1504, 2026-04-17T16:29:29): - XRP new_balance: 41.01792720880708 - RLUSD new_balance: 86.22001773779789

Conclusion: live.starting_balance_* was snapshotted from the on-chain wallet at engine startup. That wallet already reflected the two deposit capital_events posted 42 minutes earlier. Since every ledger row is computed from that seed, the current ledger.new_balance already contains those deposits. The overlay would re-add them.


What rebuild() would do on next live restart (as currently implemented)

xrp_fills_only   = get_current_balance(XRP)       = 41.01792720880708   # contains deposit
xrp_overlay      = get_capital_delta_total("XRP")  = +39.27
self._xrp_balance = fills_only + overlay           = 80.28792720880708   # WRONG — +39.27 XRP phantom

rlusd_fills_only = get_current_balance(RLUSD)      = 86.22001773779789   # contains deposit
rlusd_overlay    = get_capital_delta_total("RLUSD") = +85.00
self._rlusd_balance = fills_only + overlay         = 171.22001773779789  # WRONG — +85.00 RLUSD phantom

Phantom notional ≈ 137 RLUSD. Breaks WAC, sizing, needs_seed check, session starting_value, and PnL on first post-FLAG-030 restart.


Why the test suite didn't catch it

All rebuild tests start from empty ledger + no starting_balance seed. The live DB has one condition the tests don't: starting_balance and capital_events both exist, starting_balance is GREATER than the sum of capital_events (pre-existing dust), and the earliest ledger row's implied prior balance = starting_balance. The overlay assumes fills_only is truly fills-only — on this live DB it isn't.


Options

A. One-time data migration — subtract capital_events sum from live.starting_balance_*. Mutates historical truth. Rejected.

B. created_at boundary filter — overlay only capital_events WHERE created_at >= MIN(created_at) FROM inventory_ledger WHERE asset = ?. Pre-engine rows excluded, post-engine rows correctly applied. Edge case: fresh DB → NULL boundary → overlay nothing (explicit fallback, document it).

C. Reclassify the 2 rows — special-case data fix, future bug vector. Rejected.

D. Route ALL capital events through inventory_ledger — correct long-term architecture, out of scope for FLAG-030.

Orion's ranking: B now + D as tech-debt follow-up.


Current state of work

  • FLAG-008: committed 6823484, pushed. Clean.
  • FLAG-030: working tree on main, uncommitted. Files touched: inventory_manager.py, state_manager.py, tests/test_inventory_manager.py (34 tests passing on current spec, wrong spec).

Waiting on decision before touching anything else.

— Orion (he/him)