Archived
The signals and markets tables existed since Phase 2/5 but never had a writer; the replay engine (phase plan line 2.1) needs a per-(market, cycle) archive of what the strategy saw and decided. This wires them up: - signals: one row per evaluated market per cycle, now carrying INPUTS (news_sentiment, feat_*_lo, volume_24h, days_to_resolution) plus the existing outputs (probs, edges, gates, skip_reason). skip_reason is granular: unsupported/no_signals/prior_extreme/family/edge_net/ confidence/reentry_guard. news_budget_skipped distinguishes "GNews not asked" (5-query budget) from "no news". - ext_snapshots: one row per cycle with the ExternalSignals snapshot; signals rows join on cycle_ts. - markets: metadata upserted each cycle (replay rebuilds Market from it). - Retention: prune > SIGNALS_RETENTION_DAYS (default 90) once a day. - SIGNAL_RECORDER_ENABLED (default true) gates all DB writes; every write is try/except — the recorder can never break trading. Strategy changes are purely additive (record accumulation at each exit path of evaluate()); no weights, thresholds, gates or sizing touched, per the freeze in the current phase plan. Tests: 10 new deterministic tests (85 total passing). Schema migration dry-run validated against prod postgres inside a rolled-back transaction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>