# VIOLET — partial spec for another agent (OA TODO) Date: 2026-06-16. Carved from the VIOLET dev plan: the pending items that are **self-contained** — a separate agent can complete each WITHOUT touching another agent's in-flight files, with clear tests + pass criteria. --- ## 0. HARD RULES (apply to every task below — non-negotiable) 1. **Never edit shared files.** Forbidden to modify: `prod/nautilus_event_trader.py`, `prod/clean_arch/dita_v2/**`, `prod/clean_arch/dita/decision.py`, `nautilus_dolphin/**`, `prod/clean_arch/dita_v2/blue_parity.py`, `prod/bingx/leverage.py`. You may READ them. 2. **VIOLET stays DARK** — no orders, no live execution, no VST keys. No starting/stopping services. No Hazelcast restart. No PROGREEN. 3. **V-TYPES on all new code** — `StrictModel` / `Annotated[... Field]` / `@typed` (beartype) per `prod/clean_arch/violet/domain.py`. No arbitrary magnitude caps; only faithful poison-guards (finite / non-negative where BLUE guarantees it). 4. **Each task below is NEW-FILE-ONLY** by design — do NOT modify these in-flight files (another agent owns them right now): `live_blue_source.py`, `shadow_live_factors.py`, `live_factor_source.py`, `decision_engine.py`, `sizing.py`. Add new modules/tests instead. ## 0a. COMMIT / BRANCH POLICY (read this — three shared-index collisions happened on 2026-06-16) Multiple agents share ONE working tree + ONE `.git/index` on this box. `git commit` commits the ENTIRE index, so a concurrent agent's staged files get swept into your commit (one landed in forbidden `dita_v2/`). Therefore: 1. **Work in your own `git worktree`** if at all possible: `git worktree add ../vp-oa -b agent/oa-violet` and do ALL work there. This makes collisions impossible. (See `prod/docs/VIOLET_OB_FEED_AND_AGENT_COORDINATION.md` §3.) 2. **If you must share the working tree**, NEVER `git add -A` / `git add .`. Stage your exact files, and commit with an explicit pathspec so only your paths are committed: `git commit -F msg.txt -- path/to/your_new_file.py path/to/your_test.py` Verify after every commit: `git show --stat --format="" HEAD` must list ONLY your files. 3. **One commit per task**, message prefix `VIOLET OA:`; end with the Co-Authored-By trailer. Before reporting done: `git diff --name-only HEAD~1` ∌ any forbidden shared path. 4. **Run tests on the prod interpreter**: `/home/dolphin/siloqy_env/bin/python3 -m pytest -q`. The mount is CIFS-slow (a 30-test file ≈ 60-150s); that is normal, not a hang. Use `git grep` (not recursive `grep -r`/`find`, which time out at ~2min). --- ## TASK 1 — Parity-pin tests for the hand-replicated sizing arithmetic **Why.** `prod/clean_arch/violet/sizing.py` hand-transcribes BLUE arithmetic from `esf_alpha_orchestrator.py` (regime_size_mult :898-909, market_ob_mult :587-595, strength_cubic :872-885, the 5-factor compose :600-619). The `@gate` Monte-Carlo proves the COMPOSED leverage bit-identical, but there is no PER-FORMULA pin that fails loudly if BLUE changes one factor's formula. This task adds those pins. See `prod/docs/VIOLET_BLUE_PARITY_STRUCTURAL_DIVERGENCE.md` (mitigation #1). **Affected files (NEW only):** - `prod/clean_arch/violet/test_violet_sizing_parity_pin.py` (new) **Approach.** - Import BLUE's real `NDAlphaEngine` from `nautilus_dolphin.nautilus.esf_alpha_orchestrator` (READ-only use; construct a minimal instance with default ENGINE_KWARGS-equivalent params). - For a sampled grid of inputs (vel_div ∈ [-0.06, 0], boost ∈ [1,3], beta ∈ {0.2,0.8}, mc_scale ∈ {0.5,1.0}, ob (median_imbalance, agreement_pct) over a grid, dc_status ∈ {NONE,CONFIRM}, posture ∈ {APEX,STALKER}), drive BLUE's engine to compute each intermediate (`_day_*` state → `_update_regime_size_mult`; the OB block; `_strength_cubic`) and assert VIOLET's `VioletSizer.regime_size_mult / market_ob_mult / strength_cubic / dc_lev_mult` return the EXACT same float (`==`, not approx — these are deterministic). - If a BLUE method is not callable in isolation (needs engine state), set the minimal `_day_*` attributes directly and call the method; document any state you had to set. **Tests / pass criteria.** - New test file: every parametrized case asserts exact equality VIOLET-replica == BLUE-method. - `pytest -q prod/clean_arch/violet/test_violet_sizing_parity_pin.py` → all pass. - The existing `@gate` composition test still passes (don't change sizing.py). - DONE when: ≥ 200 grid points per formula, zero mismatches, no edits outside the new test file. --- ## TASK 2 — Multi-exchange OB provider seam (scaffold + interface, NOT wired live) **Why.** VIOLET currently reads BLUE's extant Binance-reference OB via `HZOBProvider`. The spec requires being able to run a SEPARATE OB stream later (BingX testnet / 3rd-party venues have genuinely different order books). The `OBProvider` behind `OBFeatureEngine` is the swap seam. This task defines + tests that seam as a new module, WITHOUT wiring it into the live path (wiring is owned by the in-flight `live_blue_source` / `shadow_live_factors`). **Affected files (NEW only):** - `prod/clean_arch/violet/venue_ob_provider.py` (new) - `prod/clean_arch/violet/test_violet_venue_ob_provider.py` (new) - `prod/docs/VIOLET_SPEC__MULTI_EXCHANGE_OB_SEAM.md` (new short design note) **Approach.** - Read `nautilus_dolphin/nautilus_dolphin/nautilus/ob_provider.py` (the `OBProvider` ABC + `OBSnapshot`) and `hz_ob_provider.py` (BLUE's reference impl) to learn the exact interface (`get_snapshot`, `get_assets`, `get_all_timestamps`, `get_snapshot_count`, snapshot fields: bid/ask notional+depth arrays of length 5, timestamp, asset). - Define `VioletVenueOBProvider(OBProvider)` — a venue-agnostic provider that takes a normalized tick source (NOT a live WS yet; accept an injected callable / in-memory buffer). Produce `OBSnapshot`s with the SAME shape BLUE expects so it drops into `OBFeatureEngine` unchanged. - Include a `MockTickVenueOBProvider` for tests (deterministic snapshots). Do NOT open any real exchange connection. V-TYPES on the normalized tick (5-level arrays non-negative, finite). - Design note documents: the seam, how a future BingX WS adapter plugs in, and that wiring into `_source_ob_market` is deferred to the owner of `live_blue_source.py`. **Tests / pass criteria.** - `VioletVenueOBProvider` conforms to `OBProvider` (all abstract methods implemented; an `OBFeatureEngine(provider)` can `step_live` + `get_market` over mock snapshots without error). - Poison rejection: negative/NaN depths or wrong-length arrays are rejected at construction. - `pytest -q prod/clean_arch/violet/test_violet_venue_ob_provider.py` → all pass. - DONE when: the provider drives a real `OBFeatureEngine` to a finite `get_market` result in a test, no live connections, no edits outside the 3 new files. --- ## TASK 3 — Base-fraction sizing study (analysis + report; no production code change) **Why.** The base sizing fraction (0.20) is a champion constant; a study was specced but not run (`prod/docs/VIOLET_STUDY_SPEC__BASE_FRACTION_SIZING.md` — READ it first; it is the authority for scope/method). This is a pure analysis task producing a report — zero behavior change — so it is fully parallelizable. **Affected files (NEW only):** - `prod/VIOLET_dev/studies/base_fraction_study.py` (new analysis script) - `prod/VIOLET_dev/reports/base_fraction_study_.md` or `.json` (new report output) **Approach.** - Follow the existing study spec exactly. Use recorded data only (CH `dolphin_violet` / `dolphin` read-only via `http://localhost:8123`, user `dolphin` / key `dolphin_ch_2026`). Do NOT write to any production table. Do NOT change `sizing.py` / `decision_engine.py`. - Compute the requested sensitivity (PnL / drawdown / capital-utilization vs base_fraction over the spec's grid), honoring the leverage caps (base_max=8, abs_max=9) and the margin-study findings (notional = 0.20 × conviction × capital today). - Output a report with the recommended base_fraction + evidence; flag any caveats. Recommend, do NOT apply. **Tests / pass criteria.** - The script runs end-to-end on the prod host and writes a report to `prod/VIOLET_dev/reports/`. - A small `pytest` (or `--self-test` mode) validates the core computation on a synthetic fixture (deterministic input → known output), so the math is checkable without live data. - DONE when: report archived + self-test passes + no production table writes + no code-behavior change. --- ## What is intentionally NOT in this spec (do not start these) - **DARK soak start** — HELD for the operator's explicit word. - **V4 live execution** — blocked on VST keys; operator-gated. - **HZ Bridge refactor** (`TODO_HZBRIDGE`) — depends on `dolphinng5_predict/hzbridge` shipping (owned by another agent); not self-contained yet. - **Edits to `live_blue_source.py` / `shadow_live_factors.py` / `sizing.py` / `decision_engine.py`** — in-flight; coordinate before touching.