fix(ideas): respecteer YAML-volgorde bij plan-materialize

Tasks erven nu story-priority i.p.v. eigen task.priority bij
materializeIdeaPlanAction. Worker sorteert op `priority ASC, sort_order ASC`;
gemixte task-priorities binnen één story zouden anders de YAML-volgorde
verstoren (e.g. tasks met priority 1/1/1/2/1/2 → worker-volgorde 1,2,3,5,4,6
i.p.v. 1,2,3,4,5,6).

- actions/ideas.ts: priority = s.priority bij task-create
- lib/schemas/idea.ts: task.priority optional (geaccepteerd, genegeerd)
- lib/idea-prompts/make-plan.md: documenteer dat task.priority genegeerd wordt
- __tests__/lib/idea-schemas.test.ts: test dat omitted task.priority slaagt

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-05-14 01:57:48 +02:00
parent 76c2efd27c
commit 0a040b721f
4 changed files with 36 additions and 4 deletions

View file

@ -128,4 +128,21 @@ describe('ideaPlanMdFrontmatterSchema', () => {
})
expect(r.success).toBe(false)
})
it('accepts plan with task.priority omitted (inherits story-priority via materialize)', () => {
const r = ideaPlanMdFrontmatterSchema.safeParse({
...validPlan,
stories: [
{
title: 'Story zonder task-priorities',
priority: 2,
tasks: [
{ title: 'Taak 1' }, // geen priority — moet geaccepteerd
{ title: 'Taak 2', verify_required: 'ALIGNED' },
],
},
],
})
expect(r.success).toBe(true)
})
})

View file

@ -738,7 +738,11 @@ export async function materializeIdeaPlanAction(
title: t.title,
description: t.description ?? null,
implementation_plan: t.implementation_plan ?? null,
priority: t.priority,
// Erf priority van de story zodat YAML-volgorde gerespecteerd
// blijft. Worker sorteert op `priority ASC, sort_order ASC`;
// gemixte task-priorities binnen één story zouden anders de
// YAML-volgorde verstoren (zie plan-fix task-volgorde-na-upload).
priority: s.priority,
sort_order: ti + 1,
status: 'TO_DO',
verify_required: t.verify_required ?? 'ALIGNED_OR_PARTIAL',

View file

@ -101,7 +101,8 @@ stories:
1. Bestand X aanpassen — concrete steps
2. Test toevoegen Y
3. Verifieer Z
priority: 2
# task.priority is optioneel en wordt door materialize GENEGEERD.
# Tasks erven story.priority; sort_order = positie in deze tasks-array.
verify_required: ALIGNED_OR_PARTIAL # ALIGNED | ALIGNED_OR_PARTIAL | ANY
verify_only: false # true voor pure verify-passes
- title: "Taak B"
@ -142,7 +143,12 @@ Beschrijf:
## Validatie-regels die de parser afdwingt
- `pbi.title`: 1200 chars, **verplicht**.
- `pbi.priority`, `story.priority`, `task.priority`: integer 14.
- `pbi.priority`, `story.priority`: integer 14, **verplicht**.
- `task.priority`: integer 14, **optioneel**. **Wordt door materialize genegeerd**
ten faveure van story-priority — alle tasks binnen een story erven dezelfde
priority. Reden: worker sorteert op `priority ASC, sort_order ASC`; gemixte
task-priorities zouden de YAML-volgorde verstoren. De YAML-volgorde *is* de
execution-volgorde — daar is `sort_order` (positie in de array) voor.
- Minimaal 1 story; per story minimaal 1 taak.
- `implementation_plan`: max 8000 chars.
- `verify_required`: enum exact `ALIGNED` | `ALIGNED_OR_PARTIAL` | `ANY`.

View file

@ -20,11 +20,16 @@ export type IdeaUpdateInput = z.infer<typeof ideaUpdateSchema>
const verifyRequiredEnum = z.enum(['ALIGNED', 'ALIGNED_OR_PARTIAL', 'ANY'])
// Task-level priority is geaccepteerd in het schema voor backward-compat,
// maar wordt door `materializeIdeaPlanAction` genegeerd ten faveure van
// story-priority. Reden: worker sorteert op `priority ASC, sort_order ASC`
// — gemixte task-priorities binnen één story zouden de YAML-volgorde
// verstoren. Auteurs hoeven het veld dus niet meer in te vullen.
const planTaskSchema = z.object({
title: z.string().min(1).max(200),
description: z.string().max(4000).optional(),
implementation_plan: z.string().max(8000).optional(),
priority: z.number().int().min(1).max(4),
priority: z.number().int().min(1).max(4).optional(),
verify_required: verifyRequiredEnum.optional(),
verify_only: z.boolean().optional(),
})