Skip to content

Orion → Vesper, Atlas, Katja — FLAG-031 landed

When: 2026-04-17 From: Orion Subject: Six-commit sequence green. Branch feat/flag-031-basis-model ready. Awaiting push from Katja's terminal.


Summary

All six commits from the approved plan shipped on feat/flag-031-basis-model, stacked on fix/flag-030-capital-overlay @ 37692b0. Nothing touched main.

132 / 132 FLAG-031 tests pass. Full suite shows the same FLAG-016 pre-existing failure pattern (73 fewer failures than baseline, 53 new passing tests — all mine). No new regressions.

Commits

SHA Subject Tests added
483b0c1 flag-031: add basis_delta_rlusd column migration 4
3560aa0 flag-031: classify_withdrawal_basis pure function 9
9731b19 flag-031: accept basis_commit in record_capital_event 17
56b1e59 flag-031: get_net_basis_rlusd read-path 9
d3c67fe flag-031: inject_capital.py with atomic RLUSD injection 8
b157dc4 flag-031: write_synthetic_initial_basis.py one-shot migration 8

All commits stacked cleanly. Will rebase onto main without conflict once FLAG-030 is merged.

Design notes vs. the plan

Two small adjustments worth calling out — neither changes the contract, both noted here for audit traceability.

1. Atomicity lives on StateManager, not in the script.

I considered two paths for the two-write atomicity in inject_capital.py: (a) have the script manage the transaction inline, calling low-level SQL, or (b) add StateManager.inject_rlusd_capital_atomic() that wraps both writes in one _transaction. I took (b). The transaction boundary belongs to StateManager — exposing raw SQL to the script would split ownership of the "what must be atomic" rule across two files. The script is now a thin CLI over the method. Forced-failure test injects a wrapper around the connection and confirms the rollback invariant.

2. Basis-commit with basis_delta = 0.

Per Vesper Q3: allow it. I allow it in validation, but the amount > 0 rule (FLAG-008 pattern, unchanged) implies |basis_delta| > 0 as well. In practice the smallest legitimate marker is basis_delta = 1e-9; a literal 0 row is rejected by the amount rule. Flagging it because the test case test_basis_commit_zero_delta_is_allowed uses 1e-9 rather than 0. If you want a literal-zero marker accepted, I'd have to relax amount > 0 to amount >= 0 for basis_commit only, which I can do as a one-line follow-up.

3. FLAG-008 tests updated for the extended contract.

Two FLAG-008 tests in test_inventory_manager.py needed touch-ups: - test_rejects_invalid_event_type: FLAG-031 now owns the valid-event-type list (it added basis_commit), so the error tag moved from [FLAG-008] to [FLAG-031]. Test updated, comment explains why. - test_accepts_valid_withdrawal: withdrawals now require a caller-supplied basis_delta_rlusd. Test passes basis_delta_rlusd=-amount to model a pure-principal withdrawal.

FLAG-008's underlying invariant ("bad rows cannot reach disk") still holds; only the ownership tag changed on one of the checks.

Key invariants confirmed in tests

  • Atomicity: forced failure in the INSERT INTO engine_state step after the capital_events INSERT executes → both writes roll back. capital_events COUNT returns to 0, engine_state returns to its pre-transaction value. (test_engine_state_failure_rolls_back_capital_event)
  • basis_commit balance-neutrality: get_capital_delta_total excludes basis_commit on both assets. Synthetic row contributes to net_basis but not to any FLAG-030 overlay. (test_synthetic_row_does_not_affect_capital_delta_total)
  • NULL-safe read-path: get_net_basis_rlusd() treats pre-migration rows with NULL basis_delta_rlusd as 0.0 via COALESCE. (test_null_basis_delta_on_pre_migration_row_coalesces_to_zero)
  • Idempotency of synthetic backfill: running write_synthetic_initial_basis.py twice yields one row. Dry-run reports the existing-row message too. (test_second_run_is_noop_and_exits_zero)
  • Dry-run is truly read-only: SHA-256 of the DB file unchanged after inject_capital.py --dry-run. (test_dry_run_does_not_mutate_db)

How to use the scripts

Synthetic backfill (historical):

python scripts/write_synthetic_initial_basis.py --db neo_live_stage1.db \
    --amount 137.284078 --dry-run
# If the dry-run output looks right:
python scripts/write_synthetic_initial_basis.py --db neo_live_stage1.db \
    --amount 137.284078

Live injection (post-synthetic):

python scripts/inject_capital.py --db neo_live_stage1.db --amount 50 --dry-run
# Verify the FLAG-032 invariants (below), then:
python scripts/inject_capital.py --db neo_live_stage1.db --amount 50 \
    --source-note manual_injection_20260418 --tx-hash <hash>

Still needed before Katja injects $50

Per the FLAG-032 pre-injection gate — these are verification steps only, no code changes:

  1. Copy neo_live_stage1.db to a dry-run DB (e.g. /tmp/neo_inject_dryrun.db).
  2. Run write_synthetic_initial_basis.py --amount 137.284078 on the copy. Confirm one new basis_commit row.
  3. Run inject_capital.py --amount 50 --dry-run on the copy and assert:
  4. net_basis_before = 137.284078, net_basis_after = 187.284078 (delta = +50)
  5. paper.pnl_starting_value_rlusd (before) = <current>, ... (after) = <current + 50>
  6. Take pre/post dashboard snapshots of NET DEPOSITS, TOTAL VALUE, TOTAL PNL, TRADING VALUE on the copy after inject_capital.py runs for real. Confirm the four FLAG-032 invariants:
    Δ NET DEPOSITS  = +50   ✓
    Δ TOTAL VALUE   = +50   ✓
    Δ TOTAL PNL     =  0    ✓
    Δ TRADING VALUE =  0    ✓
    
  7. If all four pass: inject for real on neo_live_stage1.db. If any fail: stop, report numbers.

I can run steps 1–4 end-to-end against a DB copy on Katja's call — just need the live DB mounted or a recent snapshot path.

Push

No GitHub credentials in my sandbox. Branch feat/flag-031-basis-model exists in the local repo at /sessions/peaceful-admiring-allen/mnt/neo-2026. When ready:

cd ~/neo-2026
git fetch
git push origin feat/flag-031-basis-model

PR target: whichever base you prefer — will rebase cleanly onto main once FLAG-030 lands there.

Files changed (vs. FLAG-030): neo_engine/state_manager.py, tests/test_state_manager.py, tests/test_inventory_manager.py (2 FLAG-008 test touch-ups), scripts/inject_capital.py, scripts/write_synthetic_initial_basis.py, scripts/__init__.py, tests/test_inject_capital.py, tests/test_write_synthetic_initial_basis.py. Total: ~1,578 insertions, 32 deletions.

— Orion