VIOLET V1c: observe-only launcher + hard guard + divergence monitor + service (DARK)

launch_dolphin_violet.py: own namespaces hard-set (CH dolphin_violet, HZ
DOLPHIN_STATE_VIOLET/PNL, Zinc prefix violet, DOLPHIN-VIOLET-001); own
credentials (BINGX_VIOLET_API_KEY/SECRET) — DARK idle with periodic WARNING
until provisioned; CH preflight SELECT-probes the required tables and NEVER
creates (DDL-before-code); kernel snapshot path repointed away from PINK's
fixed /tmp/.pink_kernel_state.json; mainnet hard-disabled; observe loop
never calls runtime.step(). ObserveOnlyVenue: submit/cancel raise
ObserveOnlyViolation with full attribute delegation — the kernel's
venue-submit-failure rollback converts a refusal into a synthetic REJECT
(slot back to IDLE), proven against the real kernel. FeedDivergenceMonitor:
per-asset scan-vs-venue divergence rows (bookTicker WS via
prod/bingx/market_stream, REST fallback) with stale-mid suppression and
plane seq propagation — the FET 0.2176-vs-0.1878 detector; runs even DARK
(public data). Supervisord [program:dolphin_violet] autostart=false, no
keys in conf by design. Violet package: 42 tests green + V0 gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-06-12 16:09:04 +02:00
parent d639a69307
commit 970c33cb8e
7 changed files with 984 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
"""VIOLET observe-only hard guard (Stage V1).
``ObserveOnlyVenue`` wraps any venue adapter and makes order placement
structurally impossible: ``submit``/``submit_async``/``cancel``/
``cancel_async`` raise ``ObserveOnlyViolation`` and log CRITICAL. Every
other attribute (including assignment — e.g. the runtime's
``venue._kernel_ref = kernel``) delegates to the wrapped adapter, so
account streams, reconcile reads and connection management work unchanged.
This is the hard guarantee, independent of policy configuration: even if a
policy step were ever wired into the V1 runtime by mistake, no order can
reach the exchange.
"""
from __future__ import annotations
import logging
from typing import Any
LOGGER = logging.getLogger("violet.observe_guard")
_BLOCKED = ("submit", "submit_async", "cancel", "cancel_async")
_SELF_ATTRS = ("_inner", "_logger")
class ObserveOnlyViolation(RuntimeError):
"""An order-placement call reached the observe-only venue guard."""
class ObserveOnlyVenue:
"""Delegating wrapper that refuses order placement."""
def __init__(self, inner: Any, logger: logging.Logger | None = None) -> None:
object.__setattr__(self, "_inner", inner)
object.__setattr__(self, "_logger", logger or LOGGER)
# -- blocked surface -----------------------------------------------------
def _refuse(self, name: str, *args: Any, **kwargs: Any) -> None:
msg = (
f"OBSERVE-ONLY VIOLATION: venue.{name}() called — VIOLET V1 must "
f"never place or cancel orders (args={args!r:.200})"
)
object.__getattribute__(self, "_logger").critical(msg)
raise ObserveOnlyViolation(msg)
def submit(self, *a: Any, **k: Any) -> Any:
self._refuse("submit", *a, **k)
async def submit_async(self, *a: Any, **k: Any) -> Any:
self._refuse("submit_async", *a, **k)
def cancel(self, *a: Any, **k: Any) -> Any:
self._refuse("cancel", *a, **k)
async def cancel_async(self, *a: Any, **k: Any) -> Any:
self._refuse("cancel_async", *a, **k)
# -- delegation ----------------------------------------------------------
def __getattr__(self, name: str) -> Any:
return getattr(object.__getattribute__(self, "_inner"), name)
def __setattr__(self, name: str, value: Any) -> None:
if name in _SELF_ATTRS:
object.__setattr__(self, name, value)
else:
setattr(object.__getattribute__(self, "_inner"), name, value)
def __repr__(self) -> str: # pragma: no cover — debug helper
return f"ObserveOnlyVenue({object.__getattribute__(self, '_inner')!r})"