MoSCoW Prioritization, Personal Training OS (v1 / race-week MVP)¶
Artifact: 1.2 (Phase 1, Planning) · Owner: Product Owner (Primary User) Version: v1.0, RATIFIED by PO 2026-07-04 · Date: 2026-07-04
MoSCoW sorts scope into Must (no v1 without it), Should (important, not vital), Could (nice, first to drop), Won't (explicitly out this release). Discipline rule: Must-haves should be a minority of effort; if everything is Must, nothing is prioritized. "Won't" is a real decision, carried from the Charter's out-of-scope.
Prioritized at capability level (not all 94 requirements). Note: creating the 15 database structures is itself a Must (requirement ARCH-001); what varies below is how far each is seeded, viewed, and automated for v1.
Must, the race-week MVP (usable for the target races, 25 to 26 Jul)¶
| Capability | Serves |
|---|---|
| All 15 DBs created with schema, relationships & automation-ready fields | ARCH-001; foundation |
| People + Primary User & Secondary User as first-class | SC3 |
| Training Sessions core (log runs / races / workouts) | core |
| Races DB + Example Half Marathon & Example 5K seeds | race week |
| Historical run seeds (11-mi, 5-mi) | continuity |
| Running Shoes + auto mileage rollup | SC6 (gear) |
| Running Routes + generic seeds | core |
| Hockey game sessions + attendance / counts-toward-training logic | core rule |
| Dashboard + core views (This Week, Planned Runs, Races, Hockey both teams, Shoe Mileage) | SC1 |
| Calendar import for planned runs (low-effort capture) | SC2 |
| Core rollups (shoe mileage, hockey load) | SC4 |
Should, valuable; do if time before race week, else fast-follow¶
| Capability | Serves |
|---|---|
| Metrics / Check-ins usable (manual daily) | SC4 |
| Nutrition Log usable (manual) | future SC2 |
| Goals + Training Blocks with views | insight |
| Weekly Reviews (manual) | habit/SC1 |
| Exercise Library + Workout Templates populated | SC5 |
| ≥1 running + 1 strength + 1 hockey plan (linked/embedded materials) | SC5 |
| Hockey Drills + Resources seeded | SC5 |
Could, nice-to-have; first to drop under time pressure¶
| Capability | Serves |
|---|---|
| Richer insight dashboards (beyond mileage + load) | SC4+ |
| Embedded videos / extra plan materials | SC5+ |
| Equipment/balance-board nuance, extra routes | polish |
Won't (this release), deferred by Charter, revisit post-v1¶
| Deferred | Why / status |
|---|---|
| ~~Garmin live sync~~ | ✅ PROMOTED → SHIPPED as Increment 2 (2026-07-05). Was deferred for time; time recovered (ahead of schedule) → built. Increment 2 delivered both Garmin activities to Training Sessions (2a) and Garmin daily wellness metrics to Metrics/Check-ins (2b), plus the Withings weight sync to Metrics/Check-ins (2c, weight only). All live daily 06:00; operational evidence only (formal V&V outstanding). |
| Strava live sync | Scaffolded / prepped, BLOCKED on a paid Strava subscription (distinct from un-built deferrals: the integration is staged, see STRAVA-SETUP.md, and only the paid subscription gates go-live; no secrets configured yet). |
| ~~MyFitnessPal (nutrition)~~ | ✅ PROMOTED → SHIPPED as Increment 4 (2026-07-09), see Amendment v1.4 below. The compliant path identified here was taken = MFP Premium emailed CSV export ("Download Your Data" / "Meal Level Nutrition Details"), user-initiated and ToS-clean; automation/mfp_email_to_notion.py ingests it into the Nutrition Log at per-meal grain with every column. The export is one row per logged food (several per meal, no food-name column), so foods are summed into per-meal totals (nothing dropped). It stays true that MFP has no open API (partner-only) and scraping is ToS-barred (the scraper also broke on MFP's Dec-2025 SPA rewrite) and the Withings API does not expose nutrition/macros: that is exactly why the export route was used. The Gmail-relay auto-trigger (--gmail, IMAP + a Gmail App Password) is live and verified 2026-07-09: Primary User provisioned the GMAIL_APP_PASSWORD secret and the relay ran end-to-end (found the export email, downloaded it, aggregated + wrote the 71 meal rows, labeled the email PTOS-Nutrition-Ingested; a re-run finds 0 unprocessed), fully hands-off once the operator taps MFP "Download Your Data" (a manual --zip <export.zip> fallback also exists, and the graceful-skip when the secret is absent remains in code as a safety net). |
| Apple Health live sync | Deferred. No cloud API; needs an on-device Health Auto Export bridge, and is largely redundant with Garmin. |
| RAG / AI-insight capability | Charter §5. Candidate for a post-race-week Increment 4 (payoff grows with logged data). |
| Other life domains ("everything eventually") | Charter §5. Mission boundary, not a schedule call. Keep out. |
| Users beyond Primary User + Secondary User (family/friends/kids) | Charter §5. Keep out unless a real need appears. |
| ~~Auto-schedule hockey games into Training Sessions~~ | ✅ PROMOTED → SHIPPED as Increment 3 (2026-07-05). Upcoming games auto-create Planned Hockey sessions linked to the game; TBD bracket placeholders are filtered (team must be a named participant); the plan-vs-actual reconciler flips the row to Attended when the Garmin skate lands. Built to ADR-0003 (game DBs stay source-of-truth). |
PO ratification: ✅ 2026-07-04, accepted as drafted. SC5 (training-plan materials) accepted as Should / fast-follow: go-live (G6) may precede SC5, with materials landing shortly after race week.
Amendment v1.1 (2026-07-05): added one Won't-this-release item (auto-schedule hockey games) from UAT validation. Verification passed (built to ADR-0003) but validation flagged an expectation gap; PO disposition = accept MVP as-is, deferred automation logged above. No change to Must/Should/Could.
Amendment v1.3 (2026-07-05): re-triage after finishing Must+Should+Could ahead of schedule (build complete ~3 weeks before race week 25 to 26 Jul). "Won't" is a time-boxed decision, so two items were promoted out of Won't and shipped: (1) Garmin live sync → Increment 2, which delivered both Garmin activities (2a) and Garmin daily wellness metrics (2b), plus the Withings weight sync (2c, weight only); (2) auto-schedule hockey games → Increment 3 (this change). Also corrected drift: the Won't list had still shown Garmin as deferred after it shipped. Discovery run on the remaining integrations (MyFitnessPal, Apple Health) with findings folded into the Won't table above; Strava broken out as scaffolded-but-blocked (paid subscription). No change to Must/Should/Could scope. Change driver = capacity, logged in RAID.
Amendment v1.4 (2026-07-09): promoted MyFitnessPal (nutrition) out of Won't and shipped it as
Increment 4. The compliant export path already identified in the Won't table was built:
automation/mfp_email_to_notion.py ingests the MFP Premium emailed CSV export into the Nutrition Log at
per-meal grain, capturing every column (all macros incl. fat sub-types, plus micronutrients and per-meal
Time). The export is one row per logged food (several per meal, no food-name column), so foods are
summed into per-meal totals (nothing dropped). Schema extended per ADR-0007 (14 new Nutrition Log
properties). Automating the export trigger (headless browser) is ToS-barred, so the operator taps MFP
"Download Your Data"; everything after that tap is automated. The Gmail-relay auto-trigger (--gmail,
IMAP + a Gmail App Password) is live and verified 2026-07-09: Primary User provisioned the GMAIL_APP_PASSWORD
secret and the relay ran end-to-end (found the export email, downloaded it, aggregated + wrote the meal rows,
labeled the email done; a re-run finds 0 unprocessed), fully hands-off; a manual --zip <export.zip> fallback
also exists, and the graceful-skip when the secret is absent remains in code as a safety net. First ingest
2026-07-09: 24 days, 71 meal rows aggregated from 115 food-level export rows, idempotent. Operational
evidence only; not yet covered by the formal V&V suite (increment verification is a G7 / follow-up item).
No change to Must/Should/Could scope.