Snapshot PINK DITAv2 system + Sprint 0 flaw-fix verification

First commit of the previously-untracked PINK-on-DITAv2 migration system
(execution moves to the Rust kernel; policy stays on legacy DITA, so Alpha
Engine algorithmic integrity is preserved). BLUE is untouched.

Sprint 0 (safety snapshot + flaw-fix verification, MARKET single-leg scope):
- Verified Rust FSM fixes (flaws 2,4,10,11,13) by source read of lib.rs.
- Hardened 5 vacuous/guarded assertions in test_flaws.py so each flaw test
  genuinely exercises its fix. Most important: Flaw 5 now asserts capital
  moves by EXACTLY realized PnL (was entering/exiting at the same price).
- Offline suites: 533 passed, 0 failed (35 flaws + 402 kernel/accounting/
  bridge + 96 runtime/persistence/multi-exit/restart/seams).
- GATE PASS: MARKET-path-critical flaws 1,2,5 confirmed fixed + green.
- Added SPRINT0_FLAW_VERIFICATION.md report and _rust_kernel/.gitignore
  (excludes Rust target/ build artifacts).

LIMIT/partial-fill remain explicitly out of scope (MARKET-only bring-up).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-05-30 18:26:43 +02:00
parent 34d01fe6a4
commit 3d7b00e28d
89 changed files with 32782 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
# Sprint 0 — DITAv2 flaw-fix verification report
**Date:** 2026-05-30
**Scope:** Verify (do not re-implement) the DITAv2 flaw fixes before migrating PINK
onto the kernel for BingX testnet (MARKET single-leg first). Source read + offline
MockVenue test execution. No exchange contact.
## Method
- Read the full Rust FSM (`_rust_kernel/src/lib.rs`, 1700 L) and the Python bridge
(`rust_backend.py`) + `account.py` + `mock_venue.py`.
- Hardened previously-vacuous guarded assertions in `test_flaws.py` so each flaw test
genuinely exercises its fix (details below).
- Ran all offline suites under `siloqy_env` with `PYTHONPATH=/mnt/dolphinng5_predict`.
## Offline test results (all green)
| Suite group | Result |
|---|---|
| `test_flaws.py` (hardened) | 35 passed |
| kernel FSM + accounting invariants + kernel bridge + multi-exit contract | 402 passed |
| pink direct-runtime, CH persistence, multi-exit integration/fuzz, restart-reconcile, rate-limit, routing, sync/async seams | 96 passed |
| **Total** | **533 passed, 0 failed** |
(Two benign warnings: `EDAIN normalizer not available` — unrelated import; one
`coroutine never awaited` inside an intentional hang-detection test.)
## Test-hardening performed (removed false-green guards)
1. **Flaw 5 / `test_partial_exit_settles_pnl_incrementally`** — was entering & exiting at
the *same* price (realized_pnl == 0) under a `if slot.realized_pnl != 0.0:` guard, so the
capital assertion never ran. Now: SHORT entry @100, exit @90 → realized PnL strictly
positive, and asserts **capital moved by EXACTLY realized PnL** (`|Δcapital realized| < 1e-9`).
This is the core single-authority invariant and is now unconditional.
2. **Flaw 2 / `test_cancel_ack_exit_still_works`** — exit auto-filled in the default scenario,
so the exit order was already gone (`if slot.active_exit_order is not None:` skipped). Now
uses `exit_partial_fill_ratio=0.5` so the exit order stays live, then asserts CANCEL_ACK
clears it and returns the slot to `POSITION_OPEN`.
3. **Flaw 9 / `test_cancel_uses_slot_asset_not_trade_id`** — guard made unconditional (ACK-only
entry deterministically leaves the entry order live).
4. **Flaw 12 / `test_transitions_count_matches_lifecycle`** — guard made unconditional.
5. **Flaw 13 / `test_pnl_warning_on_unsettled_reentry`**`if slot.is_free():` made unconditional.
## Per-flaw verdict (MARKET single-leg path = Sprint 1)
| Flaw | Severity | Fixed? | Evidence |
|---|---|---|---|
| 1 — entry-order cancel broken | Critical | **FIXED** | `lib.rs` CANCEL branch accepts entry cancel when `active_entry_order` set & state ∈ {ENTRY_WORKING,ORDER_REQUESTED,ORDER_SENT,IDLE}; bridge emits `venue.cancel`. 5 tests pass. |
| 2 — no CANCEL_ACK→IDLE for entry (hung orders) | Critical | **FIXED** | `lib.rs:1193-1212` CANCEL_ACK entry branch clears order + resets trade_id/asset/side/size/PnL → IDLE. Non-vacuous tests pass. |
| 5 — capital settle only on terminal | High | **FIXED** | bridge `on_venue_event` settles incremental `realized_pnl` per fill; `account.settle()` moves capital by exactly that amount. Exact-invariant test passes. |
| 6 — LIMIT order_type/limit_price dropped | Critical | FIXED (N/A to MARKET) | payload carries `order_type`/`limit_price`; out of scope for MARKET-only Sprint 1. |
| 4 — double-close/double-settle on final leg | Low | **FIXED** | `apply_fill` exit branch: realized accrues once/fill; `should_close` guarded by size; closed slot rejects further EXIT (`NO_OPEN_POSITION`); dup fills deduped. |
| 10 — event dedup window | Low | **FIXED** | `seen_event_ids` (cap 256, FIFO evict); duplicate events short-circuit to `DUPLICATE_EVENT`. Tests pass. |
| 11 — reconcile validation | Low | **FIXED** | `reconcile_slots_json` validates every slot via `validate_slot` and rejects the whole batch without mutating on failure. Tests pass. |
| 13 — re-entry PnL loss | Low | **FIXED** | ENTER resets realized/unrealized/size; bridge resets `_last_settled_pnl[slot]` on ENTER. Tests pass. |
| 3, 7, 8, 9, 12 | Med/Low | FIXED | covered by hardened/passing tests. |
## GATE decision
**PASS.** The MARKET-path-critical flaws (1, 2, 5) are confirmed fixed in source and proven
by non-vacuous offline tests. Sprint 1 (PINK single-leg MARKET on BingX testnet/VST) may proceed.
## Carry-forward risks (NOT GATE blockers)
- **Sprint 3 (multi-leg) sizing:** the exit branch computes `exit_size = base_size × ratio` with
`base_size = initial_size` and cumulative ratios (e.g. `0.5, 1.0`). On the final leg this can
exceed the *remaining* position; the kernel currently relies on the venue clamping the fill to
the open size. Validate on testnet before enabling `multi_exit`.
- **LIMIT / partial-fill** remains explicitly out of scope (MARKET-only bring-up).