VIOLET OA: partial spec PASS 6 — execution internals + quirk-injection gate
VIOLET_PART_SPEC_OA_TODO_PASS6.md — the execution internals on top of PASS-5's mock, plus the quirk-injection layer that flips PASS-5's QuirkProfile seams ON and proves each handler survives. Six independent units extending contracts_v3 (AccountFrame/PositionFrame/ReconcileCorrection/ OwnershipPolicy): 25. Account/position frame contracts + ownership predicate (foreign-fill filter basis). 26. Fill-pump (ownership filter [quirk #2], dedup, idempotent) → ledger deltas. 27. Reconcile loop (zero-wb guard [#1], reseed-on-update, settle/funding event_seq order [#5]). 28. TTL requote / cancel-replace (+ setLeverage ordering [#7]) over PASS-5 venue + V2 driver. 29. Orphan detection (ORPHAN_VENUE adopt, ORPHAN_LOCAL quarantine — never silent flatten/resurrect). 30. Quirk-injection suite + @gate: flip every QuirkProfile flag ON, assert each is neutralized. VIOLET's exec reconcile/quirk-handling mirrors PINK's production-tested logic (pink_direct.py is the authoritative reference — transcribe + cite). New-file-only: quirk injection plugs into PASS-5's existing seams via NEW fill/frame models, never editing the PASS-5 mock. Real-key boundary smoke remains MANDATORY before V4-live (injection proves logic, not undocumented venue reality). Standing ready for PASS 7–9. Added PASS 6 to the review queue in VIOLET_TODO_CRITICAL.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
190
prod/docs/VIOLET_PART_SPEC_OA_TODO_PASS6.md
Normal file
190
prod/docs/VIOLET_PART_SPEC_OA_TODO_PASS6.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# VIOLET — partial spec for another agent, PASS 6 (OA TODO): EXECUTION INTERNALS + QUIRK INJECTION
|
||||
|
||||
Date: 2026-06-17. Continues PASS 5 (the mock-BingX execution stack). PASS 5 built the NORMATIVE
|
||||
mock (order FSM, venue, fill reducer) with quirk SEAMS left OFF. **PASS 6 builds the execution
|
||||
INTERNALS** — reconcile, fill-pump, TTL-requote, orphan handling — **and IMPLEMENTS the quirk
|
||||
INJECTION + handling logic**, flipping each `QuirkProfile` flag ON and proving the reconcile/filter
|
||||
logic survives it. This reproduces, for VIOLET, the hard-won PINK production fixes.
|
||||
|
||||
**Read first (authoritative references — READ ONLY, never edit):**
|
||||
- `prod/clean_arch/runtime/pink_direct.py` — PINK's live execution runtime: the EXACT reconcile,
|
||||
fill-pump, ownership-filter, zero-wb-guard, orphan, and requote logic this pass mirrors.
|
||||
- `prod/clean_arch/exec/**` — the ExecutionRouter (maker/taker policy, hooks).
|
||||
- PASS 5 files: `prod/clean_arch/violet/exec/{order_fsm,mock_bingx_venue,fill_reducer,bingx_quirks}.py`
|
||||
+ `contracts_v3.py` — the substrate PASS 6 composes (READ + IMPORT; do NOT edit).
|
||||
- Memory/incident lineage of each quirk: `project_pink_orphan_fixes`,
|
||||
`ditav2_kernel_audit_20260611`, `incident_pink_spool_diskfill_20260611`.
|
||||
|
||||
VIOLET's ALPHA models BLUE; VIOLET's EXECUTION reconcile/quirk-handling models **PINK's
|
||||
production-tested logic** (PINK is the exec-active fork). Transcribe PINK faithfully — cite
|
||||
`pink_direct.py:line` in each handler's docstring.
|
||||
|
||||
---
|
||||
|
||||
## 0. HARD RULES (identical to PASS 1–5 — summarized)
|
||||
- **Never edit shared files** (`prod/nautilus_event_trader.py`, `clean_arch/dita_v2/**`,
|
||||
`dita/decision.py`, `nautilus_dolphin/**`, `blue_parity.py`, `prod/bingx/leverage.py`,
|
||||
`prod/clean_arch/runtime/pink_direct.py`, `prod/clean_arch/exec/**`). READ only.
|
||||
- **VIOLET DARK** — everything runs against the PASS-5 mock; NO real venue/network/key, no
|
||||
service/HZ control.
|
||||
- **V-TYPES on all new code**; faithful poison-guards only.
|
||||
- **NEW-FILE-ONLY** under `prod/clean_arch/violet/exec/` (+ extend `contracts_v3.py`). Do NOT
|
||||
modify the PASS-5 files (`order_fsm.py`, `mock_bingx_venue.py`, `fill_reducer.py`,
|
||||
`bingx_quirks.py`) or any in-flight V3.4 file. Quirk INJECTION must be done by NEW
|
||||
fill/frame models + wrappers that plug into PASS-5's existing seams (`MockBingxVenue` takes an
|
||||
injectable `fill_model` + a `QuirkProfile`), NOT by editing the mock.
|
||||
|
||||
## 0a. COMMIT / BRANCH POLICY (3 shared-index collisions on 2026-06-16 — non-negotiable)
|
||||
Own `git worktree` (`git worktree add ../vp-oa6 -b agent/oa-violet6`) strongly preferred. Else
|
||||
never `git add -A`; `git commit -F msg -- <files>` with explicit pathspec; verify
|
||||
`git show --stat --format="" HEAD` lists ONLY your files. One commit/task, prefix `VIOLET OA:`,
|
||||
Co-Authored-By trailer. Tests on `/home/dolphin/siloqy_env/bin/python3`. `git grep` only.
|
||||
|
||||
---
|
||||
|
||||
## I. SHARED INTERFACE EXTENSIONS (add to `contracts_v3.py`; never fork a parallel type)
|
||||
Reuse PASS-3/4/5 types (`VenueTick`, `OpenPositionView`, `ExecIntent`, `CapitalState`, `Order`,
|
||||
`OrderAck`, `Fill`, `OrderStatus`, `PositionDelta`). ADD the account/reconcile vocabulary (all
|
||||
`StrictModel` / `Annotated`):
|
||||
1. **`AccountFrame`** — venue-reported account snapshot: `wallet_balance: float (finite, ge=0)`,
|
||||
`available: float (ge=0)`, `ownership_id: str`, `event_seq: Seq`, `ts_ns: MonoNs`. (Carries the
|
||||
zero-wb seam: `wallet_balance` may legitimately arrive as 0.0 in a poison frame — quirk #1.)
|
||||
2. **`PositionFrame`** — venue-reported position: `asset: Symbol`, `qty: float`,
|
||||
`entry_price: Px`, `leverage: Annotated[int, Field(ge=1)]`, `ownership_id: str`,
|
||||
`event_seq: Seq`, `ts_ns: MonoNs`.
|
||||
3. **`ReconcileCorrection`** — `asset: Symbol`, `kind: str`
|
||||
("DRIFT"/"ORPHAN_LOCAL"/"ORPHAN_VENUE"/"NONE"), `local_qty: float`, `venue_qty: float`,
|
||||
`action: str` ("ADOPT_VENUE"/"FLATTEN"/"QUARANTINE"/"NOOP"), `event_seq: Seq`.
|
||||
4. **`OwnershipPolicy`** — `account_id: str`, `client_order_id_prefix: str` — the predicate used to
|
||||
decide a fill/frame is OURS vs foreign (quirk #2). Provide `owns(ownership_id) -> bool`.
|
||||
|
||||
If a task needs another field, ADD it here and note it.
|
||||
|
||||
---
|
||||
|
||||
## TASK 25 — Account/position frame contracts + ownership policy
|
||||
**Why.** The reconcile/filter vocabulary + the ownership predicate every handler needs.
|
||||
**Affected files (NEW):** extend `contracts_v3.py` (the §I types);
|
||||
`prod/clean_arch/violet/exec/ownership.py` (the `OwnershipPolicy` predicate impl);
|
||||
`prod/clean_arch/violet/exec/test_violet_ownership.py`.
|
||||
**Interface/approach.** `OwnershipPolicy.owns(ownership_id)` returns True iff the id matches our
|
||||
account / client_order_id prefix (transcribe PINK's ownership check — cite `pink_direct.py:line`).
|
||||
Frames/fills with a non-owned `ownership_id` are FOREIGN (must be filtered downstream).
|
||||
**Pass criteria.** `owns()` correct for own vs foreign ids; frames poison-reject (non-finite
|
||||
wallet_balance rejected, but **0.0 wallet_balance is ACCEPTED into the type** — it is a legitimate
|
||||
poison-frame value the reconcile layer must SEE and then ignore, not a type error). No edits
|
||||
outside the new/extended files.
|
||||
|
||||
## TASK 26 — Fill-pump (ownership filter + dedup → ledger deltas) [quirk #2]
|
||||
**Why.** Drain fills from the venue, drop foreign fills, dedupe, convert to `PositionDelta` via the
|
||||
PASS-5 fill reducer, feed the PASS-4 economics ledger. PINK's fill-pump is the reference.
|
||||
**Affected files (NEW):** `prod/clean_arch/violet/exec/fill_pump.py`,
|
||||
`prod/clean_arch/violet/exec/test_violet_fill_pump.py`.
|
||||
**Interface/approach.** `FillPump(reducer, ledger, ownership: OwnershipPolicy)` with
|
||||
`pump(fills: list[Fill]) -> list[PositionDelta]`: filter `ownership.owns(f.ownership_id)` (FOREIGN
|
||||
fills dropped — **ownership fill filter, quirk #2**), dedupe by `(venue_order_id, event_seq)`,
|
||||
apply each via PASS-5 `fill_reducer.apply_fill`, push the `PositionDelta` into the ledger
|
||||
(`event_seq`-ordered). Idempotent: re-pumping the same fills produces no double-count.
|
||||
**Pass criteria.** Own fills applied; foreign fills dropped (ledger unchanged); duplicate fills
|
||||
deduped; out-of-order event_seq handled per ledger rules; idempotency proven. Cite the PINK
|
||||
ownership filter. No edits outside the 2 files.
|
||||
|
||||
## TASK 27 — Reconcile loop (zero-wb guard + reseed-on-update + settle ordering) [quirks #1, #5]
|
||||
**Why.** Periodically reconcile local position/capital vs venue frames; the zero-wb guard and
|
||||
reseed-on-update are the documented PINK fixes that stop a transient `walletBalance=0` frame from
|
||||
zeroing capital.
|
||||
**Affected files (NEW):** `prod/clean_arch/violet/exec/reconcile.py`,
|
||||
`prod/clean_arch/violet/exec/test_violet_reconcile.py`.
|
||||
**Interface/approach.** `Reconciler(ownership)` with
|
||||
`reconcile(local: dict[Symbol, OpenPositionView], account: AccountFrame,
|
||||
positions: list[PositionFrame]) -> list[ReconcileCorrection]`:
|
||||
- **Ignore foreign frames** (ownership).
|
||||
- **Zero-wb guard (quirk #1):** if `account.wallet_balance == 0.0` (poison frame), DO NOT adopt it
|
||||
— skip the capital update, log, keep prior (cite PINK).
|
||||
- **Reseed-on-update:** adopt venue position state only on a genuine update (newer `event_seq`),
|
||||
not on a stale/duplicate frame.
|
||||
- **Settle/funding desync (quirk #5):** process frames strictly in `event_seq` order; a settle
|
||||
event arriving out of fill order is reordered, never applied ahead of its fills.
|
||||
- Emit `ReconcileCorrection`s for genuine drift (ADOPT_VENUE / FLATTEN), NOOP otherwise.
|
||||
**Pass criteria.** A zero-wb frame does NOT change capital; a stale frame is ignored;
|
||||
out-of-order settle is reordered; genuine drift yields the right correction. Hypothesis: capital
|
||||
never set to 0 by a zero-wb frame. Cite PINK lines. No edits outside the 2 files.
|
||||
|
||||
## TASK 28 — TTL requote / cancel-replace (+ setLeverage ordering) [quirk #7]
|
||||
**Why.** Maker orders that don't fill within their TTL must be canceled and re-submitted at a new
|
||||
price; `setLeverage` is a separate ackable op that must be ordered before the order it applies to.
|
||||
Composes PASS-5 `MockBingxVenue` + V2 `ExecDeadlineDriver`.
|
||||
**Affected files (NEW):** `prod/clean_arch/violet/exec/requote.py`,
|
||||
`prod/clean_arch/violet/exec/test_violet_requote.py`.
|
||||
**Interface/approach.** `RequoteController(venue, driver)` with `on_deadline(order, new_price) ->
|
||||
OrderAck`: cancel the stale maker order (assert it reaches CANCELED in the FSM), submit a fresh one
|
||||
at `new_price`. **setLeverage ordering (quirk #7):** if leverage must change, issue `set_leverage`
|
||||
and await its ack BEFORE submitting the order (no race). Reuse the V2 driver's TTL/deadline logic
|
||||
(READ `exec_driver.py`); do not fork it.
|
||||
**Pass criteria.** TTL expiry → cancel + requote at new price; the old order is CANCELED, the new
|
||||
one ACKed; setLeverage ack precedes the dependent order; requote count tracked. Determinism. No
|
||||
edits outside the 2 files.
|
||||
|
||||
## TASK 29 — Orphan detection + handling [the PINK orphan fixes]
|
||||
**Why.** Orders/positions can exist on the venue but not locally (or vice versa) — orphans. PINK's
|
||||
orphan-reconcile is the reference; misget handling caused real incidents.
|
||||
**Affected files (NEW):** `prod/clean_arch/violet/exec/orphans.py`,
|
||||
`prod/clean_arch/violet/exec/test_violet_orphans.py`.
|
||||
**Interface/approach.** `detect_orphans(local: dict, venue_positions: list[PositionFrame],
|
||||
ownership) -> list[ReconcileCorrection]`:
|
||||
- **ORPHAN_VENUE:** venue has an owned position we have no local record of → action ADOPT_VENUE
|
||||
(or FLATTEN per policy; default ADOPT_VENUE with a quarantine flag).
|
||||
- **ORPHAN_LOCAL:** we have a local position the venue doesn't report → action QUARANTINE (do not
|
||||
silently delete; the zombie-trade lesson — never resurrect/erase by guesswork).
|
||||
- Match by chain token / client_order_id where available; ambiguous → QUARANTINE.
|
||||
**Pass criteria.** Each orphan class yields the correct `ReconcileCorrection`; foreign positions
|
||||
ignored; ambiguous → quarantine, never silent flatten/resurrect. Cite the PINK orphan fix. No
|
||||
edits outside the 2 files.
|
||||
|
||||
## TASK 30 — Quirk-injection suite + gate (flip every QuirkProfile flag ON) [all quirks]
|
||||
**Why.** Prove the PASS-6 handlers actually survive each quirk by INJECTING it through PASS-5's
|
||||
seams and asserting the outcome. This is the payoff of the seam discipline.
|
||||
**Affected files (NEW):** `prod/clean_arch/violet/exec/quirk_injection.py` (the injecting
|
||||
fill/frame models that plug into PASS-5's `MockBingxVenue(fill_model=…, quirks=…)` and a
|
||||
`QuirkAccountStream` emitting injected `AccountFrame`/`PositionFrame`s);
|
||||
`prod/clean_arch/violet/exec/test_violet_quirk_injection_gate.py`; gate report →
|
||||
`prod/VIOLET_dev/reports/violet_quirk_injection_<UTC>.json`.
|
||||
**Interface/approach.** For each `QuirkProfile` flag, build the injecting model and assert the
|
||||
matching handler neutralizes it:
|
||||
- `zero_wb=True` → Reconciler keeps capital (Task 27).
|
||||
- `foreign_fill=True` → FillPump drops the foreign fill (Task 26).
|
||||
- `bound_price_poison=True` → fill_reducer PnL uses fill_price not bound_price (PASS-5 Task 23, re-asserted).
|
||||
- `settle_desync=True` → Reconciler reorders by event_seq (Task 27).
|
||||
- `setlev_race=True` → RequoteController orders setLeverage first (Task 28).
|
||||
- `reduce_only_increase=True` → OrderFSM rejects (PASS-5 Task 21, re-asserted).
|
||||
- (×leverage notional, dead `.pro` TLS) → documented; ×leverage asserted in fill_reducer,
|
||||
`.pro` TLS noted as connection-layer/real-client-only.
|
||||
**Pass criteria (`@pytest.mark.gate`).** Every quirk flag flipped ON in at least one scenario, each
|
||||
neutralized by its handler; a combined "all quirks on" storm still reaches consistent
|
||||
ledger/position state; report archived. No edits outside the new files.
|
||||
|
||||
---
|
||||
|
||||
## Composition map
|
||||
```
|
||||
PASS-5 mock (order_fsm, mock_bingx_venue[seams], fill_reducer, QuirkProfile)
|
||||
25 contracts(AccountFrame/PositionFrame/ReconcileCorrection) + ownership
|
||||
26 fill_pump(ownership filter, dedup) ───► PositionDelta ──► PASS-4 EconomicsLedger
|
||||
27 reconcile(zero-wb guard, reseed, settle-order) ─► ReconcileCorrection
|
||||
28 requote(TTL cancel/replace, setLeverage order) ─► uses PASS-5 venue + V2 driver
|
||||
29 orphans(detect) ─► ReconcileCorrection (quarantine, never silent flatten)
|
||||
30 quirk_injection + GATE: flip every QuirkProfile flag ON, assert each handler neutralizes it
|
||||
```
|
||||
Integration (running reconcile/pump/requote on the live reactor against the REAL BingX client) is
|
||||
the OWNER's job later. The **real-key boundary smoke remains MANDATORY before V4-live** — quirk
|
||||
injection proves the LOGIC, never the undocumented venue reality.
|
||||
|
||||
## Recommended order
|
||||
**25 (contracts+ownership) → 26 (fill-pump) → 27 (reconcile) → 29 (orphans) → 28 (requote) → 30
|
||||
(quirk-injection gate)**.
|
||||
|
||||
## Still NOT in scope (operator/owner only, or a later pass)
|
||||
- **Real BingX client + real-key smoke** — mandatory before V4-live; operator-gated.
|
||||
- **Live reactor wiring** of reconcile/pump/requote — owner's integration job.
|
||||
- **DARK soak start; HZ-bridge refactor; VIBRISS; the V3.4c parity root-cause (CRITICAL #1).**
|
||||
- Any edit to PASS-5 files, in-flight V3.4 files, or shared files in §0.
|
||||
@@ -64,6 +64,12 @@ economics ledger / exec-intent / alpha data feed / time exits; review when done.
|
||||
NOTE: BingX "quirks" are SEAM-ONLY here (default OFF) — a later quirk-injection pass + a mandatory
|
||||
real-key boundary smoke are required before V4-live; review when done.
|
||||
|
||||
**PASS 6**: `VIOLET_PART_SPEC_OA_TODO_PASS6.md` (issued 2026-06-17) — execution INTERNALS
|
||||
(fill-pump/ownership filter, reconcile/zero-wb guard, TTL-requote, orphan handling) + the
|
||||
QUIRK-INJECTION gate that flips PASS-5's QuirkProfile flags ON and proves each handler neutralizes
|
||||
the quirk. Mirrors PINK's production fixes (pink_direct.py). Real-key smoke still MANDATORY before
|
||||
V4-live; review when done.
|
||||
|
||||
**Action:** review each pass for correctness, BLUE-algo compliance, V-TYPES, no-shared-edits,
|
||||
real (non-vacuous) tests. **Owner: Claude (me), later.**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user