* docs(dialog-pattern): add generic entity-dialog spec Introduceert docs/patterns/dialog.md als bron-of-truth voor elke create/edit/detail-dialog in Scrum4Me, ongeacht het achterliggende dataobject. Bevat 14 secties: uitgangspunten, stack, component- architectuur, layout, validatie, drielaagse demo-policy, submission, dialog-gedrag, theming, footer, triggers/URL-state, per-entiteit profile-template, out-of-scope, en een verificatie-checklist. Registreert het patroon in CLAUDE.md "Implementatiepatronen"-tabel zodat Claude (en mensen) de spec verplicht raadplegen voor elke nieuwe dialog. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(dialog-pattern): convert task spec + add pbi/story entity-profiles Reduceert docs/scrum4me-task-dialog.md van 507 naar ~140 regels: alle gedeelde regels verhuisd naar docs/patterns/dialog.md, dit document bevat nu alleen Task-specifieke velden, URL-pattern, status-veld, server actions, triggers en bewuste out-of-scope-keuzes. Voegt twee nieuwe entity-profielen toe voor bestaande dialogen: - docs/scrum4me-pbi-dialog.md (PbiDialog: state-based, code+title-rij, PbiStatusSelect, geen delete in v1) - docs/scrum4me-story-dialog.md (StoryDialog: state-based, header met status/priority badges, inline activity-log, demo-readonly-fallback, inline-delete-confirm i.p.v. AlertDialog) Beide profielen documenteren expliciet de "Bekende gaps t.o.v. generieke spec" zodat opvolgende PR's de afwijkingen kunnen rechtzetten of bewust kunnen accorderen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Added pdevelopment docs * docs(plans): add docs-restructure plan for AI-optimized lookup Audit of existing 39 doc files (~10.700 lines) and a phased restructure proposal aimed at minimising the tokens an AI agent has to read to find the right reference. Captures resolved decisions on language (English), ADR template (Nygard default with MADR escape-hatch), index generator (node script), and folder taxonomy. Proposal status — fase 1 to follow. * docs(adr): add ADR scaffolding (templates, README, meta-ADR) Set up docs/adr/ as the canonical home for architecture decisions: - templates/nygard.md — default four-section format (Status, Context, Decision, Consequences) for one-way-door decisions. - templates/madr.md — MADR v4 with YAML front-matter and explicit Considered Options for decisions where rejected alternatives matter. - README.md — naming convention (NNNN-kebab-case), template-selection guidance (Nygard default; MADR for auth, queue mechanics, agent integration), status lifecycle, and ADR roster. - 0000-record-architecture-decisions.md — meta-ADR establishing the practice itself, in Nygard format. Backfilling existing implicit decisions (base-ui-over-radix, float sort_order, demo-user three-layer policy, etc.) is fase 6 of the docs-restructure plan. * feat(docs): add docs index generator + initial INDEX.md scripts/generate-docs-index.mjs walks docs/**/*.md, parses YAML front-matter (or first H1 fallback) and a Nygard-style ## Status section, then writes docs/INDEX.md with grouped tables for ADRs, Specs, Plans (with archive subsection), Patterns, and Other. Pure Node 20 (no external deps); idempotent — running it twice produces byte-identical output. Excludes adr/templates/, the ADR README, INDEX.md itself, and any *_*.md sidecar file. Wire-up: - package.json: docs:index → node scripts/generate-docs-index.mjs Initial run indexed 35 docs across the existing structure; the generated INDEX.md is committed so the table is reviewable in the PR before hooking generation into a pre-commit step. * chore: ignore Obsidian vault and personal sidecar files Add .obsidian/ (Obsidian vault config) and _*.md (personal sidecar notes) to .gitignore so the docs/ tree can serve as canonical source of truth while still being usable as an Obsidian vault for personal authoring. The docs index generator already excludes the same _*.md pattern from INDEX.md. * docs(plans): add PBI bulk-create spec for docs-restructure Machine-parseable spec for an executor that calls the scrum4me MCP (create_pbi → create_story → create_task) to seed the docs-restructure work into the DB. - Section 1 (Context) is the PBI description; serves as task-context via mcp__scrum4me__get_claude_context. - Section 2 lists the 6 resolved decisions (English, MD3+styling merged, solo-paneel merged, .Plans archived, Nygard ADR default, node index script). - Section 3 records what already shipped on this branch so the executor doesn't duplicate the ADR scaffolding or index generator. - Section 4 carries the structured YAML graph: 1 PBI, 8 stories (one per phase), 39 tasks. product_id is REPLACE_ME — fill before running. - YAML validated with PyYAML; field schema sanity-checked. * docs(junk-cleanup): remove stub patterns/test.md * docs(junk-cleanup): archive .Plans/ to docs/plans/archive/ * docs(front-matter): add YAML front-matter to docs/ root * docs(front-matter): add YAML front-matter to patterns/ * docs(front-matter): add YAML front-matter to plans + agent files * docs(index): regenerate INDEX.md after front-matter pass * docs(naming): drop scrum4me- prefix from doc filenames * docs(naming): lowercase API.md and MD3 filenames * docs(naming): rename plan file to kebab-case ASCII * docs(naming): rename middleware.md to proxy.md (next 16) * docs(naming): polish CLAUDE.md doc-index after renames * docs(taxonomy): scaffold topical folders under docs/ * docs(taxonomy): move spec files into docs/specs/ * docs(taxonomy): move design/api/qa/backlog/assets into folders * docs(taxonomy): move agent-instruction-audit into decisions/ * docs(split): break architecture.md into 6 topical files * docs(split): merge solo-paneel-spec into specs/functional.md * docs(split): merge md3-color-scheme into design/styling * docs(trim): extract branch/commit rules into runbook * docs(trim): extract MCP integration into runbook * docs(adr): add 0001-base-ui-over-radix * docs(adr): add 0002-float-sort-order * docs(adr): add 0003-one-branch-per-milestone * docs(adr): add 0004-status-enum-mapping * docs(adr): add 0005-iron-session-over-nextauth * docs(adr): add 0006-demo-user-three-layer-policy * docs(adr): add 0007-claude-question-channel-design * docs(adr): add 0008-agent-instructions-in-claude-md + update README index * docs(index): regenerate after ADR 0001-0008 * docs(glossary): add docs/glossary.md * chore(docs): regenerate INDEX.md in pre-commit hook * docs(readme): link INDEX + glossary + agent instructions * feat(docs): add doc-link checker script * chore(docs): wire docs:check-links and docs npm scripts * ci(docs): block merge on broken doc links * docs(links): fix broken cross-references after restructure --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
355 lines
18 KiB
Markdown
355 lines
18 KiB
Markdown
---
|
|
title: "Tweede Claude Agent — Planning Agent"
|
|
status: proposal
|
|
audience: [maintainer, contributor]
|
|
language: nl
|
|
last_updated: 2026-05-03
|
|
applies_to: []
|
|
---
|
|
|
|
# Plan: Tweede Claude Agent — Planning Agent (PBI/Story → children)
|
|
|
|
> **Eerder goedgekeurd plan in deze file:** *Scrum4Me v1.0 Release* (mobile shell + sprint-snapshots + release-discipline). Beschikbaar in chat-history; te verhuizen naar `docs/plans/v1-release.md` op een later moment. Dit nieuwe plan vervangt de plan-file inhoudelijk niet — het v1.0-werk blijft van kracht parallel hieraan.
|
|
|
|
---
|
|
|
|
## Context
|
|
|
|
**Wat de gebruiker wil:** twee gespecialiseerde Claude-agents, elk met eigen context.
|
|
|
|
| Agent | Doel | Context | Status |
|
|
|---|---|---|---|
|
|
| **Implementation Agent** | Codeert één task af → branch + PR | Code-repo (filesystem), `implementation_plan`, story, pbi, sprint, repo_url | ✅ Live (M13 / ST-1111) |
|
|
| **Planning Agent** *(nieuw)* | Genereert children: PBI→stories of story→tasks (incl. `implementation_plan` per task) | Specs + architectuur + patterns (filesystem in Scrum4Me-checkout), parent-record, bestaande children | ❌ Te bouwen |
|
|
|
|
**Wat al staat (hergebruikbaar):**
|
|
|
|
- `ClaudeJob`-model met state-machine `QUEUED→CLAIMED→RUNNING→DONE/FAILED`, `CANCELLED`-pad, stale-cleanup >30min
|
|
- `ClaudeWorker`-model voor presence-heartbeat
|
|
- SSE-pijplijn op `/api/realtime/solo` met payload-routing op `user_id + product_id`
|
|
- MCP-tools `wait_for_job`, `update_job_status`, `get_claude_context`, `create_pbi`, `create_story`, `create_task`, `update_task_plan`, `log_implementation`
|
|
- Idempotency-pattern: max 1 actieve job per resource
|
|
|
|
**Vastgelegde keuzes (uit AskUserQuestion-sessies):**
|
|
|
|
1. Agent kan **beide** niveaus: PBI→stories én story→tasks (één agent, twee modi via `target_type`)
|
|
2. Output: items **direct in DB** aanmaken via bestaande `create_*`-tools — geen review-stap in v1
|
|
3. Context: **lokaal draaien + filesystem-toegang** tot Scrum4Me-checkout (zoals impl-agent al doet)
|
|
4. Rol-scheiding: **`ClaudeJob.kind` enum** (`IMPLEMENTATION` | `PLANNING`) — één table, polymorf
|
|
5. Bestaande children: **aanvullen** — agent leest bestaande titels en voegt alleen ontbrekende toe
|
|
6. Live feedback: **stille SSE + status-pill** op de PBI/Story-card; geen aparte modal
|
|
7. MCP-shape: **bestaande `wait_for_job` uitbreiden** met `accept_kinds: string[]`-arg, default `['IMPLEMENTATION']` (backwards-compat)
|
|
|
|
---
|
|
|
|
## Approach (8 stappen)
|
|
|
|
### Stap 1 — Schema-uitbreiding
|
|
|
|
**`prisma/schema.prisma`:**
|
|
|
|
```prisma
|
|
enum ClaudeJobKind {
|
|
IMPLEMENTATION
|
|
PLANNING
|
|
}
|
|
|
|
enum PlanningTargetType {
|
|
PBI
|
|
STORY
|
|
}
|
|
|
|
enum ApiTokenKind {
|
|
IMPLEMENTATION
|
|
PLANNING
|
|
// beide kinds simultaan = afzonderlijke tokens; eenvoudiger dan multi-kind-flag
|
|
}
|
|
|
|
model ClaudeJob {
|
|
// ... bestaande velden ...
|
|
kind ClaudeJobKind @default(IMPLEMENTATION)
|
|
task_id String? // wordt nullable — planning-jobs hebben geen task
|
|
task Task? @relation(fields: [task_id], references: [id], onDelete: Cascade)
|
|
planning_target_type PlanningTargetType?
|
|
planning_target_id String?
|
|
|
|
@@index([kind, status])
|
|
@@index([planning_target_type, planning_target_id, status])
|
|
}
|
|
|
|
model ApiToken {
|
|
// ... bestaande velden ...
|
|
kind ApiTokenKind @default(IMPLEMENTATION)
|
|
}
|
|
|
|
model ClaudeWorker {
|
|
// ... bestaande velden ...
|
|
// accepted_kinds wordt afgeleid uit token.kind (geen extra kolom nodig)
|
|
}
|
|
```
|
|
|
|
**Constraint via DB-check (CHECK constraint of app-level):** een `ClaudeJob` heeft óf `task_id` (kind=IMPLEMENTATION) óf `planning_target_*` (kind=PLANNING). Nooit beide leeg, nooit beide gevuld.
|
|
|
|
**Migratie:** alle bestaande rijen krijgen `kind=IMPLEMENTATION` + `apiToken.kind=IMPLEMENTATION` als default. Backwards-compatible.
|
|
|
|
**Bestand:** `prisma/migrations/<date>_planning_job_kind/migration.sql`
|
|
|
|
### Stap 2 — Status-mappers + Zod-schemas
|
|
|
|
- `lib/claude-job-status.ts` — voeg `kind` toe aan API-shape (lowercase: `implementation` | `planning`)
|
|
- `lib/schemas/claude-job.ts` (NEW of MODIFY) — discriminated union op `kind`
|
|
- `lib/schemas/planning-target.ts` (NEW) — `{ type: 'PBI'|'STORY', id: string }` validator
|
|
|
|
### Stap 3 — Server actions
|
|
|
|
**`actions/claude-jobs.ts`** uitbreiden:
|
|
|
|
```ts
|
|
export async function enqueuePlanningJobAction(input: {
|
|
productId: string
|
|
target: { type: 'PBI' | 'STORY', id: string }
|
|
}): Promise<EnqueueResult>
|
|
```
|
|
|
|
Logica:
|
|
1. Auth-scope-check (`productAccessFilter`) — target moet binnen product zitten
|
|
2. Demo-block (`session.isDemo` → 403)
|
|
3. Idempotency: weiger als er al een `PLANNING`-job actief is voor dit `(target_type, target_id)`
|
|
4. Insert `ClaudeJob` met `kind=PLANNING`, `task_id=null`, `planning_target_*` ingevuld
|
|
5. `pg_notify('scrum4me_changes', { type: 'claude_job_enqueued', kind: 'planning', ... })`
|
|
|
|
`cancelClaudeJobAction` (bestaand) blijft werken — accepteert nu ook PLANNING-jobs (zelfde state-machine).
|
|
|
|
### Stap 4 — SSE-routing
|
|
|
|
**`app/api/realtime/solo/route.ts`:**
|
|
|
|
- Bestaande `claude_job_*`-events krijgen `kind` in payload
|
|
- Bij connect: `claude_jobs_initial`-event bevat ook actieve PLANNING-jobs van vandaag
|
|
- Filter blijft `user_id + product_id` — geen extra topic nodig
|
|
|
|
### Stap 5 — UI: triggers + status-pills
|
|
|
|
**Trigger in beide dialog-profielen** (geprofileerd in PR #45):
|
|
|
|
| Locatie | Knop-label | Target |
|
|
|---|---|---|
|
|
| `components/backlog/story-dialog.tsx` (edit-mode) | `🤖 Genereer taken met Claude` | `{ type: 'STORY', id: story.id }` |
|
|
| `components/backlog/pbi-dialog.tsx` (edit-mode) | `🤖 Genereer stories met Claude` | `{ type: 'PBI', id: pbi.id }` |
|
|
|
|
Knop-gedrag:
|
|
- `<DemoTooltip show={isDemo}>` rond knop (laag 3 demo-policy)
|
|
- `disabled` als er al een PLANNING-job actief is voor deze target (live via SSE-store)
|
|
- Tooltip bij disabled: "Plan-job al gestart — wachten op resultaat"
|
|
- Klik → `enqueuePlanningJobAction` → toast "Plan gestart" → dialog blijft open zodat user resultaat ziet binnenkomen
|
|
|
|
**Status-pill component (NEW):**
|
|
|
|
`components/shared/planning-job-pill.tsx` — kleine badge die de status van een lopende PLANNING-job toont:
|
|
- `QUEUED` — grijs, "In wachtrij"
|
|
- `CLAIMED / RUNNING` — blauw met spinner, "Plan wordt gegenereerd…"
|
|
- `DONE` — groen, fade-out na 5s
|
|
- `FAILED` — rood, klikbaar voor error-detail
|
|
- `CANCELLED` — niet getoond (verwijdert pill)
|
|
|
|
Plaatsing:
|
|
- Op `PbiList`-card naast PBI-titel (rechts)
|
|
- Op `StoryPanel`-card naast story-titel (rechts)
|
|
- In `PbiDialog` / `StoryDialog`-header (edit-mode) als large variant
|
|
|
|
**Live updates:** bestaande `useClaudeJobsStore` (Zustand, populated uit SSE) — alleen `kind` toevoegen aan filter-helpers.
|
|
|
|
### Stap 6 — MCP-tools (`mcp` repo, aparte PR)
|
|
|
|
**Wijziging 1 — bestaande tool uitbreiden:**
|
|
|
|
```ts
|
|
// wait_for_job tool input schema
|
|
{
|
|
accept_kinds?: ('IMPLEMENTATION' | 'PLANNING')[] // default: ['IMPLEMENTATION']
|
|
wait_seconds?: number // bestaand
|
|
}
|
|
```
|
|
|
|
Server-side: `WHERE kind = ANY($1) AND status = 'QUEUED'` in de `FOR UPDATE SKIP LOCKED`-query. Token-kind moet ook compatibel zijn (token.kind `IN` accept_kinds-overlap).
|
|
|
|
Response-shape voegt `kind` toe; voor `PLANNING`-jobs vervangt `task` door `planning_target` met embedded record:
|
|
|
|
```ts
|
|
{
|
|
job_id: string
|
|
kind: 'IMPLEMENTATION' | 'PLANNING'
|
|
product: { id, name, repo_url, ... }
|
|
// IMPL-only:
|
|
task?: { ..., implementation_plan, story, pbi, sprint }
|
|
// PLANNING-only:
|
|
planning_target?: {
|
|
type: 'PBI' | 'STORY'
|
|
pbi?: { id, code, title, description, priority, status, existing_stories: [{ id, code, title, priority }] }
|
|
story?: { id, code, title, description, acceptance_criteria, priority, status, pbi: {...}, existing_tasks: [{ id, title, priority, status }] }
|
|
}
|
|
}
|
|
```
|
|
|
|
**Wijziging 2 — nieuwe MCP-tool:**
|
|
|
|
`get_planning_context(target_type, target_id)` — losstaande lookup voor agent die handmatig een planning wil starten zonder job-claim. Optioneel; `wait_for_job` retourneert dezelfde data al.
|
|
|
|
**Geen nieuwe write-tools nodig:** bestaande `create_story` + `create_task` + `update_task_plan` werken al.
|
|
|
|
**Schema-sync:** vendor/scrum4me submodule update na Scrum4Me-PR merge.
|
|
|
|
### Stap 7 — Agent-prompt + lokale Claude-command
|
|
|
|
In de Scrum4Me-checkout (of in een gedeelde plek voor agent-prompts) twee Claude Code commands:
|
|
|
|
**`/implement-next-story`** — bestaand, gebruikt `wait_for_job({ accept_kinds: ['IMPLEMENTATION'] })`
|
|
|
|
**`/generate-plan`** — nieuw:
|
|
|
|
Korte prompt-flow:
|
|
1. `wait_for_job({ accept_kinds: ['PLANNING'], wait_seconds: 600 })` — claim
|
|
2. Lees `planning_target` uit response (PBI of STORY) + `existing_*`
|
|
3. **Lees lokale docs uit Scrum4Me-checkout:**
|
|
- `docs/specs/functional.md` (functioneel kader)
|
|
- `docs/architecture.md` (technisch kader)
|
|
- `docs/patterns/*.md` (relevante patterns op basis van target-titel/-beschrijving)
|
|
- `docs/design/styling.md` als target UI-werk betreft
|
|
4. Bedenk children:
|
|
- Voor `STORY`-target: 3-7 taken met titel, korte beschrijving, `implementation_plan` (verwijst naar relevante patterns + bestanden), priority
|
|
- Voor `PBI`-target: 2-5 stories met titel, beschrijving in user-story-format, acceptance_criteria, priority
|
|
5. Filter ontbrekende items: skip wat overlapt met `existing_*` (titel-match)
|
|
6. Voor elk: `create_task` of `create_story` via MCP
|
|
7. `update_job_status({ status: 'DONE', summary: 'Aangemaakt: 4 taken / 0 overgeslagen (titel-overlap)' })`
|
|
|
|
Bij failure: `update_job_status({ status: 'FAILED', error })` + toast voor user.
|
|
|
|
**Mens-rolverdeling:** twee Claude Code-sessies tegelijk draaien (één met `/implement-next-story` running, één met `/generate-plan` running). Beide claimen alleen hun eigen kind via `accept_kinds`. Dezelfde gebruiker-token of twee aparte (afhankelijk van hoe je workers wilt scheiden).
|
|
|
|
### Stap 8 — Tests
|
|
|
|
| Test | Locatie |
|
|
|---|---|
|
|
| `enqueuePlanningJobAction` — auth, demo, idempotency, scope | `__tests__/actions/claude-jobs-planning.test.ts` |
|
|
| Schema-mapper voor `kind` + `planning_target_*` | `__tests__/lib/claude-job-status.test.ts` |
|
|
| SSE-event format met `kind` | `__tests__/api/realtime-solo-planning.test.ts` |
|
|
| Status-pill rendering per status | `__tests__/components/shared/planning-job-pill.test.tsx` |
|
|
| Knop disabled-state in StoryDialog/PbiDialog bij actieve job | `__tests__/components/backlog/dialog-planning-button.test.tsx` |
|
|
|
|
MCP-tools testen in `mcp` repo (aparte PR).
|
|
|
|
---
|
|
|
|
## Critical files
|
|
|
|
### Scrum4Me-repo
|
|
|
|
| File | Action | Reden |
|
|
|---|---|---|
|
|
| `prisma/schema.prisma` | MODIFY | `ClaudeJobKind`, `PlanningTargetType`, `ApiTokenKind` enums + nullable `task_id` + `planning_target_*` velden |
|
|
| `prisma/migrations/<date>_planning_job_kind/` | NEW | Migratie + check-constraint |
|
|
| `lib/claude-job-status.ts` | MODIFY | `kind` in API-shape |
|
|
| `lib/schemas/claude-job.ts` | NEW/MODIFY | Discriminated union op `kind` |
|
|
| `lib/schemas/planning-target.ts` | NEW | Target-validator |
|
|
| `actions/claude-jobs.ts` | MODIFY | `enqueuePlanningJobAction` toevoegen, idempotency uitbreiden |
|
|
| `app/api/realtime/solo/route.ts` | MODIFY | `kind` in payload, initial-state ook PLANNING-jobs |
|
|
| `stores/claude-jobs-store.ts` (of vergelijkbaar) | MODIFY | `kind`-filter helpers |
|
|
| `components/backlog/story-dialog.tsx` | MODIFY | "Genereer taken"-knop + status-pill in header |
|
|
| `components/backlog/pbi-dialog.tsx` | MODIFY | "Genereer stories"-knop + status-pill in header |
|
|
| `components/backlog/story-panel.tsx` | MODIFY | Status-pill op story-card |
|
|
| `components/backlog/pbi-list.tsx` | MODIFY | Status-pill op pbi-card |
|
|
| `components/shared/planning-job-pill.tsx` | NEW | Generic pill-component |
|
|
| `docs/patterns/claude-agent-roles.md` | NEW | Pattern-doc: één table, kind-enum, accept_kinds-arg, lokale agent-prompts |
|
|
| `docs/architecture.md` | MODIFY | Sectie "Claude Agents" uitbreiden — twee rollen, schema, queue, prompts |
|
|
| `docs/specs/dialogs/pbi.md` | MODIFY | Sectie "Speciale gedragingen → Planning-trigger" toevoegen |
|
|
| `docs/specs/dialogs/story.md` | MODIFY | Idem |
|
|
| `docs/specs/dialogs/task.md` | MODIFY | Vermelden dat tasks ook door planning-agent kunnen ontstaan |
|
|
| `__tests__/actions/claude-jobs-planning.test.ts` | NEW | |
|
|
| `__tests__/lib/claude-job-status.test.ts` | MODIFY | `kind`-mapping testen |
|
|
| `__tests__/api/realtime-solo-planning.test.ts` | NEW | |
|
|
| `__tests__/components/shared/planning-job-pill.test.tsx` | NEW | |
|
|
| `__tests__/components/backlog/dialog-planning-button.test.tsx` | NEW | |
|
|
|
|
### mcp repo (aparte PR, na Scrum4Me-merge)
|
|
|
|
| File | Action |
|
|
|---|---|
|
|
| `src/tools/wait_for_job.ts` | MODIFY — `accept_kinds`-arg + polymorf response |
|
|
| `src/tools/get_planning_context.ts` | NEW (optioneel, helper) |
|
|
| `src/types/job.ts` | MODIFY — kind + planning_target |
|
|
| `src/prompts/generate-plan.md` | NEW — Claude command-prompt |
|
|
| `vendor/scrum4me/` (submodule) | UPDATE — na Scrum4Me-merge |
|
|
|
|
---
|
|
|
|
## Volgorde van uitvoering
|
|
|
|
1. **Schema + migratie + status-mapper** (Stap 1+2) — eigen commit, geen UI-impact
|
|
2. **Server action `enqueuePlanningJobAction` + tests** (Stap 3) — werkt headless via curl/test
|
|
3. **SSE-payload uitbreiden + claude-jobs-store** (Stap 4) — backend pipe klaar
|
|
4. **Status-pill component + tests** (Stap 5a) — losstaande primitive
|
|
5. **Trigger-knoppen in StoryDialog + PbiDialog** (Stap 5b) — UI-trigger werkt, agent nog niet
|
|
6. **Pause** — verifieer end-to-end met handmatig insert in `claude_jobs` (kind=PLANNING) of via mock-MCP-call
|
|
7. **MCP-PR in mcp repo** (Stap 6) — `wait_for_job` uitbreiden, types updaten
|
|
8. **Lokaal `/generate-plan`-command schrijven + testen** (Stap 7) — agent claimt, leest, schrijft
|
|
9. **End-to-end test** (Stap 8) — story → klik knop → agent rendert taken → SSE → live in TaskPanel
|
|
10. **Docs-PR** — pattern-doc `claude-agent-roles.md`, architecture-update, dialog-profielen aanvullen
|
|
|
|
Branch-naming: `feat/M15-planning-agent` (Scrum4Me) + `feat/planning-agent` (mcp).
|
|
|
|
Conform CLAUDE.md "branch-per-milestone": commits accumuleren lokaal, pushen pas na gebruikerstest.
|
|
|
|
---
|
|
|
|
## Verification
|
|
|
|
1. `npm run lint && npm test && npm run build` groen
|
|
2. **Schema-migratie:** bestaande `claude_jobs`-rijen krijgen `kind=IMPLEMENTATION`; check-constraint blokkeert ongeldige combinaties
|
|
3. **Idempotency:** twee keer klikken op "Genereer taken" → tweede klik geeft toast "Plan-job al gestart", knop disabled
|
|
4. **Demo-block:** demo-user ziet knop disabled met DemoTooltip; server action returnt 403 als je 'm toch aanroept
|
|
5. **SSE live:** trigger planning-job → status-pill verschijnt op story-card binnen 1s zonder refresh
|
|
6. **End-to-end:** lokale `/generate-plan` agent claimt job, leest target via `wait_for_job`, leest 3-4 docs uit Scrum4Me-checkout, maakt 3-5 taken via `create_task`, status DONE → taken zichtbaar in TaskPanel zonder refresh
|
|
7. **Cancel-flow:** gebruiker kan vanuit dialog een running PLANNING-job cancellen → status-pill verdwijnt, agent ziet job-status `CANCELLED` bij volgende `update_job_status`
|
|
8. **Cross-kind isolation:** een implementation-agent met `accept_kinds=['IMPLEMENTATION']` (default) ziet PLANNING-jobs niet; idem omgekeerd
|
|
9. **Aanvullen-policy:** trigger op story die al 2 taken heeft — agent voegt alleen ontbrekende toe (logged in summary: "Aangemaakt: 3 / Overgeslagen: 2 (titel-overlap)")
|
|
10. **Documentatie:** `docs/patterns/claude-agent-roles.md` beschrijft beide agent-rollen, hun job-flow, en hoe je een derde agent zou toevoegen
|
|
|
|
---
|
|
|
|
## Open punten (na approval expliciet maken)
|
|
|
|
1. **Token-strategie:** krijgt elke agent-rol een eigen ApiToken (cleaner, twee credentials), of bestaat er één multi-kind-token per user? *Voorstel: aparte tokens — één per kind. Gebruiker beheert ze in Settings.*
|
|
2. **Concurrency in 1 worker:** mag `accept_kinds: ['IMPLEMENTATION', 'PLANNING']` (één worker pakt allebei)? *Voorstel: ja, technisch toegestaan, maar in v1 raad je af want context-pollution. Documenteren als "kan, maar gebruik gescheiden processen".*
|
|
3. **Doc-selectie:** hoe bepaalt de agent welke `docs/patterns/*.md` relevant zijn? *Voorstel: lees `docs/patterns/`-index op + match op keywords uit target-titel/-beschrijving. Geen embeddings in v1.*
|
|
4. **Hoeveel children per run?** *Voorstel: hard cap 8 in de prompt (anders gaat 'ie speculeren). Gebruiker kan opnieuw klikken voor meer.*
|
|
5. **Editable plan-text:** wanneer agent `implementation_plan` invult op een nieuwe task, kan de gebruiker die later via TaskDialog editen — dat werkt al, geen extra werk.
|
|
6. **Failure-recovery:** wat als agent halverwege crasht? Stale-cleanup >30min werkt al; partial-children blijven aangemaakt. *Voorstel: accepteer partial — gebruiker kan opnieuw triggeren, aanvullen-policy filtert duplicaten.*
|
|
|
|
---
|
|
|
|
## Out of scope (v1 van deze feature)
|
|
|
|
- ❌ Diff-review-flow (vervangen-modus uit eerdere AskUserQuestion)
|
|
- ❌ Live streaming-output van agent (alleen status-events, geen tekst-stream)
|
|
- ❌ Meerdere parallele PLANNING-jobs op dezelfde target (idempotency blokkeert)
|
|
- ❌ Custom prompts per product (vaste prompt-template `/generate-plan`)
|
|
- ❌ Embeddings / vector-search over docs (agent leest plain files)
|
|
- ❌ Cross-user planning (agent werkt altijd binnen eigen product-scope)
|
|
- ❌ Auto-trigger (bv. "elke nieuwe lege story krijgt automatisch een plan-job") — handmatige trigger blijft regel
|
|
- ❌ Agent-tot-agent-orkestratie (planning-agent kan geen impl-agent triggeren) — gebruiker blijft in the loop
|
|
- ❌ Planning op product-niveau (PBI's genereren) — pas zinvol als product-spec-input bestaat
|
|
- ❌ Planning-agent UI in Solo Paneel (Solo blijft impl-only) — triggers zitten in backlog-dialogs
|
|
|
|
---
|
|
|
|
## Migratie-pad voor toekomstige derde agent (referentie)
|
|
|
|
Als er ooit een derde agent komt (bv. **review-agent** die een PR review't):
|
|
|
|
1. `ClaudeJobKind` enum uitbreiden met `REVIEW`
|
|
2. `ApiTokenKind` enum uitbreiden met `REVIEW`
|
|
3. `enqueueReviewJobAction` aanmaken (kopieert pattern van planning)
|
|
4. `wait_for_job` accepteert nieuwe `kind` automatisch via `accept_kinds`
|
|
5. Pattern-doc `claude-agent-roles.md` uitbreiden met de derde rol
|
|
|
|
Geen schema-revolutie nodig — `kind`-enum is het uitbreidingspunt.
|