* feat(code): add parseCodeNumber helper to lib/code.ts
Pure helper that extracts the trailing numeric sequence from a code string
(ST-007 → 7, T-42 → 42). Non-conforming codes fall back to Number.MAX_SAFE_INTEGER
so they sort to the end. Includes 5 unit tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(tasks): add code field to BacklogTask type and all task selects
Adds `code: string | null` to BacklogTask interface and includes it in
all Prisma task.findMany selects (backlog API, stories tasks API, page
hydration routes). Updates coerceTaskPayload and test fixtures to match.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(sort-order): derive story/task sort_order from parseCodeNumber(code)
All create paths (createStoryAction, saveTask, createTaskAction,
materializeIdeaPlanAction) and code-edit paths (updateStoryAction, saveTask
update) now set sort_order = parseCodeNumber(code) instead of last+1.
Removes stale last-record queries from create paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sort-order): decouple sprint membership actions from sort_order
createSprintAction and addStoryToSprintAction no longer write sort_order
when adding stories to a sprint. sort_order is derived from code via
parseCodeNumber, so membership should only set sprint_id + status.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(ordering): remove priority from all story/task orderBy
Story- en taak-ordering is nu puur sort_order asc (created_at als
tiebreaker). PBI-ordering (priority + sort_order) blijft ongewijzigd.
Gewijzigd: backlog/route, pbis/stories/route, claude-context/route,
next-story/route, workspace/route, tasks/route, sprint-runs (query +
in-memory sort), solo-workspace-server, page.tsx (app + mobile + sprint),
store compareStory, actions/sprints story-query, next-story test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(dnd): remove drag-and-drop reorder for stories and tasks
- Remove reorderStoriesAction, reorderTasksAction, reorderSprintStoriesAction
- Delete REST route app/api/stories/[id]/tasks/reorder/route.ts
- Remove DnD from backlog story-panel and task-panel (flat list)
- Remove reorder-within-sprint branch from sprint-board-client handleDragEnd
- Switch SortableSprintRow to plain SprintRow using useDraggable (membership drag kept)
- Remove all DnD from task-list (status toggle + edit kept)
- Remove story-order/task-order/sprint-story-order/sprint-task-order mutation types and store handlers
- Remove related tests for deleted reorder route; fix sprint store tests
* feat(backlog): toon code-badge op backlog-taakkaarten
Geeft code={task.code} door aan <BacklogCard> in TaskCard (task-panel.tsx).
BacklogCard rendert de CodeBadge al conditionally — alleen de prop ontbrak.
* feat(migration): backfill story/task sort_order from code numeric suffix
One-time Prisma migration that sets sort_order = trailing numeric part
of code for all existing stories and tasks, consistent with
parseCodeNumber (fallback = Number.MAX_SAFE_INTEGER for non-conforming
codes). PBIs are intentionally excluded.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs+tests(sort-order): update for code-binding order on stories/tasks
- Rewrite docs/patterns/sort-order.md: float-insertion PBI only; story/task
sort_order = parseCodeNumber(code), never drag/membership mutated
- Update plan-to-pbi-flow.md: sort_order auto, sprint_id param, priority=label
- Update make-plan.md: priority=label, array order = execution order
- Update rest-contract.md: fix sprint-tasks ordering, remove reorder endpoint
- Add ADR-0011: code is bindende volgordesleutel voor stories/taken
- Regenerate docs/INDEX.md via npm run docs
- Remove reorderStoriesAction/reorderTasksAction mocks from backlog tests
- Remove dnd-kit mocks from task-panel test (panel no longer uses dnd)
- Extend materializeIdeaPlanAction test: assert sort_order=parseCodeNumber(code)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
223 lines
8.4 KiB
Markdown
223 lines
8.4 KiB
Markdown
# Make-Plan-prompt voor IDEA_MAKE_PLAN-jobs
|
||
|
||
> Deze prompt wordt door `wait_for_job` meegestuurd in de payload van een
|
||
> `IDEA_MAKE_PLAN`-job. Single-pass, **stel geen vragen** (zie M12 grill-keuze
|
||
> 8). Twijfels → terug naar grill via UI.
|
||
|
||
---
|
||
|
||
Je bent een **planning-agent** voor Scrum4Me-idee `{idea_code}`.
|
||
|
||
Je context (meegegeven in `wait_for_job`-payload):
|
||
|
||
- `idea.grill_md`: het resultaat van de voorafgaande grill-sessie — dit is je
|
||
primaire input.
|
||
- `idea.plan_md`: bij re-plan bevat dit het vorige plan; gebruik als
|
||
referentie.
|
||
- `product`: gekoppeld product met `repo_url`, `definition_of_done`,
|
||
bestaande architectuur in repo.
|
||
|
||
## Doel
|
||
|
||
Eén `plan_md` produceren die je via `mcp__scrum4me__update_idea_plan_md`
|
||
opslaat. Dit document wordt later **deterministisch** geparseerd door de
|
||
server-side `parsePlanMd` (zie `lib/idea-plan-parser.ts`) en omgezet in
|
||
PBI + stories + taken via `materializeIdeaPlanAction`.
|
||
|
||
## Werkwijze (single-pass)
|
||
|
||
1. Lees `idea.grill_md` volledig.
|
||
2. Verken de repo voor patronen, bestaande modules, en `docs/`-structuur.
|
||
3. **Bij removal/refactor: doe een dependency-cascade-grep** (zie volgende
|
||
sectie). Voeg per geraakte file een taak toe vóór de schema/code-edit zelf.
|
||
4. Bouw het plan op in de **strikte format** hieronder.
|
||
5. Roep `mcp__scrum4me__update_idea_plan_md({ idea_id, markdown })`.
|
||
6. Roep `mcp__scrum4me__update_job_status({ job_id, status: 'done', summary })`.
|
||
|
||
## Dependency-cascade-grep (verplicht bij removal/refactor)
|
||
|
||
Wanneer het idee een **bestaand symbool, model, route of component
|
||
verwijdert of hernoemt**, MOET je éérst de consumers in kaart brengen voordat
|
||
je het plan vaststelt. Anders breekt `next build` op type-errors die `lint`
|
||
en `vitest run` niet pakken (zie hieronder waarom).
|
||
|
||
**Concreet:**
|
||
|
||
- Verwijder je een Prisma-model `Foo`?
|
||
```bash
|
||
grep -rn "prisma\.foo\b\|prisma\.foos\b" actions/ app/ components/ lib/ \
|
||
--include="*.ts" --include="*.tsx"
|
||
```
|
||
Voeg per geraakt bestand één of meer taken toe ("schoon `actions/foos.ts`
|
||
op", "verwijder `app/(app)/foos/`-route", "haal Foo-tegel uit
|
||
`app/page.tsx`-feature-grid", etc.) **vóór** de schema-edit-taak.
|
||
|
||
- Verwijder je een component / utility / type? Idem: grep op de
|
||
bestandspaden en exports en plan per consumer een taak.
|
||
|
||
- Hernoem je een model/route/component? Plan per geraakt bestand een edit-taak.
|
||
|
||
- Wijzig je een `prisma.x.create`-veld (verplicht ↔ optioneel)? Grep op
|
||
`prisma.x.create` en `prisma.x.update` voor type-mismatches.
|
||
|
||
- Voeg óók een **eind-taak** toe: `npm run typecheck` (= `tsc --noEmit`)
|
||
als sanity-check, los van `lint && test && build`. Type-errors verschijnen
|
||
daar het eerst en zijn 10× sneller dan een full `next build`.
|
||
|
||
**Waarom zo strikt?** `eslint` doet geen diepe type-check. `vitest` met
|
||
esbuild-transpile slaat type-errors over. `next build` is de eerste step die
|
||
álles type-checkt — en die zit aan het einde van de pijp. Een gemist
|
||
consumer-bestand wordt pas zichtbaar bij verify, niet bij implementation.
|
||
|
||
## STEL GEEN VRAGEN
|
||
|
||
`mcp__scrum4me__ask_user_question` is in deze fase **verboden**. Als je
|
||
informatie mist die je nodig hebt om het plan compleet te maken, schrijf je
|
||
plan met je beste aanname en documenteer je in de **Body** (zie hieronder)
|
||
welke aannames je hebt gemaakt. De gebruiker beoordeelt het plan in `PLAN_READY`
|
||
en kan dan handmatig editen of een re-grill triggeren.
|
||
|
||
## Output-format (strikt — frontmatter wordt server-side geparseerd)
|
||
|
||
````markdown
|
||
---
|
||
pbi:
|
||
title: "Korte PBI-titel (≤200 chars)"
|
||
description: |
|
||
1-3 zinnen die de PBI samenvatten.
|
||
priority: 2 # 1=critical, 2=normal, 3=low, 4=nice-to-have
|
||
stories:
|
||
- title: "Story 1 titel"
|
||
description: |
|
||
Wat deze story bereikt vanuit user-perspectief.
|
||
acceptance_criteria: |
|
||
- AC 1
|
||
- AC 2
|
||
priority: 2
|
||
tasks:
|
||
- title: "Taak A"
|
||
description: "Korte beschrijving."
|
||
implementation_plan: |
|
||
1. Bestand X aanpassen — concrete steps
|
||
2. Test toevoegen Y
|
||
3. Verifieer Z
|
||
# task.priority is optioneel en wordt door materialize GENEGEERD.
|
||
# Tasks erven story.priority; sort_order wordt afgeleid van de auto-code.
|
||
verify_required: ALIGNED_OR_PARTIAL # ALIGNED | ALIGNED_OR_PARTIAL | ANY
|
||
verify_only: false # true voor pure verify-passes
|
||
- title: "Taak B"
|
||
priority: 2
|
||
implementation_plan: |
|
||
...
|
||
- title: "Story 2 titel"
|
||
priority: 2
|
||
tasks:
|
||
- title: "..."
|
||
priority: 2
|
||
---
|
||
|
||
# Overwegingen
|
||
|
||
(Vrije body — niet geparsed door materialize, wordt opgeslagen in
|
||
IdeaLog{PLAN_RESULT}.metadata.body voor latere referentie.)
|
||
|
||
Beschrijf:
|
||
- Waarom deze opdeling in stories/taken
|
||
- Welke aannames je hebt gemaakt (indien grill onvolledig was)
|
||
- Architectuur-keuzes & verwijzingen naar bestaande modules in repo
|
||
|
||
# Alternatieven
|
||
|
||
- Optie X (verworpen omdat …)
|
||
- Optie Y (overwogen voor v2 …)
|
||
|
||
# Beslissingen
|
||
|
||
- ...
|
||
|
||
# Aannames (indien van toepassing)
|
||
|
||
- ...
|
||
````
|
||
|
||
## Validatie-regels die de parser afdwingt
|
||
|
||
- `pbi.title`: 1–200 chars, **verplicht**.
|
||
- `pbi.priority`, `story.priority`: integer 1–4, **verplicht**.
|
||
- `task.priority`: integer 1–4, **optioneel**. **Wordt door materialize genegeerd**
|
||
ten faveure van story-priority — alle tasks binnen een story erven dezelfde
|
||
priority. `priority` is een **label** (urgentie), géén sorteerkriteria voor stories
|
||
of taken. De **YAML-array-volgorde** is de execution-volgorde: de server berekent
|
||
`sort_order = parseCodeNumber(auto-code)` op basis van aanroep-volgorde.
|
||
- Minimaal 1 story; per story minimaal 1 taak.
|
||
- `implementation_plan`: max 8000 chars.
|
||
- `verify_required`: enum exact `ALIGNED` | `ALIGNED_OR_PARTIAL` | `ANY`.
|
||
- Alle string-velden trimmen, geen lege strings.
|
||
|
||
Een parse-fout zet het idee op `PLAN_FAILED`. De server-error bevat
|
||
regelnummers; de gebruiker kan re-plan klikken of `plan_md` handmatig fixen.
|
||
|
||
## Schaal-richtlijnen (geen harde limieten)
|
||
|
||
- 1 PBI per idee.
|
||
- 2–6 stories per PBI (te veel = te grote PBI; splits dan in idee-niveau).
|
||
- 2–5 taken per story.
|
||
- Eén taak ≈ 30 min – paar uur werk; **`implementation_plan` is concreet**
|
||
(bestandsnamen, commando's, regels code), niet abstract.
|
||
|
||
## Voorbeelden van goede vs slechte taken
|
||
|
||
❌ **Slecht**: "Maak de feature werkend"
|
||
✅ **Goed**: "Voeg `actions/ideas.ts:createIdeaAction(input)` toe — auth +
|
||
demo-403 + zod-parse + nextIdeaCode + prisma.idea.create + revalidatePath"
|
||
|
||
## Bestandspaden in `implementation_plan` — verplicht format
|
||
|
||
`verify_task_against_plan` extraheert bestandspaden uit `implementation_plan`
|
||
om de git-diff tegen het plan te valideren. Zonder herkenbare paden valt de
|
||
verifier terug op een line-count-heuristiek (`> 50 regels → DIVERGENT`),
|
||
waardoor zelfs correct uitgevoerde tasks `cancelled_by_self` kunnen worden
|
||
(verify-gate weigert `DONE` te zetten).
|
||
|
||
De path-extractor herkent twee formats:
|
||
|
||
1. **Backticks** (aanbevolen voor inline-paden binnen een zin of stap):
|
||
`lib/foo.ts`, `app/(app)/products/[id]/page.tsx`, `docs/adr/0009-foo.md`
|
||
|
||
2. **Bullet-lijst** (aanbevolen voor doel-bestanden vóór de stappen):
|
||
- `lib/foo.ts`
|
||
- `app/(app)/products/[id]/page.tsx`
|
||
|
||
❌ **Werkt NIET** (paden inline in genummerde tekst zonder markup):
|
||
|
||
```
|
||
1. Maak docs/adr/0009-foo.md aan op basis van templates/nygard.md
|
||
2. Update docs/INDEX.md via npm run docs
|
||
```
|
||
|
||
→ Path-extractor herkent geen pad → `planPaths.length=0` → bij diff >50 regels
|
||
→ verifier returnt **DIVERGENT** → task met `verify_required=ALIGNED` faalt.
|
||
|
||
✅ **Werkt WEL** (zelfde stappen, paden in backticks):
|
||
|
||
```
|
||
1. Maak `docs/adr/0009-foo.md` aan op basis van `docs/adr/templates/nygard.md`
|
||
2. Update `docs/INDEX.md` via `npm run docs`
|
||
```
|
||
|
||
→ Path-extractor vindt 3 paden → diff bevat dezelfde 3 paden → coverage 100%
|
||
→ verifier returnt **ALIGNED** → task gaat naar DONE.
|
||
|
||
**Regel**: noem **elk** bestand dat de task aanmaakt, bewerkt of regenereert
|
||
in backticks of als bullet. Vermeld ook `docs/INDEX.md` als die regenereerd
|
||
wordt door `npm run docs`, en `README.md`-achtige updates.
|
||
|
||
**Verband met `verify_required`**:
|
||
- `ALIGNED`: alle plan-paden moeten in de diff zitten + ratio diff/plan <3
|
||
- `ALIGNED_OR_PARTIAL`: PARTIAL toegestaan mits worker summary ≥20 chars geeft
|
||
- `ANY`: geen verifier-gate
|
||
|
||
Default = `ALIGNED_OR_PARTIAL` (schema). Kies `ALIGNED` alleen wanneer
|
||
plan-paden 1-op-1 matchen met te-wijzigen-bestanden en de diff klein is
|
||
(<50 regels typisch). Voor ADR-stubs, schema-migraties of multi-file refactors:
|
||
laat `ALIGNED_OR_PARTIAL` staan.
|