--- title: "Herbruikbaar scripts/insert-milestone.ts" status: done audience: [maintainer, contributor] language: nl last_updated: 2026-05-03 applies_to: [] --- # Plan: herbruikbaar `scripts/insert-milestone.ts` ## Doel Eén commando dat een specifieke milestone (PBI + stories + tasks) uit de backlog leest en idempotent toevoegt aan de DB, zónder bestaande data te raken. Voor M8 nu, en voor M9..M∞ later. ## Bron-keuze: backlog ipv plan-bestand Twee bronnen denkbaar: - **`.Plans/-.md`** — freeform plan-tekst, niet gestructureerd, niet gecommit - **`docs/backlog/index.md`** — al strict gestructureerd, gecommit, single source of truth voor alle bestaande seed-pipelines Voorstel: het script leest de **backlog**. Workflow blijft natuurlijk: 1. Plan schrijven naar `.Plans/.md` (lokaal, draft) 2. Milestone-sectie + stories formaliseren in `docs/backlog/index.md` (PR) 3. Na merge: `npm run db:insert-milestone -- M8 [--product SCRUM4ME]` Eén canonical bron, geen ambiguïteit, en de bestaande parser doet 90% van het werk al. ## Wijzigingen ### 1. `prisma/seed-data/parse-backlog.ts` — tolerant maken Huidige parser kent alleen M0..M6 in `MILESTONE_PRIORITY/_GOAL/_SPRINT_STATUS` + asserts ≥8 milestones / ≥60 stories. M7 en M8 worden nu stilletjes overgeslagen. Concrete edits: - Voeg `M7` en `M8` toe aan de drie maps (M7: priority 4, sprint COMPLETED, goal "MCP-server voor Claude Code"; M8: priority 4, sprint COMPLETED, goal "Realtime updates voor Solo Paneel") - Voor onbekende sleutels: fallback naar `priority: 4`, `sprint_status: 'COMPLETED'`, `goal: `. Dat maakt M9..M∞ vanzelf bruikbaar zonder code-wijziging - Verwijder de strikte filter `KNOWN_KEYS.includes(...)` of verleg naar een "alle-M[\d.]+ headers" check - Voeg optionele `loadBacklog(repoRoot, { strict?: boolean })` toe. `strict: true` (default) behoudt de bestaande "≥8 milestones, ≥60 stories" asserts (zodat de seed niet stilletjes anders gedraagt). Insert-milestone roept met `strict: false` ### 2. `scripts/insert-milestone.ts` (nieuw, ~90 regels) ``` Usage: tsx scripts/insert-milestone.ts [--product ] [--dry-run] Default product code: SCRUM4ME ``` Logica: 1. Parse args; valideer dat milestone-key matcht `^M[\d.]+$` 2. `loadBacklog(repoRoot, { strict: false })` 3. Zoek milestone op `key`; faal helder met "milestone not found in docs/backlog/index.md" als ie er niet in staat 4. Lookup product via `code` (default `SCRUM4ME`); faal als niet gevonden 5. Upsert PBI: - `where: { product_id_code: { product_id, code: milestone.key } }` - sort_order = `(max(sort_order) van bestaande PBIs in product) + 1` als nieuw, anders ongemoeid 6. Voor elke story: - Upsert Story op `(product_id, code = story.ref)` - status = `'DONE'` of `'OPEN'` zoals gemarkeerd in markdown - sort_order, priority en pbi_id correct ingesteld 7. Voor elke task: bulk insert **alleen** als de story op dit moment 0 tasks heeft (idempotent — herhaling dupliceert niets) 8. Print samenvatting: `M8: PBI created, 6 stories upserted (1 created, 5 unchanged), 6 tasks created` 9. `--dry-run`: alle DB-calls overslaan, alleen wat het zou doen printen Edge cases: - Story-code conflict tussen producten: schema heeft `@@unique([product_id, code])` op Story dus dit is per-product safe - Tasks zonder `code` veld in DB (klopt — code wordt afgeleid van story.code + index in get_claude_context) - Demo-product: script accepteert `--product DEMO` o.i.d. — niet hardcoded SCRUM4ME ### 3. `package.json` script ```json "db:insert-milestone": "tsx scripts/insert-milestone.ts" ``` ### 4. Verificatie na implementatie - Dry-run eerst: `npm run db:insert-milestone -- M8 --dry-run` - Daarna echt: `npm run db:insert-milestone -- M8` - In Prisma Studio of via SQL: zie M8 PBI, 6 stories, 6 tasks onder SCRUM4ME-product - Tweede run: `npm run db:insert-milestone -- M8` → "0 created, 6 unchanged" — geen duplicaten - Niet-bestaande key: `npm run db:insert-milestone -- M99` → "milestone M99 not found" - Bestaande seed-flow blijft werken: `prisma db seed` met `strict: true` faalt nog steeds bij format-drift in de backlog ## Branch- en PR-strategie `scripts/insert-milestone.ts` is orthogonaal aan ST-801. Twee keuzes: - **A. Eigen mini-branch + PR** — `tooling/insert-milestone-script`, ~95 regels code, makkelijk reviewbaar, gemerged voordat M8 verder gaat. Daarna gebruiken om M8 in DB te zetten en met de implementatie door. - **B. Aan ST-801 plakken** — voegt scope toe aan een PR die al code ↔ infra-overschrijdend is (migratie + tools). Voorgestelde keuze: **A**. De tool is breder bruikbaar dan M8 alleen. ## Volgorde 1. Switch naar `main` (ST-801 blijft op zijn eigen branch staan) 2. Branch `tooling/insert-milestone-script` 3. Edit `parse-backlog.ts` (M7/M8 maps + tolerant + strict-mode option) 4. Schrijf `scripts/insert-milestone.ts` 5. Voeg `db:insert-milestone` toe aan `package.json` 6. Lokaal testen met M8 (dry-run + echt + tweede run) 7. Commit, push, PR 8. Na merge: tool gebruiken om M8 in DB te krijgen, daarna ST-802 oppakken op feat/ST-801-branch ## Geschatte size - ~10 regels parser-edit - ~95 regels nieuw script - ~1 regel package.json - ~25 regels test/usage doc in script-comment - 1 commit, 1 PR