The Implementation Plan
Twenty-four design documents described a system that did not exist. This is the bridge: four phases in the order five constraints dictate, each with one falsifiable gate — and a gate that fails is fixed, never renegotiated.
What it is
The plan is deliberately narrow. It does not re-derive the design; it cites it, and where the two disagree the spec wins and the plan is wrong. It exists for three things: authorization — if the sequencing and the frozen interfaces are right, the build starts; scope control — a fence around the interesting parts that would cost us the necessary ones; and a definition of done — a phase is not finished when it compiles, it is finished when its gate passes.
Version 0.5, dated 2026-09-03, records Phases 0, 1 and 2 done. Phase 3 and Phase 1.5 are next.
Where we stood on 2026-08-31
An inventory measured, not remembered, at the moment the plan was written:
| Layer | State |
|---|---|
| Design documents | 24 — specified well past the point where more specification helps |
| Schema | 105 CREATE TABLE statements, reviewed by nobody but the author |
| Migrations | Zero, by standing rule |
| Entity layer | 6 of 105 tables |
| Trading engine | ~120 lines; a TODO where the system goes |
| FMP client | 3 methods — no news, no dividends, no forex |
| Infrastructure | Designed, not deployed — ~900 lines of Pulumi, nothing stood up |
| Strategies · backtester · tests | Zero, zero, zero |
Roughly 930 lines of C# across the six projects the engine uses. The gap between design maturity and code maturity was the defining fact of the project, and the reason the plan exists.
The five constraints that set the order
- No migrations until the first database is built. So Phases 1 and 2 had to run without touching MySQL — and could, because blob is the canonical store for everything they need.
- The news archive is a rolling 365-day window, and it is moving. Every month of delay is a month of history gone from our reach. The archiver went first for that reason alone, not because it is architecturally important. It is not.
- The design says build the backtester first. It is the only host that forces
decide(MarketState) → TargetWeightsinto existence; build the live engine first and the contract emerges by accident. - Live money is not in scope and will not be for a long time. No broker spec exists. Paper only, and mostly not even that.
- Infrastructure is deployed when a gate requires it. Three phases on a laptop; the estate at Gate 4.
Phase 0 — decided 2026-09-02
| # | Decision | Consequence |
|---|---|---|
| 4a | Build the schema, with additions | plutus.sql (123 tables) is the migration source; the first database was built from it into local MySQL 8 |
| 4b | A maintained MarketCalendarDays | Seeded from 8,456 SPY bar dates; 12.7k rows, one year added per year |
| 4c | Docker MySQL for run rows now | BacktestRuns and the trial registry real from the first Phase 2 run |
| 4d | Per-resolver recompute cadence — Allan's refinement | Technical, news and stress resolvers rerun every hourly window; macro, fundamentals and regime in the morning only, carried forward |
| 4e | Transcripts — open | 402 on our key, booked at $0 in two specs; FMP support emailed 2026-09-02 |

The phases
Three feeds,
from/to always, floor at today − 364; one gzipped blob per day, idempotent; gaps recorded, never toleratedpassedRegime and FRED series land frozen and as-of stamped; gated on three endpoints and an export job in the other repositorynext
The contracts, the point-in-time assembler, the bar store, the fill simulator, two controls and
dollar-mag7; the phase that matterspassedFirst migration from
plutus.sql; entities for the tables Phases 1–2 touch, not all of them; run rows pointed at blobs already writtennextPull, compute the world once, decide with the same code Phase 2 ran, execute simulated fills only; the scheduler and the resume ledgerlater
The gates
| Gate | Pass = | Result |
|---|---|---|
| 1 | 365 daily news blobs, valid, gap-free, byte-identical on re-run; tomorrow's arrives unattended | Passed 2026-09-01 — 364 days × 2 feeds, 0 missing, 4 random days verified; grades is snapshot-only by plan limit |
| 1.5 | Regime and macro snapshot lands unattended, byte-identical on re-run, degrades on staleness with a reason | Waiting on GMI-side work |
| 2 | Full-history spy-hold matches SPY total return within tolerance; run reproduces bit-identically | Passed 2026-09-03 — 1993-02-01 → 2026-09-02, 8,455 days: ×31.53 / 10.82 % against ×31.76 / 10.84 %, ΔCAGR −0.02 pp; 12/12 contract tests |
| 3 | Migration applies clean; the Phase 2 run reproduces and writes a run row; calendar table ≡ seed file | Next |
| 4 | Five unattended trading days; survives a mid-cycle kill with no duplicate order; journal schema matches the backtest | Later |

- IBKR / live orders — no broker spec; nothing has earned trust
- News processing — archiving is urgent, scoring is not
- The Claude lane — expensive per call; packet design unsettled
- The other ~50 resolvers — mechanical once two prove the pattern
- Tournament, intraday, admin UI, the learning loop
- Each is attractive and each would cost the phases above.
Phases 1 and 2: no agents, or nearly none — they set the contracts, and parallel work against unsettled interfaces produces merge debt that costs more than it saves. Phase 4 and beyond: the resolver ports, the entity backfill, per-strategy implementations against a frozen IStrategy — mechanical work against contracts that have stopped moving, done in batches with a review pass each.
One exception taken early: a read-only pass checking plutus.sql against the design standards before the human review.
- News licensing forbids retaining bodies — archive now, read terms in parallel; discarding later is possible, refetching is not
spy-holdwill not reconcile — that is the gate doing its job; it failed once and was fixed- The frozen contracts are wrong — cheapest to fix during review, which is what the contracts section is for
- FMP tier changes under us — the probe ritual is scripted; re-run it before any dependent phase