Implementation Plans — next enhancement milestone
Generated by the improve skill on 2026-07-13 at commit d54a2a9, from an
8-cluster recon sweep (~95 evidence-cited findings), a 5-frame ideation pass
(48 raw ideas → 14 merged candidates, all 14 verified sound by a fresh-context
spot-check against HEAD), and a design-fit review of the dashboard additions.
Companion design artifacts: docs/ideation/2026-07-13-next-milestone-ideation.html
(ranked ideas + bases), docs/ideation/momentum-architecture-current.{drawio,png},
docs/ideation/momentum-milestone-featureset.{drawio,png}.
Execute in the order below unless dependencies say otherwise. Each executor: read the plan fully before starting, honor its STOP conditions, and update your row when done.
Execution order & status
| Plan | Title | Priority | Effort | Depends on | Status |
|---|---|---|---|---|---|
| 001 | Production safety rails — CI test gate, dead-man's switch, pg_dump backup | P1 | S | — | DONE |
| 002 | Dead-weight deletion — schwab/, grafana/, dead modules/tables/projections | P2 | S | 001 | DONE |
| 003 | Money-path hardening — daily self-restart, positive-evidence contract, reconcile, cage count | P1 | M | 001 | DONE |
| 004 | Learning flywheel — one population module, scheduled eod_replay + nightly_tune, atomic writes | P1 | M | 001 (002 rec.) | DONE |
| 005 | Entry-path unification + decision receipts | P2 | M | 001, 003, 004 | DONE |
| 006 | Experiment OS — pre-registered counterfactual experiments over logged fires (flagship) | P1 | L | 004 (005 rec.) | DONE |
| 007 | Operator control plane — dashboard truth + kill switch + effective config (step 1 = prod bug fix, ship early) | P2 | M | 001, 003 (006 for ledger data) | DONE |
| 008 | Conversion-signal model — measure if the labeled data separates winners | P1 | L | 006, 004 | MEASURED 2026-07-14 (corrected): the 0.514 was the liq1-dominated MIX. Scoped to live v1: CV AUC 0.641 — REAL signal, but it is ~entirely the VWAP gate the bot ALREADY runs (above-VWAP +1R 35.4% vs below 12.7%). Residual within above-VWAP = 0.526 ≈ noise. RVOL-fallback added (read-only test 2026-07-14): 0.526→0.535, within noise — RVOL adds nothing beyond VWAP. Verdict: VWAP is the whole story for current features; no second indicator. Only market-context + catalyst remain untested (forward-accrual only, negative prior). The lever is a different setup (premarket), not more ORB filters. |
| 010 | Premarket shadow entry — prove a FILL-ABLE edge before any live premarket order | P2 | L | 006, 009 | NO-GO (Step 1 measured 2026-07-15): premarket is a paper-fill mirage. pm1+fat-tail-exit expR: −0.50R @0.5% fill, −1.27R @1% (realistic thin book), −2.74R @2%, vs the ORB's −0.11R. The 22-min fat tail can't outrun the 1-2% premarket spread. STOP — do not build the live shadow track. The ORB's 5-min wait exists to trade in penny-spread regular-session liquidity. |
| 009 | Feature-population prerequisite — instrument v1/pm1 (market context, RVOL fallback, catalyst-on), then re-run 008's probe | P2 | L | 006, 008 | code DONE, awaiting supervised rebuild+probe (market context + thin-name RVOL fallback + SPY/QQQ ingest + enrichment-on + committed probe all landed & tested; Steps 4-5 rebuild/AUC run supervised). 2026-07-16: the 07-15 nightly job never fired (docker outage overlapped 20:00 ET) — 07-15 was a data hole (0 setup_events, no SPY ingest, no regime row). BACKFILLED supervised: SIP refetch + 50 v1 setups + 6 pm1 fires + SPY/QQQ ingest + regime row for 07-15. Accrual clock unbroken; verify tonight's 20:00 scheduler fires. |
| 011 | Regime gate — a FREE-data daily signal deciding whether the ORB trades today; metalabel P(our ORB profits this session), proven in the harness (walk-forward) before any live gate |
P1 | L | 006, 004, 009 | BACKTESTED ON PROD (2026-07-15) — VIABLE as a SHADOW damage-control signal, NOT yet a live gate. 266 walk-forward sessions: trade-always −0.111R/session (36% hit) → meta_v1 GATED −0.004R/session (48% hit), trading only the best ~32% of days; delta +0.107R in-sample, +0.128R OOS (recent 80 sessions), improves across 3 folds. threshold_v1 rule gates too little to matter. Leaky full-fit +0.61R ≫ walk-forward +0.078R confirms the walk-forward discipline was load-bearing; OOS holding = the edge is real. Verdict: turns a bleeding strategy roughly FLAT by sitting out bad regimes. FIRE-WEIGHTED harness (the LIVE v1 population — gap≥10%, vol≥300k — 2041 fires): BOTH experiments PASS their pre-registered bars (first PASS of the milestone) — regime_meta_v1 expR_delta +0.0965R, baseline −0.085R/fire → GATED +0.0117R/fire (POSITIVE on the real population, keeps ~33%); regime_threshold_v1 +0.083R but keeps only 26 fires (its pass = 'sit out 99%', thin/ignore). So on the actual tradeable population the gate is mildly POSITIVE, not just flat. DEPLOYED (shadow): scheduler runs build-features+score nightly; admin /api/regime/run button triggers on demand. LIVE-GATED IN PAPER (Step 5 shipped 2026-07-15, commit 0ac09d3): _regime_reject blocks fresh entries on unfavorable sessions, TRADING_REGIME_GATE_ENABLED=1 in both compose, fail-open everywhere. Blocker-1 (tape_regime not pre-open) resolved by DELETING tape_regime — measured 0.000 importance; LIVE feature set = breadth_rvol(vol_upto/avg, non-look-ahead) + spy_lagged + trailing. Takes effect on next deploy. Real-money promotion still a separate owner decision. 2026-07-16 AUDIT + FIX: the shipped live gate was structurally INERT — live_session_favorable read today's breadth_rvol from today's OWN setup_events rows, which the labeler only writes at 20:00 ET, so the fail-open guard returned None every live session (verified: no meta_live score + 1288 all-pass gate receipts on 07-16; the 07-15 'validation block' p=0.080 was computed PRE-guard on a zero-filled feature — an artifact, not a validation). Also found breadth_rvol was UNIT-CONTAMINATED: _session_context pooled all setup versions, and pm1 stores RAW cumulative premarket volume in relative_volume (median 261k) vs ratio tracks (~0.8) — ~240/267 historical sessions were pm1-raw-volume, and plan 009's v1 RVOL fallback was about to flip forward sessions to ratio units (07-15 rebuilt = 0.18), silently breaking the feature. FIX (same-day): breadth_rvol redefined pm1-ONLY (median premarket volume — the dominant historical source, unit-consistent, strictly pre-open knowable); live gate recomputes today's pm1 fires IN MEMORY from premarket minute_bars (pure compute_premarket_setups, no insert); _regime_reject retries fail-open verdicts every ~5 min instead of caching None all day (definite verdicts still once/day). regime_features rebuilt (267 sessions, labels unchanged), scores rewritten, fire-weighted re-validation vs the PRE-REGISTERED bars: regime_meta_v1 expR_delta +0.0570 (bar +0.05, n=2058, PASS — weaker than the contaminated +0.0965 but real), keeps 37%, baseline −0.078→gated −0.021; recent-80-session delta +0.149R/session (always −0.141 → gated +0.008, trading 29% of days). threshold_v1 +0.0766 but keeps 1% (sit-out-everything, ignore as before). Live check 07-16 on fixed code: breadth 612,819, verdict UNFAVORABLE — first genuine live decision. Adversarial review (19-agent, 9 findings) hardened the live path: previous_close falls back to the latest prior session's close when today's daily_bars row is absent intraday (else the gap basis silently flips to the premarket open = different fire population than training); verdicts before 9:50 ET are PROVISIONAL (re-scored ~5 min — ingest lag can truncate the premarket frame) and the first verdict at/after 9:50 is FINAL even when None (caps the scorer at a handful of runs/day instead of ~78 on quiet days — hot-path stall guard); NULL-breadth training rows excluded from the live fit (zero-fill taught a 'zero premarket volume' class the serve path can never produce); throttle datetime arithmetic moved inside the fail-open try. KNOWN ACCEPTED SKEW: live premarket volumes are scaled-IEX estimates vs the nightly SIP tape (up to ~25-50x low on symbols without a volume_ratio row) — regime_scores['meta_live'] vs the EOD label is the standing forward measure of whether this skew flips verdicts; revisit (intraday SIP refetch at 9:46+, 16-min embargo) if agreement is poor. Takes effect on next image deploy. Prior status below. CODE DONE + REVIEW-APPROVED (commit 5cef4aa), deploy-wired + backtested at 092d607. Built: research/regime.py (probe + walk-forward build-features/score), iv_regime_gate harness intervention (keep-or-zero, fail-open), regime_threshold_v1+regime_meta_v1 JSONs, 5 tests incl. the mutate-the-future leakage guard. Reviewer re-ran: 9 new + 35 existing experiments tests green, ruff clean, live paths untouched. HMM rung skipped (statsmodels absent). Research: docs/research/regime_notes.md. SUPERVISED next step (hits production Postgres — NOT done by the executor): python3 -m research.regime probe (Step-0 STOP gate) → build-features → score --model threshold_v1/meta_v1 → register+run+adjudicate the two experiments → record expR_delta + OOS/fold results here. Review findings to fold in at that point: (1) tape_regime = earliest setup's at-trigger (~9:35) reading, not strictly pre-open — fine for the shadow harness, must be lagged before Step-5 live promotion; (2) minor: _load_regime_favorable model_version has no None-guard (both JSONs set it, fail-open if absent). Honest prior unchanged: most promising AND most curve-fit-prone (~150-260 sessions); walk-forward + threshold-floor + OOS decide GO vs "no free-data regime signal at this sample size". |
| 012 | Dashboard order-limits verbosity + dead-column cuts (owner request 2026-07-16) | P2 | S | — | DONE (2026-07-17, review-APPROVED after 2 revision rounds; commits b349518+1f3ddca on advisor/012-dashboard-order-limits in worktree .claude/worktrees/plan012 — awaiting owner merge). Step 3 revised mid-execution: lifecycle events never carried limit/stop, enriched client-side via client_order_id join to d.orders. |
| 013 | Symbol drill-in: 24h candlestick + live buy/sell trade markers (TradingView Lightweight Charts v5.2, vendored) | P2 | M | 012 (soft — reuses its bracket-leg maps) | DONE (2026-07-17, review-APPROVED after 1 revision round; commits b4ad3d3+709e7a4 on worktree-agent-ae2ee0000d5e3a7eb — awaiting owner merge). Headless-browser render-verified. Executor surfaced 2 pre-existing out-of-scope defects: OrderFilledEvent has no side field (worked around via order_submitted sibling join in /api/chart) and GET /api/attribution 500s when DATABASE_URL unset (research/attribution.py hardcodes os.environ lookup). |
| 014 | Live decision trace — gate-receipt feed (value→threshold per gate) + chart reject markers | P2 | M | 013 (chart overlay half; feed panel standalone) | DONE (2026-07-17, review-APPROVED first pass, zero revisions; commit dd81dbb on worktree-agent-acb00535650deac1a — awaiting owner merge). Decision Trace panel (lazy-load + SSE-throttled), /api/decisions (clamped 500, case-insensitive, server-side epoch), collapsed reject markers merged into the chart's single markers primitive. |
| 015 | Backtest replay dashboard (/backtest) — theoretical entries/exits over past sessions under CURRENT settings, via Experiment-OS replay | P2 | L | 013 (chart component) | DONE (2026-07-17, review-APPROVED first pass; commit 8ac222a on worktree-agent-ae4d3f36e18c6e7a5 — awaiting owner merge). replay_window = assembly-only over harness primitives (same _entry_index/adverse-fill/R math); /api/backtest 45-session clamp + 10-min cache behind a dedicated lock; /backtest page with THEORETICAL banner + X-of-Y coverage line + per-trade drill-in (blue entry/purple exit markers). Deviations accepted: /api/chart gained backward-compatible date= anchor (72h cap couldn't reach old sessions); batching idiom taken from regime.py (plan's run() pointer was wrong). |
| 016 | EDGAR dilution enrichment — unbreak silent nightly refresh (UTC current_date bug + missing float_cache DDL) + pre-register dilution_veto_v1 keep-or-zero experiment | P2 | M | 006 | IN PROGRESS (2026-07-17) |
Status values: TODO | IN PROGRESS | DONE | BLOCKED (with one-line reason) | REJECTED (with one-line rationale)
Expected drift (read before running any plan's drift check)
Every plan stamps d54a2a9 and its drift check diffs against that commit. Executed
in order, later plans WILL see diffs from earlier ones (compose scheduler/db-backup
blocks from 001/003/004/006, workflow test job from 001, trading_execution/
run_live_paper changes from 003/004/005, telegram_bot from 001). That is EXPECTED
drift: verify only that the plan's quoted code excerpts still exist semantically
(line numbers may shift); STOP only on changes NOT attributable to a completed
plan in this series (check the status table above).
Dependency notes
-
001 first, always: it is the gate that makes every other plan's image push test-verified. 007's step 1 (the POST
NameErrorimport fix) is a production bug fix that may be cherry-picked ahead of everything. -
002 before the refactor-heavy plans (004/005) so they diff against a smaller surface; its production
DROP TABLEsection runs only after 001's backup exists. -
003 before 005/007: both build on its clean-shutdown/flatten semantics. Note the documented interaction: 007's
flatten_allcommand must not trigger 003's daily-restart exit (see 007 STOP conditions). -
004 before 006: every experiment population MUST come from
strategy/population.py— running experiments against a look-ahead population re-creates the exact artifact class (vr1/liq1) this milestone exists to kill. -
005 before 006 is recommended (receipts enrich replay + rank_one_bullet needs rank), but 006's bar-path replay works without it — the rank experiment just starts underpowered.
-
Postgres provisioning (owner): the only new DDL in the milestone is plan 006's
experiments/experiment_runs/experiment_verdictstables (full DDL inplans/006-experiment-os.md). Plans 001–005/007 add no tables. The owner said they will provision the database once the plan is solid — that means: apply 006's DDL (or let the harness's idempotent schema-apply do it on first run), and after 002 lands, optionally run its operatorDROP TABLElist post-backup. -
013 soft-depends on 012: the chart's entry/stop/target price lines reuse the bracket-leg maps (
stopBy/targetBy/entryLimitBy) 012 builds inrender(d). 013 alone must build them itself (STOP condition covers it). -
012/013/014/015 are UI/read-path only — zero overlap with plans 008-011's research/live-gate surface; safe to execute in parallel with any of them.
-
Recommended UI execution order: 012 → 013 → 014 → 015. 014's Decision Feed panel half can land before 013; its chart-overlay half can't. 015 consumes replay.py as-is — any plan that changes exit-sim semantics invalidates its honesty claim and must re-verify it.
-
015's data supply is the nightly setup_events build (plan 009's accrual) — a missed scheduler night is a missing day on /backtest; the page surfaces it via the "sessions replayed X of Y" line.
Queued defects (surfaced by plan 013/015 executors — owner-confirmed 2026-07-17, plan files pending)
- OrderFilledEvent has no
sidefield (storage/event_schema.py; sole emit sitealpaca_paper/execution.pypasses none). /api/chart works around it by joining the sibling order_submitted row — fix at the emitter so every consumer gets it. Live-path change: needs its own plan + tests, do NOT drive-by fix. - GET /api/attribution 500s when DATABASE_URL unset —
research/attribution.py:_connect()hardcodesos.environ["DATABASE_URL"], bypassing the storage facade's fallback chain everything else uses. Read-side, small. - Nightly scheduler's
regime build-featuresstep silently produced no row two nights running (07-15 full-outage, 07-16 step-level: setups+SPY landed, regime row didn't — backfilled supervised both times). Pull the scheduler container's stdout at 20:00 ET tonight; suspect thepython -m research.regimeCLI's store bootstrap (WATCHER_EVENT_DB_PATHdefault) diverging from DATABASE_URL in-container.
Findings considered and rejected (do not re-audit)
- Retest/pullback entry logic, scale-out partials, close-above-trigger confirmation from folklore — refuted in
docs/research/entry_conversion_research.md(external evidence + in-house tests); the research doc's "explicit do-nots". - Selection levers (confirmation-speed gate, float gating, liquidity floors, VWAP-reclaim promotion, liquid-breakout, leading-gainer detector, premarket-volume slices) — refuted at year scale per project memory; the validated population stays as-is.
- Reviving the NiceGUI controlroom — owner preference: :8765 is the dashboard.
- LISTEN/NOTIFY for dashboard change detection — deferred, not rejected: the shared cached signal (007 step 2) is the sufficient lazy fix; NOTIFY is the named upgrade path.
- TimescaleDB / pg extensions — not required at current scale (README's own assessment); revisit only if event/bar volume grows past what the hot-path index handles.
strategy/regime.pydeletion — already deleted at HEAD; recon reference was stale. NOTE: plan 011 introduces a NEW, unrelatedresearch/regime.py— an offline metalabel scorer (session-levelP(ORB profits today)), not the deleted live regime module. Different file, different purpose; do not conflate.- Schwab account sync revival for human-vs-bot comparison — the only non-delete rationale for schwab/; owner may veto 002's schwab deletion if that comparison is still wanted (plan 002 grep-gates it either way).