exec(unified): UnifiedExecutor — initial-submit pipeline + S2 pain-fence

executor.py composes the built parts into one execute(request, snapshot): S-grade fence →
router.decide → placer.pre_submit → submit → register working. The initial-submit half that
complements DriveLoop's expiry half (analogue of pink_direct.py:1645-1700).

Composition rulings encoded + tested:
- S2/S3 pain-fence (§15.2): refused WHOLE, loudly, below T14 — never silently sliced.
- placer declines (spread gate) → cross ONLY if urgency crosses on expiry; ACQUIRE ABANDONS
  (a missed entry is free, §4-1). Both mutation-verified RED.
- TTL from urgency discipline: PROTECT 2s / ROTATE deadline_ms / ACQUIRE quote-lifetime.

contract.py: SGrade enum (S0-S3) + s_grade/parent_request_id fields. _constants: MAKER_QUOTE_TTL_S.

FIX (real bug, not just test): drive_loop._is_resolved EXIT was trade_id-based (a PINK
artifact — PINK reused the position's trade_id for exits). The agnostic layer never gets
the position id, so exit-done is now SIZE-based. Kept ENTER on clientOrderId match.

Full exec_unified suite: 94 green, mutation-litmus verified.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-07-15 02:30:30 +02:00
parent a310c92977
commit 21419b03d0
6 changed files with 376 additions and 3 deletions

View File

@@ -36,6 +36,9 @@ OPENISH = frozenset({
})
# Stages that mean the position is gone. pink_direct.py:1106.
CLOSED_STAGES = frozenset({"POSITION_CLOSED", "CLOSED", "TRADE_TERMINAL_WRITTEN", "IDLE"})
# Stages that mean the venue rejected our order (post-only would cross, etc.).
# pink_direct.py:1000. A rejected maker quote still registers → resolves via the TTL path.
REJECTED_STAGES = frozenset({"ORDER_REJECTED", "EXIT_REJECTED"})
@dataclass(frozen=True)
@@ -64,6 +67,12 @@ class ResubmitPlan:
reduce_only: bool
# The plan the venue receives is the same shape whether it is an initial submit (executor,
# attempt 0) or a rebuilt retry/escalation (drive loop). "Resubmit" is the origin name;
# OrderPlan is the role name the executor uses.
OrderPlan = ResubmitPlan
class ExecPort(Protocol):
"""The single seam to kernel + venue. Fakeable; the loop touches the world ONLY here."""
@@ -103,11 +112,21 @@ class DriveLoop:
# ── classification ───────────────────────────────────────────────────────
def _is_resolved(self, wo: WorkingOrder, slot: SlotView) -> bool:
"""Entry filled or exit done, per kernel truth (pink _entry_filled/_exit_done)."""
"""Entry filled or exit done, per kernel truth (pink _entry_filled/_exit_done, L1099).
ENTER: our entry filled — the slot carries OUR clientOrderId (the kernel tags the new
position with it; clientOrderId echo is the best-practice fill key, audit H5) and shows
size + an open stage.
EXIT: the position is gone — size drained or a closed stage. **Deliberately SIZE-based,
not trade_id-based**: pink_direct.py:1105 could compare `slot_tid != wo.trade_id` only
because it REUSED the position's trade_id for the exit intent. This layer is agnostic
(contract §2) — the caller mints a fresh request_id for the exit and never hands us the
position's id — so an exit is "done" iff the position closed, which is the size signal.
"""
if wo.action is Action.ENTER:
return slot.trade_id == wo.request_id and slot.size > 0 and slot.stage in OPENISH
return (slot.trade_id != wo.request_id or slot.size <= 0
or slot.stage in CLOSED_STAGES)
return slot.size <= 0 or slot.stage in CLOSED_STAGES
def after_submit(self, wo: WorkingOrder, *, rejected: bool) -> str:
"""Classify a maker submit: filled-now / working / rejected. pink L975.