-- Migration: Create shadow_run table for 252+ trading-day model validation -- Purpose: Immutable append-only audit trail for shadow run results -- PIT Safety: published_at column enables point-in-time queries -- Idempotency: Schema exists → no-op; checksum validation prevents duplicate runs CREATE SCHEMA IF NOT EXISTS model_operations; CREATE TABLE IF NOT EXISTS model_operations.shadow_run ( run_id UUID PRIMARY KEY, model_id UUID NOT NULL, window_start DATE NOT NULL, window_end DATE NOT NULL, status VARCHAR(50) NOT NULL DEFAULT 'Pending', -- Performance metrics (JSONB for flexible schema versioning) metrics_json JSONB, -- Phase breakdown: Bull, Bear, Sideways, Volatility phase_analysis_json JSONB, -- Cost scenario analysis cost_analysis_json JSONB, -- False exit / reentry attribution false_exit_analysis_json JSONB, -- Validation gates: PBO ≤ 20%, DSR ≥ 95%, cost 2x positive validation_gates_json JSONB, -- Error context if status = Failed error_message TEXT, -- Audit timestamps created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, published_at TIMESTAMP, -- NULL = unpublished; populated when final CONSTRAINT check_window_order CHECK (window_start <= window_end), CONSTRAINT check_status CHECK (status IN ('Pending', 'DataBackfill', 'Replay', 'EvaluationComplete', 'Failed')) ); -- Indexes for common queries CREATE INDEX IF NOT EXISTS idx_shadow_run_model_created ON model_operations.shadow_run (model_id, created_at DESC); CREATE INDEX IF NOT EXISTS idx_shadow_run_status ON model_operations.shadow_run (status); CREATE INDEX IF NOT EXISTS idx_shadow_run_published_at ON model_operations.shadow_run (published_at); -- Table comments for documentation COMMENT ON TABLE model_operations.shadow_run IS '252+ trading-day model validation runs. Append-only immutable audit trail. PIT-safe: queries use published_at <= cutoff.'; COMMENT ON COLUMN model_operations.shadow_run.run_id IS 'Unique shadow run identifier. Idempotency key for job deduplication.'; COMMENT ON COLUMN model_operations.shadow_run.status IS 'Execution phase: Pending → DataBackfill → Replay → EvaluationComplete or Failed.'; COMMENT ON COLUMN model_operations.shadow_run.published_at IS 'Timestamp when results finalized. NULL = unpublished. Used for PIT queries (published_at <= @cutoff).'; COMMENT ON COLUMN model_operations.shadow_run.validation_gates_json IS 'Production readiness gates: {pbo_under_20: bool, dsr_above_95: bool, cost_2x_positive: bool, all_gates_passed: bool}';