-- VIOLET V3e: shadow decision journal. One row per ACTUATED ShadowDecision the
-- VioletDecisionEngine emits (the muted "what BLUE would do this scan"). NEVER an
-- order — execution stays off behind the ObserveOnlyVenue guard. session_id is a
-- boot-time UUID (mono_ns is meaningless across restarts without it).
-- Apply via apply_violet_ddl.py (one statement per HTTP POST).

CREATE TABLE IF NOT EXISTS dolphin_violet.violet_decisions
(
    `ts`                  DateTime64(3, 'UTC'),
    `session_id`          String,
    `scan_number`         UInt64,
    `mono_ns`             UInt64,
    `asset`               LowCardinality(String),
    `side`                LowCardinality(String),
    `vel_div`             Float64,
    `fraction`            Float64,
    `conviction_leverage` Float64,
    `notional_fraction`   Float64,
    `target_exposure`     Float64,
    `ars_score`           Float64,
    `bucket_idx`          UInt8,
    `actuated`            UInt8,
    -- V3.4 full-sizing breakdown: conviction = base × dc × regime(ACB) × ob × esof,
    -- capped @9. NULL on the legacy base-only path (no live SizingFactors); populated
    -- when the launcher feeds live factor planes. Additive columns — on a pre-existing
    -- table apply the matching `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` instead.
    `base_leverage`       Nullable(Float64),
    `dc_lev_mult`         Nullable(Float64),
    `regime_size_mult`    Nullable(Float64),
    `market_ob_mult`      Nullable(Float64),
    `esof_size_mult`      Nullable(Float64)
)
ENGINE = MergeTree
ORDER BY (asset, ts)
TTL toDate(ts) + toIntervalDay(180);
