Adds prod/docs/WATCHDOG_GHOST_SUBSCRIPTION_SELF_RESTART.md: the 2026-09-16 04:10:40
r27 ghost-subscription wedge (empty data after 04:08 WS reconnect), the log-only
-> self-restart (b) promotion via the watchdog_decision seam, the guard contract
(acc_age>=900s, uptime>600s, probe-not-None), the 51-test suite, mutation-litmus
results, operational status (pid 3506857 still pre-fix; restart safe per
AGENTS.md BLUE=flat-venue).
E1 as submitted (release phantom on promotion-SUPPRESSED entries) does not survive
review: the orchestrator is single-position and self-clears exit_manager+self.position
on its own exit each cycle (esf_alpha_orchestrator 491-492), so shadow mode is a faithful
paper mirror and pi's fix would regress shadow parity. The investigation instead found the
real bug — phantom_release left engine.position set → single-position engine bricked on a
proven reject — fixed in f11.1/blue-sizing-parity 98941373. Preserves pi's original E1 text.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
F10 (BLUE's kernel in the UV/VIOLET body, live-mainnet-capable, promotion-gated by
the arm file) now runs under supervisord as program flight10 instead of an ad-hoc
agent background task (which got reaped ~18min -- the only reason it kept dying).
Command SOURCES /root/flight10_prod.env (chmod 600, secrets NOT inlined here) so every
autorestart revive gets the full env (mainnet keys, DITA_V2_ZINC=REAL shared-RAM exec
plane, UV_EXEC_DARK_MODE=0, TP/SL, vol threshold, CH/HZ, arm-file path). Sets HOME + an
explicit PATH incl /root/.cargo/bin (the DITAv2 rust-backend provenance check shells
`rustc -vV`; supervisord's minimal PATH lacked it -> crash-loop). Clears stale
zinc_uv_exec_* regions pre-launch (RealZincPlane create=True FileExistsErrors on a
prior runner's un-reaped regions -> silent in-memory downgrade; F10 is sole owner so
clearing is safe -> REAL shared RAM every start/autorestart). Polite: startsecs=100 +
startretries=3 -> a startup-crash goes FATAL, never rate-loops BingX. autostart=false,
autorestart=true, log rotation, rlimit_as=3GB. BLUE (dolphin:nautilus_trader) untouched.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
MCTS planner with dynamic book:
Episode 3: slippage=1.125 bps (first aggressive fills)
Episode 20: slippage=0.177 bps (84% reduction)
Episode 30: slippage=0.008 bps (99% reduction!)
The planner learns to:
1. Place passive orders at better offsets
2. Wait for book to move before crossing
3. Use urgency-driven maker/taker decision
4. Reduce slippage through queue position optimization
PnL stays positive throughout (+1687 to +5048 bps).
Fill value improving from -0.319 to -0.000 (less negative = better).
REQUOTE is now distinct from QUOTE:
QUOTE: PLACE new order (no existing to cancel)
REQUOTE: CANCEL_REPLACE existing + place new (immediate)
CHASE: PLACE with short TTL (auto-cancel retry)
CANCEL: Remove existing order
action_menu generates REQUOTE with metadata={'requote': True} for existing orders.
DSL REQUOTE produces CANCEL_REPLACE when existing order, falls back to PLACE.
All 800+ tests pass.
README: Fill Quality section (core optimization target, metrics, reward
function, PerformanceMatrix, CMA-ES integration)
HftBacktestCWM integration doc: FillQuality dataclass, fill_value_score
computation, reward function weighting, PerformanceMatrix tracking
OB microstructure study: Section 13 — Fill Quality Optimization,
per-asset expectations, optimization strategy, connection to OB dynamics
Fill quality is MALKHUT's core aim: the system learns to get better fills
(faster, better-priced, less adverse selection) across regimes and venues.
Fill quality is MALKHUT's core aim. Wired end-to-end:
1. FillQuality state (state.py):
- slippage_bps, price_improvement_bps, levels_consumed
- is_maker_fill, rolling_fill_rate, post_fill_adverse_bps
- fill_value_score: composite metric for optimization
- Added to MarketWorldState.fill_quality field
2. HftBacktestCWM.transition() (hft_cwm.py):
- _compute_fill_quality() computes all metrics per transition
- Fill quality now tracked for every CWM step
- Empty book guards added for safety
3. MinimalCryptoLOBCWM.transition() (core.py):
- Same fill quality computation for deterministic fallback
- Empty book guards added
4. Reward function (hft_cwm.py):
- fill_quality_reward = w_fill_probability * fill_value_score (PRIMARY)
- Bonus for maker fills that improve price
- Penalty for adverse selection after fill
- Base reward (PnL, adverse selection, fees) preserved
5. PerformanceMatrix (selector.py):
- RegimeStrategyScore: 4 new fill quality fields
- record(): accepts fill_rate, slippage, price_improvement, fill_value_score
- EMA updates for all fill quality metrics
6. EpisodeResult (cma_trainer.py):
- avg_fill_value_score, avg_price_improvement_bps, avg_post_fill_adverse_bps
- Accumulated per-step during _run_episode
- Recorded to PerformanceMatrix in evaluate_candidate
All 1379+ tests green.
Bolts SmartExecBridge into the flight's scan loop behind UV_SMART_EXEC (default off). Fully
lazy: flag off => smart_bridge is never imported and the naive maybe_promote runs unchanged
(verified: runner import does not load smart_bridge when the flag is unset). Flag on =>
entries rest as PostOnly GTX makers, exits stay MARKET, the 6s tick drives TTL-abandon.
Reuses bridge.gate (two-man rule) + bridge.stats. runner.py compiles; wire import-safe both
paths. This is the 'bolt to flight 5/6' — dormant until an operator flips the flag and restarts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SmartExecBridge: a drop-in for PromotionBridge.try_promote that rests entries as PostOnly GTX
makers (via exec_unified.router policy) instead of always paying the taker cross. DORMANT —
selected only by UV_SMART_EXEC=1 (default off); nothing imports it yet, so the running flight
is untouched. T1 = smallest bug surface (spec §15):
- ENTER -> maker (ACQUIRE): PostOnly LIMIT @ touch; unfilled by next scan tick -> CANCEL/abandon
('a missed entry is free' §4-1). No chase, no cross, no requote race.
- EXIT -> MARKET unchanged (never strand; zero new exit risk in v1).
- the 6s scan tick IS the drive clock: sweep-stale-then-place each promote.
Reuses router.decide + friction side-lane (never blocks a promote); fail-soft (never raises
into the scan loop). 11 tests, 2 mutation litmus RED (entry-maker policy; stale-sweep).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
intent_translator.py: the injected to_kernel_intent KernelExecPort needs, wiring the pure
engine to the live DITAv2 kernel. Side/size/cancel mappings each verified against vendored
source (bingx_venue:627, rust_backend:448/897); EXIT inversion mutation-verified RED. Tested
against REAL dita_v2 (importorskip). Lazy dita_v2 import keeps the rest of the package clean.
143 tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lands the /root/dev local increments (share was ENOSPC; now writable) into the canonical repo:
- kernel_port.py: real ExecPort over the DITAv2 kernel (duck-typed; injected to_kernel_intent).
- dialect.py §11: BingX boundary — clientOrderId(H4)/dash/quantize/payload (PostOnly=timeInForce).
- friction.py §12: effective-bps + naive-baseline savings; side-lane journal that can't raise
(b46ebd2); BingX commission-sign flip. DDL ships with code (register in applier verify-set).
- drive_loop/executor/working: Decimal size threaded through plan/working types (exit size cap).
All pure stdlib+Decimal, mutation-litmus RED on the two load-bearing asserts. 132 tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
Rolling stats (no episode accumulation), CMA-ES every 10 cycles (3 evals),
gc.collect() after CMA, global try/except for crash safety.
100-opponent swarm, 9 assets, 270 scenarios.
Fixed OOM kill by replacing all_episodes list accumulation with:
- Rolling stats (clear every 20 episodes)
- Only PnL history kept for characterization
- Peak/worst tracking without full episode storage
- Periodic stdout reports from rolling aggregates
100-opponent swarm + 9 assets × 30 scenarios = 270 scenarios per cycle.
CMA-ES every 5 cycles (3 evals). 3-hour target.