Owner: Project manager (agent)
Source spec: concept.md
Last updated: 2026-10-24
This document is the execution plan for the concept. Where it conflicts with
concept.md, the concept wins; this file only adds sequencing, contracts, and
working agreements.
Deliver the eight MVP acceptance criteria in concept.md as executable,
reproducible evidence. The model stays deliberately simple; the lifecycle is
the product.
Out of scope: alternate datasets beyond the optional loader, custom SPA, Kubernetes, GPUs, hosted services, automated promotion (flag reserved only).
See decisions.md for rationale. Summary:
| ID | Decision |
|---|---|
| ADR-001 | Seeded synthetic dataset is the primary workload; breast-cancer loader is optional |
| ADR-002 | Promotion is manual, gated by a policy-checked, recorded decision; auto_promote flag reserved |
| ADR-003 | PostgreSQL stores prediction events and the active-model pointer |
| ADR-004 | Observability = MLflow UI + generated HTML/JSON reports + one minimal static status page |
| ADR-005 | Drift statistics are implemented in-repo; Evidently is an optional report renderer |
| ADR-006 | MLflow registry aliases are authoritative for artifacts; our Postgres table is authoritative for the served pointer |
| ADR-007 | Python 3.12 managed by uv; uv.lock is committed |
| ADR-008 | Tests are tiered: unit (no Docker), integration (Postgres/MLflow), e2e (Compose) |
Every wave ends with something runnable, tested, documented, and demonstrable. A wave is not complete until its exit gate passes from a clean environment.
| Wave | Stage | Goal | Exit gate | Size |
|---|---|---|---|---|
| W0 | Frame | Contracts, scaffold, CI stub, CLI skeleton | uv run pytest + lint green; contracts reviewed; no domain logic |
S |
| W1 | Phase 1 | Data generation/loading, fingerprinting, validation, split manifests | Two independent preparations produce identical fingerprints and split hashes; malformed input fails clearly | M |
| W2 | Phase 1 | Training pipeline + MLflow tracking | Complete, inspectable run; no leakage; rerun reproduces metrics/artifact hash | M |
| W3 | Phase 2 | Registry, transactional active pointer, promotion gate | Inferior candidate rejected with reasons; better approved; concurrent promotions → exactly one wins | L |
| W4 | Phase 2 | FastAPI serving, prediction events, rollback | /predict reports serving version; 422s are actionable; rollback visible next request, no rebuild |
M |
| W5 | Phase 3 | Monitoring, drift reports, traffic simulator, status page | Shift flagged; clean traffic not flagged; small samples guarded; drift ≠ performance loss | L |
| W6 | Phase 4 | Retraining loop, rollback hardening | Failed candidate leaves active untouched; rollback verified; operations idempotent | M |
| W7 | Evidence | Demo scripts, README, architecture/acceptance docs, full CI | Fresh clone → documented sequence → all 8 criteria observed; CI green | M |
Milestones: W2 = Phase 1, W4 = Phase 2, W5 = Phase 3, W7 = MVP.
Defined as Pydantic models in W0 and exported as JSON Schema. All later waves consume these; changes require a PM decision and a version bump.
Commitments made now that must be discharged by a later wave.
| Wave | Obligation | Source |
|---|---|---|
| W1 | Manifest records provenance for both the generator and the optional real loader — discharged in W1: generator_parameters records the generator math/regime and the WDBC loader provenance, license note, and label transform |
ADR-001 |
| W2 | Measure the baseline, recalibrate the provisional quality floors, record the change — discharged in W2: floors are now ROC-AUC 0.83 / precision 0.70 / recall 0.65 / F1 0.67, calibrated across five seeds | ADR-010 |
| W3 | Gate uses the calibrated floors; tests cover human rejection of an all-pass candidate | ADR-010 |
| W3 | Compare candidate and active on the candidate’s validation slice and record that slice in the decision | ADR-011 |
| W5 | Define concept-drift and performance-degradation thresholds; absent labels → not_evaluated |
ADR-010 |
| W7 | Choose and add the repository license before any public announcement | PM open item |
docs/acceptance.md from W7 onward.| Risk | Impact | Mitigation |
|---|---|---|
| MLflow / Evidently API churn | Rework, flaky tests | Pin versions; wrap behind internal interfaces |
| Compose stack slow on macOS | Integration flakiness | Healthchecks, pinned images, Docker-free unit tier |
| Pointer inconsistency under concurrency | Wrong model served | Postgres row lock; two-process test |
| “Improved candidate” not reproducible | Demo looks fabricated | Synthetic generator with a constructible regime shift |
| Determinism polluted by BLAS threads | Reproducibility gate fails | Pinned random_state and thread env |
| Scope growth into platform/UI work | Never ships | MLflow UI + generated pages only |
main is the integration branch. The PM commits and pushes completed work;
subagents do not commit or push.