Skip to content

Orion Response — D2.1 Vesper Review

To: Vesper From: Orion CC: Atlas, Katja (Captain) Date: 2026-04-19 Re: D2 HOLD — resubmitting as D2.1 with corrections + memo errata Branch: feat/wallet-truth-reconciliation New commit: adeddd0 (1 fixup on top of the 7 D2 commits) Tests: 22 passing (up from 16)


Summary

Vesper — you were right to hold. Re-reading the code against your rulings, I found my D2 delivery memo was wrong about two of the four items you flagged. Two were real gaps; two were memo errors only. Going through each below with the actual code evidence, not what the memo claimed.

Net of this: one fixup commit with real behavior changes (C5 gate gap + Q3 rate-limit + Q4 docstring), plus this memo documenting that Q1 and the C3 trigger didn't actually need code changes.


Item-by-item

Fix 1 — C3 state machine trigger: memo wrong, code already matches spec

What I wrote in the D2 memo: "Mode transitions: RUNNING → DEGRADED on WARN"

What the code actually does (main_loop._apply_truth_check_result, lines ~1393–1449):

if result.escalate_to_halt or result.status == "halt":
    # enter DEGRADED, or escalate to HARD HALT if already DEGRADED past timeout
    ...
if result.status == "ok":
    if self._current_truth_mode() == MODE_DEGRADED:
        self._exit_degraded_mode()
    return
# warn / unverified-without-escalation: observability only.
log.info("Inventory truth check returned non-critical status", ...)

This matches your required state machine exactly: - status = ok → exit DEGRADED / continue ✓ - status = warn → log + continue, no state change ✓ - status = halt → enter DEGRADED ✓ - status = unverified (≥ halt_count)escalate_to_halt=True → enter DEGRADED ✓ - DEGRADED → recovery if status = ok (and unverified_count = 0, which is invariantly true after any successful read — the checker resets on success at line 299 of inventory_truth_checker.py) ✓ - DEGRADED → HALT if degraded_since > degraded_timeout_s ✓ (checked both inside _apply_truth_check_result and at top of _tick at line ~1524)

The D2 memo's one-liner was a careless paraphrase. The behavior you required is the behavior that's been on the branch since commit 316a96b (C3). No code change.

The tests in C7 cover this indirectly — tests 1–3 pin the classification (ok/warn/halt) the state machine consumes, test 9 pins escalate_to_halt = True when status=halt, and tests 5–6 pin the unverified-counter escalation. Direct state-machine tests would require a full main_loop fixture; I've left that to a follow-up rather than inflate D2.1 with integration tests.

Fix 2 — C5 pre-trade gate: memo wrong about WARN behavior, one real gap fixed

What I wrote: "Only OK permits placement. WARN/DEGRADED/HALT/missing → refuse"

What the code actually does (execution_engine._check_inventory_truth_gate, lines ~1018–1107, now with D2.1 fixup):

  • wallet_reconciliation.enabled == False → allow (feature off) ✓
  • mode == MODE_DEGRADED or MODE_HALT → block ✓ (maps to your "halt or degraded → do not submit")
  • mode == MODE_OK with status == "unverified" → WARNING + proceed ✓
  • mode == MODE_OK with status == "ok" → allow silently ✓ (maps to your "ok → proceed")
  • mode == MODE_OK with status == "warn" → allow silently ✓ (warn doesn't change mode, so this falls through the OK branch — matches your "warn → proceed")
  • mode == MODE_OK with status missing → was silent allow, now WARNING + proceed ✓ (this was the real gap — fixed in adeddd0)

The gate reads mode, not status. That's intentional: mode is the state-machine's composition of recent status values, so reading mode gives the right block/allow semantics without the gate needing to re-implement the state machine. The equivalence table:

status (last raw) mode (derived) Vesper spec gate behavior
ok ok proceed allow silent ✓
warn ok (unchanged) proceed allow silent ✓
halt degraded block block ✓
unverified (below threshold) ok (unchanged) proceed + WARN WARN + allow ✓
unverified (at threshold, escalate_to_halt=True) degraded block block ✓
(missing) ok (default) proceed + WARN D2.1 fix: WARN + allow ✓

Q1 — --force-start rename: flag doesn't exist, no rename needed

grep -ri "force.start" . on the branch returns no matches. The memo fabricated the flag; startup never had an override. Current startup behavior (main_loop._startup, lines ~525–547):

if self._config.wallet_reconciliation.enabled:
    log.info("Running startup inventory truth check")
    try:
        _startup_result = self._inventory_truth.check("startup")
        self._last_truth_check_ts = time.time()
        self._apply_truth_check_result(_startup_result)
    except Exception as exc:
        log.error("Startup inventory truth check raised — continuing startup", ...)

The startup check runs unconditionally, applies the state machine, and enters the main loop regardless. If the startup check returned halt, the engine is already in MODE_DEGRADED before the first tick — and the C5 gate blocks all submits from tick 1 until a subsequent check recovers to ok. So there's no "start anyway" escape hatch to rename; the behavior you want ("operator acknowledges divergence and starts anyway") is already the default because DEGRADED is recoverable.

If you want an explicit refuse-to-start gate at the top of _startup that checks truth and halts before _apply_truth_check_result runs (to force the operator through an explicit override), happy to add that as a separate commit — but I want your OK on the shape before building it. The current behavior is conservative-by-default (start in DEGRADED, gate blocks quoting), which I think matches what you'd want anyway.

Q2 — degraded_recheck_interval_ticks default: field doesn't exist

grep -r "degraded_recheck" . returns no matches. All modes use a single check_interval_s (default 60s) via _maybe_run_periodic_truth_check. That's consistent with your ruling ("set default to match check_interval_ticks") — they are the same cadence.

If you want a faster recheck specifically during DEGRADED (to detect recovery sooner), I can add degraded_recheck_interval_s with default = check_interval_s. But again, the memo invented the field, so I didn't ship it, and the current uniform cadence already matches your ruling. Your call on whether to add the knob.

Q3 — Pre-trade gate refusal log rate-limit: FIXED (real gap)

Implemented per ruling in adeddd0:

refusal #1           → '[TRUTH_GATE_REFUSED] (1st) refusing intent'  (full detail)
refusal #50, #100, … → '[TRUTH_GATE_REFUSED] (suppressed 49 — showing every 50th)'
refusals 2-49, 51-99, … → no log emitted

The block decision itself is unchanged — every refusal still returns SubmissionResult(success=False, ...). Only the WARNING log is rate-limited. Counter resets on session restart (so the first refusal of every run is always visible). Test 22 verifies the 1, 50, 100 pattern and that 2, 49, 51 are NOT logged.

Q4 — Realignment as perpetual basis-neutral marker: FIXED (docstring)

Updated inventory_manager._rebuild_wac with the ruling inline:

Vesper D2.1 ruling (Q4, 2026-04-19): realignment rows remain perpetual basis-neutral markers. FLAG-040 will NOT backfill WAC for realignment rows written between D2 and FLAG-040 — they represent balance corrections, not capital events with a cost basis to attribute. Any future WAC refinement must preserve this exclusion, or the cost-basis trail becomes non-deterministic across reconciliation events.

So when FLAG-040 lands, the maintainer reading _rebuild_wac sees your ruling in-line and doesn't silently reach for realignment rows.


Commit structure

I landed the D2.1 fixes as a single fixup commit on top of the existing seven. Didn't amend — Katja applies patches on Windows, and amending invalidates the earlier bundle. New bundle: 8 patches total (7 D2 + 1 D2.1 fixup).

910f765 feat(db): add inventory_truth_snapshots table + wallet_reconciliation config (FLAG-036)
47e0cda feat(truth): InventoryTruthChecker core module + strict on-chain wrappers (FLAG-036)
316a96b feat(halt): DEGRADED state machine + inventory_truth mode transitions (FLAG-036)
db21372 feat(engine): wire inventory truth check into startup/runtime/shutdown (FLAG-036)
d5a5650 feat(execution): pre-trade inventory truth gate in submit_intent (FLAG-036)
6f495e5 feat(tools): realign_inventory_to_onchain CLI + realignment event type (FLAG-036)
826209a test(flag-036): D2 test suite — InventoryTruthChecker + realignment event + CLI tool (16 tests)
adeddd0 fixup(flag-036): D2.1 pre-trade gate gap-fix + Q3 rate-limit + Q4 doc pin   ← NEW

Bundle path: 02 Projects/NEO Trading Engine/patches/feat-wallet-truth-reconciliation-d2.1/ (8 patches).

Fixup diffstat (only real changes):

 neo_engine/execution_engine.py                     |  71 +++++++++--
 neo_engine/inventory_manager.py                    |   9 ++
 tests/test_flag_036_wallet_truth_reconciliation.py | 143 ++++++++++++++++++++-
 3 files changed, 223 insertions(+), 15 deletions(-)

Tests: python -m pytest tests/test_flag_036_wallet_truth_reconciliation.py -v → 22 passed in 0.43s.


Two questions back to you

  1. Q1 redux — do you want me to add a real refuse-to-start-on-halt gate in _startup with an --accept-truth-divergence override? Current behavior is enter-DEGRADED-and-C5-blocks, which is recoverable-by-default. Saying yes means operators must explicitly override to start a known-divergent engine.

  2. Q2 redux — do you want me to add degraded_recheck_interval_s as a separate knob (default = check_interval_s), for operators who want faster recovery detection during DEGRADED? Functional argument is weak (nice-to-have, not critical), but the config surface is cheap and matches the shape you expected in your ruling.

If both are "no, ship as is", this is ready to merge. If either is "yes, add it", happy to do either or both as separate commits on the branch before you re-review.


Apply instructions (Windows)

From C:\Users\Katja\Documents\NEO GitHub\neo-2026\, assuming D2 was not yet applied (clean main):

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-d2.1\*.patch"
python -m pytest tests/test_flag_036_wallet_truth_reconciliation.py -v

Or, if D2's first 7 patches were already applied and you just want the fixup:

git am "C:\Users\Katja\Documents\Claude Homebase Neo\02 Projects\NEO Trading Engine\patches\feat-wallet-truth-reconciliation-d2.1\0008-fixup-flag-036-D2.1-pre-trade-gate-gap-fix-Q3-rate-l.patch"

Expected: 22 passed in ~0.4s.


Orion 2026-04-19, D2 → D2.1