Skip to content

SUPERSEDED — DO NOT ACTION. This tasking was based on an incorrect diagnosis (DEGRADED cancel path missing FLAG-047 detection). Diagnosis was corrected after code review. The actual root cause is a truth-check timing race. Vesper has delivered the correct fix. See [C] Atlas-Orion Briefing — S54 Root Cause, FLAG-052 Fix, FLAG-051 Summary.md for the full corrected analysis. Orion is on hold for FLAG-052. branch: fix/degraded-cancel-race priority: HIGH — S55 blocked


FLAG-052 — DEGRADED Entry Cancel Path Missing Cancel-Fill Race Detection

What happened

S54 halted via inventory_truth_halt at ~02:04 UTC. The sequence:

  1. Engine entered DEGRADED
  2. Fired "Degraded entry cancel" on active buy order (sequence ~103476262)
  3. That order had already been filled on-chain before the cancel arrived
  4. XRPL returned tecNO_TARGET
  5. Engine recorded order as CANCELLED_BY_ENGINE
  6. RECONCILER_SKIP_ENGINE_CANCEL suppressed fill recognition on subsequent ticks
  7. Truth check saw: delta_xrp = −13.646, delta_rlusd = +19.5inventory_truth_halt

Actual fill: ~13.65 XRP bought, ~19.5 RLUSD paid (~1.429 RLUSD/XRP). Capital was flat. The halt was spurious — caused by the engine not recognizing its own fill.

Root cause

FLAG-047 added tecNO_TARGETCANCEL_RACE_UNKNOWNaccount_tx on-chain lookup on the atomic replace cancel path only.

The DEGRADED entry cancel path — wherever _cancel_all_orders() (or equivalent) is called when the engine enters DEGRADED state — was NOT covered by FLAG-047's fix.

Same race condition. Different call site.

Required fix

Extend FLAG-047's cancel-fill race detection to the DEGRADED entry cancel path.

When a DEGRADED entry cancel returns tecNO_TARGET: - Demote order to CANCEL_RACE_UNKNOWN (same as atomic replace path) - Query on-chain via get_account_tx_for_offer (existing gateway method from FLAG-047) - Three-way resolution: - FILL → record atomically via mark_filled_after_race; do NOT mark CANCELLED_BY_ENGINE - CANCEL → terminal (landed, order gone) - INCONCLUSIVE → fail-closed; flag for manual review (do not suppress reconciler)

Do NOT mark an order CANCELLED_BY_ENGINE until on-chain resolution confirms the cancel landed.

Where to look

The atomic replace path fix (FLAG-047) is in: - Cancel response handling in the XRPL gateway (look for tecNO_TARGET handling added in fix/cancel-fill-race) - mark_filled_after_race atomic method in reconciler - get_account_tx_for_offer gateway method

Find the DEGRADED entry cancel call site — likely in state manager or main loop, wherever cancel_all_orders / cancel_for_degraded is invoked on DEGRADED entry. Apply the same tecNO_TARGET handling there.

Tests required

Minimum: 1. DEGRADED entry cancel returns tecNO_TARGET → FILL resolution → fill recorded, no CANCELLED_BY_ENGINE, no truth halt 2. DEGRADED entry cancel returns tecNO_TARGET → CANCEL resolution → order terminal, no phantom fill 3. DEGRADED entry cancel returns tecNO_TARGET → INCONCLUSIVE → fail-closed, not suppressed 4. DEGRADED entry cancel returns success (normal path) → unaffected

Existing FLAG-047 tests should continue to pass.

Delivery

Branch: fix/degraded-cancel-race
Apply instructions: standard git am patch bundle to C:\Users\Katja\Documents\Claude Homebase Neo\02 Projects\NEO Trading Engine\08 Patches\
Apply path: C:\Users\Katja\Documents\NEO GitHub\neo-2026\

Branching rules (standing): - Do NOT pre-create the branch during investigation - Use Get-ChildItem ... -Filter "*.patch" | Sort-Object Name | ForEach-Object { git am $_.FullName } form (no glob in PowerShell) - Include git branch -D fix/degraded-cancel-race before git checkout -b fix/degraded-cancel-race in apply instructions

— Vesper