Scrum4Me/docs/plans/M12-three-phase-feature-pipeline.md

28 KiB

title status audience language last_updated applies_to related
M12 — Drie-fase agent-pipeline voor feature-ideatie proposal
maintainer
contributor
nl 2026-05-03
M12
docs/adr/0009-three-phase-feature-pipeline.md
docs/plans/M11-claude-questions.md
docs/plans/ST-1111-claude-job-trigger.md
docs/obsidian-authoring.md

M12 — Drie-fase agent-pipeline voor feature-ideatie

Implementatie van ADR-0009: één geïntegreerde flow van een idee op een product naar een geïmplementeerde feature, in drie agent-fasen met menselijke checkpoints. Bouwt verder op M11 (vraagkanaal) en ST-1111 (job queue). Breidt scrum4me-mcp uit met docs-tools zodat alle agent-context — DB en docs — via één kanaal loopt.

Hard dependencies: M11 + ST-1111 moeten afgerond zijn voor ST-1204.

Gekozen kaders:

  • Drie aparte job-types — FEATURE_BRAINSTORM, DETAIL_PLAN, en de bestaande STORY_EXECUTE. Geen auto-advance tussen fasen; user triggert fase 2 en 3 expliciet.
  • Plan-content blijft file-based (docs/plans/); execution-state blijft DB.
  • Docs-context loopt via nieuwe MCP-tools (list_docs, read_doc, search_docs) — niet via directe filesystem-read door de worker.
  • ClaudeBrainstorm is een aparte entiteit naast Story. Brainstorm-Q&A loopt via ClaudeBrainstormQuestion parallel aan M11's ClaudeQuestion. M11 wordt niet aangeraakt.
  • Workers draaien onder een dedicated agent_writer-account per environment, niet onder een persoonlijke user.
  • Plan-templates in docs/plans/templates/ zorgen voor reproduceerbare structuur in fase 2.
  • In-app draft-preview ship't in v1 (naast obsidian://-link) zodat Cowork-only users niet afhankelijk zijn van Obsidian.

ST-1201 — MCP docs-tools (in scrum4me-mcp-repo)

Bestanden

  • scrum4me-mcp/src/tools/list-docs.ts — nieuw
  • scrum4me-mcp/src/tools/read-doc.ts — nieuw
  • scrum4me-mcp/src/tools/search-docs.ts — nieuw
  • scrum4me-mcp/src/lib/docs-root.ts — nieuw (env DOCS_ROOT resolver + path-safety)
  • scrum4me-mcp/src/lib/front-matter.ts — nieuw, dependency-vrij parser (mirror scripts/generate-docs-index.mjs)
  • scrum4me-mcp/src/index.ts — registreer drie tools
  • scrum4me-mcp/scripts/smoke-test.ts — uitbreiden met docs-roundtrip
  • scrum4me-mcp/README.md — tool-tabel + DOCS_ROOT env doc
  • scrum4me-mcp/.env.exampleDOCS_ROOT toevoegen

Stappen

  1. docs-root.ts — resolver: leest DOCS_ROOT env var (absolute path), throw bij ontbreken. Helper safeJoin(rel) blokkeert ..-traversal en symlinks-buiten-root.

  2. list_docs (read-tool) — input { category? }, output { path, title, status?, last_updated?, category }[]. Skip _*.md sidecars. Sorteer op last_updated desc.

  3. read_doc (read-tool) — input { path } relatief vanaf DOCS_ROOT, output { path, content, frontMatter, lastModified }. Cap 200 KB.

  4. search_docs (read-tool) — input { query, max_results? } (default 10, max 30). Substring scan v1; switch naar lunr/fuse.js als v2 nodig blijkt. Excerpt 200 chars rond eerste match.

  5. Smoke-test: list_docs({category:'pattern'}) ≥10 items; read_doc({path:'patterns/server-action.md'}) bevat "Server Action"; search_docs({query:'iron-session'}) bevat ADR-0005.

Aandachtspunten

  • Géén write-tools voor docs in deze story. write_plan (fase 2) komt in ST-1206 met striktere path-rules.
  • DOCS_ROOT is per-environment. Documenteer in obsidian-authoring.md (gebeurt in ST-1208).
  • Front-matter parser dependency-vrij — geen gray-matter.

Verificatie

  • MCP Inspector toont 3 nieuwe tools
  • Smoke-test groen
  • Path-traversal test: read_doc({path:'../package.json'}) → error
  • tsc --noEmit clean op scrum4me-mcp

ST-1202 — Schema: ClaudeBrainstorm + worker-account

Bestanden

  • prisma/schema.prismaJobType-enum uitbreiden, Role-enum uitbreiden, ClaudeBrainstorm + ClaudeBrainstormQuestion-models
  • prisma/migrations/<ts>_add_brainstorm_pipeline/migration.sql
  • prisma/seed-data/agent-writer.ts — nieuw, seedt service-account per environment
  • prisma/seed.ts — invoke nieuwe seed
  • vendor/scrum4me-submodule sync in scrum4me-mcp ná merge

Stappen

  1. Job-type uitbreiden:

    enum JobType {
      STORY_EXECUTE       // bestaand uit ST-1111
      FEATURE_BRAINSTORM  // nieuw — fase 1
      DETAIL_PLAN         // nieuw — fase 2
    }
    
  2. Role-enum uitbreiden (bestaand: OWNER, MEMBER, DEMO):

    enum Role {
      OWNER
      MEMBER
      DEMO
      AGENT_WRITER  // nieuw — alleen voor service-accounts die door workers gebruikt worden
    }
    

    Toegangslogica: requireWriteAccess accepteert AGENT_WRITER net zoals OWNER/MEMBER. Demo-blok blijft alleen op DEMO. UI-rendering hoort AGENT_WRITER-users te verbergen uit member-lijsten (eigen filter, niet via role-omittance).

  3. ClaudeBrainstorm-model (vervangt eerdere voorstel BrainstormSession):

    model ClaudeBrainstorm {
      id              String   @id @default(cuid())
      product_id      String
      product         Product  @relation(fields: [product_id], references: [id], onDelete: Cascade)
      created_by      String
      creator         User     @relation("BrainstormCreator", fields: [created_by], references: [id])
      idea_text       String   @db.Text
      status          String   // 'brainstorming' | 'draft_ready' | 'detailing' | 'plan_ready' | 'cancelled' | 'failed'
      draft_path      String?  // bv. 'plans/_draft-feature-foo.md'
      plan_path       String?  // gevuld door fase 2
      pbi_id          String?
      brainstorm_job_id String?
      detail_job_id   String?
      created_at      DateTime @default(now())
      updated_at      DateTime @updatedAt
      questions       ClaudeBrainstormQuestion[]
    
      @@index([product_id, status])
      @@map("claude_brainstorms")
    }
    
  4. ClaudeBrainstormQuestion-model (parallel aan M11's ClaudeQuestion, geen wijziging op M11):

    model ClaudeBrainstormQuestion {
      id             String   @id @default(cuid())
      brainstorm_id  String
      brainstorm     ClaudeBrainstorm @relation(fields: [brainstorm_id], references: [id], onDelete: Cascade)
      product_id     String   // gedenormaliseerd voor SSE-filter (zelfde patroon als M11)
      product        Product  @relation(fields: [product_id], references: [id], onDelete: Cascade)
      asked_by       String
      asker          User     @relation("BrainstormQuestionAsker", fields: [asked_by], references: [id])
      question       String   @db.Text
      options        Json?
      status         String   // 'open' | 'answered' | 'cancelled' | 'expired'
      answer         String?  @db.Text
      answered_by    String?
      answerer       User?    @relation("BrainstormQuestionAnswerer", fields: [answered_by], references: [id])
      answered_at    DateTime?
      created_at     DateTime @default(now())
      expires_at     DateTime
    
      @@index([brainstorm_id, status])
      @@index([product_id, status])
      @@map("claude_brainstorm_questions")
    }
    
  5. Postgres-triggers op beide tabellen, mirror M11 ST-1101 — emit op scrum4me_changes met entity: 'brainstorm' resp. entity: 'brainstorm_question'. Solo-route filtert beide weg (zelfde update als M11 deed voor 'question').

  6. Service-account seed in prisma/seed-data/agent-writer.ts:

    • Maakt één user agent-writer@scrum4me.local met role AGENT_WRITER als die nog niet bestaat
    • Wachtwoord-hash van een random secret uit env AGENT_WRITER_SECRET (zo kan workers' iron-session-vergelijkbare auth via bcrypt-compare valideren)
    • User heeft géén product-membership by default — wordt per ClaudeBrainstorm.product_id runtime gemachtigd via een aparte ProductAgentGrant-laag (zie ST-1207)
  7. npx prisma migrate dev --name add_brainstorm_pipeline

Aandachtspunten

  • M11's ClaudeQuestion blijft volledig ongewijzigd. Alleen brainstorm-Q&A gebruikt de nieuwe tabel.
  • entity: 'brainstorm' en entity: 'brainstorm_question' zijn twee nieuwe SSE-payload-waarden — solo-route en M8/M11-routes moeten ze filteren of afhandelen
  • AGENT_WRITER_SECRET is een nieuwe env var — toevoegen aan .env.example + lib/env.ts
  • ProductAgentGrant-tabel komt in ST-1207 (apart) zodat dit story behapbaar blijft

Verificatie

  • npx prisma validate clean
  • Seed-run maakt agent-writer user; herhaalde run idempotent (geen duplicate)
  • psql $DIRECT_URL -c "LISTEN scrum4me_changes;" toont nieuwe entity-waarden bij INSERT
  • M11-vraag-flow nog steeds werkend (regressie-check)
  • Submodule-sync drift-check ná merge

ST-1203 — MCP brainstorm-question-tools (in scrum4me-mcp-repo)

Bestanden

  • scrum4me-mcp/src/tools/ask-brainstorm-question.ts — nieuw
  • scrum4me-mcp/src/tools/get-brainstorm-answer.ts — nieuw
  • scrum4me-mcp/src/tools/list-open-brainstorm-questions.ts — nieuw
  • scrum4me-mcp/src/index.ts — registreer

Stappen

  1. Spec-mirror van M11's question-tools, maar gebonden aan brainstorm_id i.p.v. story_id:

    • ask_brainstorm_question({ brainstorm_id, question, options?, wait_seconds? })
    • get_brainstorm_answer({ question_id })
    • list_open_brainstorm_questions({ brainstorm_id? })
  2. Limit-enforcement: ask_brainstorm_question weigert als count(claude_brainstorm_questions WHERE brainstorm_id=… AND status≠'cancelled') ≥ 12. Returnt { error: 'limit_reached' } zodat de grill-me-skill afrondt.

  3. Auth: requireWriteAccess-check; userCanAccessProduct(brainstorm.product_id, auth.userId). AGENT_WRITER-account passeert deze check via ProductAgentGrant (ST-1207).

  4. Smoke-test uitbreiden: ask + answer roundtrip op een test-brainstorm.

Aandachtspunten

  • Code-duplicatie met M11-tools is aanvaardbaar (twee onafhankelijke flows). Als duplicatie pijn doet, factor in v2 een gemeenschappelijke question-tool-factory uit.
  • cancel_brainstorm_question niet in v1 — alleen agent-asker zou cancellen, en de caps maken het zelden nodig

Verificatie

  • MCP Inspector toont 3 nieuwe tools (totaal docs+brainstorm = 6 nieuwe in M12)
  • Smoke-test groen — ask-with-wait + parallel answer
  • Limit-enforcement test: 13e vraag retourneert limit_reached

ST-1204 — Fase 1: FEATURE_BRAINSTORM-worker

Bestanden

  • lib/jobs/handlers/feature-brainstorm.ts — nieuw
  • lib/jobs/dispatcher.ts — uitbreiden met nieuwe type
  • lib/agents/brainstorm-prompt.ts — system-prompt template
  • lib/agents/worker-session.ts — nieuw — opent een iron-session voor AGENT_WRITER-account

Stappen

  1. Worker-session helpergetAgentWriterSession(productId):

    • Authenticate agent-writer@scrum4me.local met AGENT_WRITER_SECRET
    • Return een MCP-bearer-token gebonden aan deze user voor de duur van het subprocess
    • Audit-log entry: "agent_writer accessed product X for brainstorm Y"
  2. Job-handler ontvangt ClaudeBrainstorm.id:

    • Laad brainstorm + product
    • Genereer slug uit idea_text (lowercase, dash, max 40 chars)
    • Bepaal _draft-feature-<slug>.md-pad. Update brainstorm: draft_path, status: 'brainstorming'
    • Spawn Claude Code subprocess met env: MCP_BEARER (van worker-session), DOCS_ROOT, BRAINSTORM_ID=<id>
    • Bij subprocess-exit: status → draft_ready (success) of failed (non-zero exit)
  3. Prompt-templatebrainstorm-prompt.ts:

    • Statisch met {productName}, {ideaText} placeholders
    • "Je bent in fase 1. Tools: get_product, list_pbis, list_docs, search_docs, read_doc voor context. ask_brainstorm_question om vragen te stellen (max 12). Trigger de grill-me-skill. Schrijf het resultaat naar <draft_path> via write_doc_draft (komt in ST-1206) zodra je voldoende context hebt."
  4. Caps: max 30 min wall-time → SIGTERM → na 5s SIGKILL.

Aandachtspunten

  • write_doc_draft-tool komt in ST-1206 — tot dan tijdelijke mock die naar stdout dumpt
  • grill-me wordt niet hier ingeladen; dat doet Claude Code's eigen skill-systeem zodra de prompt 'm noemt
  • Audit-log per worker-spawn is verplicht — nodig voor "wie heeft welke PBI aangemaakt"-traceerbaarheid

Verificatie

  • Handmatig: maak ClaudeBrainstorm via prisma-studio met simpel idee → handler runt → na 5-10min verschijnt _draft-feature-…md
  • Tijdens run: in-app brainstorm-tracker toont vragen via SSE
  • Audit-log heeft entry per spawn

ST-1205 — UI: "Nieuw idee", brainstorm-tracker, draft-preview

Bestanden

  • components/product/new-idea-button.tsx — nieuw
  • components/product/new-idea-dialog.tsx — nieuw, volgt docs/patterns/dialog.md
  • components/product/brainstorm-list.tsx — nieuw
  • components/product/draft-preview.tsx — nieuw — in-app modal-preview voor draft + plan
  • actions/brainstorm.tscreateBrainstorm, cancelBrainstorm, triggerDetailPlan
  • stores/brainstorm-store.ts — nieuw
  • lib/realtime/use-brainstorm-realtime.ts — listen op entity: 'brainstorm' + entity: 'brainstorm_question'
  • app/(app)/products/[id]/page.tsx — bridge mount + button-render

Stappen

  1. NewIdeaDialog — entity-dialog per docs/patterns/dialog.md. Body: textarea (max 2000, char-counter), helper "Beschrijf het idee in eigen woorden — Claude stelt straks vervolgvragen." Submit → createBrainstorm Server Action. Demo-modus: knop disabled met tooltip.

  2. BrainstormList op product-pagina:

    • Status-pills met MD3-tokens (zie docs/design/styling.md)
    • Per item: idea-truncate, created_by, last_updated-relative, action-buttons per status
    • draft_ready → "Bekijk draft" (opent <DraftPreview />) + secondary obsidian://-link + "Maak detail-plan" knop
    • plan_ready → "Bekijk plan" + "Open PBI" als pbi_id gevuld
    • brainstorming → "Annuleer" + indicator "Wacht op vragen" (blinkt als ask-pending)
    • Realtime-update via M12-bridge
  3. DraftPreview (in-app v1):

    • shadcn Dialog met markdown-render (react-markdown, al gebruikt in M5 task-detail)
    • Inhoud opgehaald via MCP read_doc({ path }) door een Server Action getDraftContent(brainstormId) die access-check doet
    • Read-only; bewerken gaat via Obsidian (link toont "Open in Obsidian" als secondary action)
    • Footer: "Maak detail-plan"-button (zelfde action als in lijst)
  4. Server Actions — volgt docs/patterns/server-action.md:

    • createBrainstorm({ productId, ideaText }) — Zod, demo-blok, access-check, transactie insert brainstorm + insert job
    • triggerDetailPlan(brainstormId) — vereist status === 'draft_ready', insert DETAIL_PLAN-job
    • cancelBrainstorm(brainstormId) — alleen creator of OWNER, kill-signal naar job indien actief
    • getDraftContent(brainstormId) — read-only, access-check, roept MCP read_doc aan
  5. Bridge + store — analoog aan M11 NotificationsBridge.

Aandachtspunten

  • Twee bronnen van M12-events: brainstorm-status-changes en brainstorm-questions. Bridge subscribet beide.
  • Brainstorm-questions hoeven NIET in M11's notification-bell te verschijnen — ze zitten in BrainstormList op de product-pagina. Houd ze visueel apart van M11-questions.
  • Open punt: wil je later toch een unified-bell? Buiten M12-scope.
  • Paginate BrainstormList na 10 items, "Toon archief" voor cancelled/failed

Verificatie

  • E2E tot fase 1: product → "Nieuw idee" → typ → submit → BrainstormList toont "brainstorming" → vragen verschijnen in component → user beantwoordt → status flipt naar "draft_ready" → "Bekijk draft" opent modal met markdown-content
  • Demo-modus: alle write-knoppen disabled met tooltip
  • Cancel: status flipt, subprocess wordt gekillt

ST-1206 — Fase 2: DETAIL_PLAN-worker + write_plan-tool + plan-templates

Bestanden

  • scrum4me-mcp/src/tools/write-plan.ts — nieuw, write-tool met strikte path-rules
  • scrum4me-mcp/src/tools/write-doc-draft.ts — nieuw, write-tool voor _draft-*.md (gebruikt door fase 1)
  • scrum4me-mcp/src/index.ts — registreer
  • lib/jobs/handlers/detail-plan.ts — nieuw
  • lib/agents/detail-plan-prompt.ts — system-prompt template
  • docs/plans/templates/milestone.md — nieuw
  • docs/plans/templates/story.md — nieuw
  • docs/plans/templates/_README.md — nieuw, beschrijft wanneer welke template gebruiken

Stappen

  1. write_doc_draft (write-tool, geen demo-blok want alleen agent_writer):

    • Input: { relativePath, content, overwrite? }
    • Path moet matchen plans/_draft-[a-z0-9-]+\.md (regex enforcement)
    • Schrijven; output { path, bytesWritten }
  2. write_plan (write-tool, geen demo-blok):

    • Input: { relativePath, content, overwrite? }
    • Path moet matchen plans/(M\d+|ST-\d+)-[a-z0-9-]+\.md — geen _draft-, geen subdirs
    • Mag niet bestaan tenzij overwrite=true (default false)
    • Output: { path, bytesWritten }
  3. Plan-templatesdocs/plans/templates/:

    • milestone.md — voor ≥3 stories. Bevat front-matter-skelet, intro-blok, story-template (h2, bestanden-lijst, stappen, aandachtspunten, verificatie), branch-strategie-blok, acceptatie-blok, scope-out-blok. Gebruik {{placeholders}} in dezelfde stijl als docs/adr/templates/nygard.md.
    • story.md — voor 1-2 stories, lichter
    • _README.md — kies-criteria + handmatig-vs-fase-2 instructies. Underscore-prefix → niet in INDEX.
  4. Detail-plan-handler ontvangt ClaudeBrainstorm.id:

    • Laad brainstorm, lees draft via MCP read_doc({path: brainstorm.draft_path})
    • Spawn Claude Code subprocess met MCP_BEARER (worker-session), DOCS_ROOT, BRAINSTORM_ID
    • System-prompt:
      • "Fase 2. Lees read_doc({path:'<draft_path>'}). Gebruik search_docs + read_doc voor relevante patterns/ADRs/architecture. Lees read_doc({path:'plans/templates/milestone.md'}) of plans/templates/story.md voor het skelet (kies milestone bij ≥3 stories). Schrijf canonical plan via write_plan naar plans/M{N}-<slug>.md of plans/ST-XXXX-<slug>.md (volgnummer via list_docs({category:'plan'}) + max+1). Maak vervolgens via save_pbi + save_story + save_task de DB-rijen aan. Geen vragen aan de user — open punten markeer je als **TODO:** in het plan."
    • Bij subprocess-exit: update brainstorm plan_path, pbi_id, status plan_ready of failed

Aandachtspunten

  • Plan-templates moeten zelf in INDEX-generator gefilterd worden via _README.md-prefix-rule (al bestaand) en via een templates/-pad-skip in scripts/generate-docs-index.mjs — kleine generator-edit nodig
  • Volgnummer-bepaling: lees alle plans/M\d+-*.md files, parse max nummer, +1. Race-conditie als twee fase-2-jobs tegelijk draaien — accept; dubbele nummers geven manuele review
  • write_plan mag een PBI-rij maken voor je het plan schrijft; volgorde in prompt: eerst plan-file (rollback-bestand bij fout), dan DB-rijen
  • Path-injection-test verplicht in unit-test

Verificatie

  • Handmatig: trigger triggerDetailPlan op een draft → na 5-15min verschijnt nieuw plans/M{N}-…md + PBI in DB → BrainstormList status plan_ready
  • npm run docs:index regenereert INDEX.md met het nieuwe plan en negeert templates/
  • Path-rules: prompt-injection-test write_plan({relativePath:'../adr/0009.md', ...}) faalt
  • Bestaand plan niet overschreven zonder overwrite=true

ST-1207 — ProductAgentGrant: per-product machtiging voor AGENT_WRITER

Bestanden

  • prisma/schema.prismaProductAgentGrant-model
  • prisma/migrations/<ts>_add_product_agent_grant/migration.sql
  • lib/auth/agent-grant.ts — helper grantAgentForBrainstorm(brainstormId)
  • lib/auth/access.tsuserCanAccessProduct uitbreiden om AGENT_WRITER met geldige grant te accepteren
  • actions/brainstorm.tscreateBrainstorm maakt grant aan in dezelfde transactie

Stappen

  1. ProductAgentGrant-model:

    model ProductAgentGrant {
      id             String   @id @default(cuid())
      product_id     String
      product        Product  @relation(fields: [product_id], references: [id], onDelete: Cascade)
      agent_user_id  String
      agent          User     @relation(fields: [agent_user_id], references: [id], onDelete: Cascade)
      reason         String   // 'brainstorm:<id>' | 'detail_plan:<id>' | 'story_execute:<id>'
      granted_by     String
      granter        User     @relation("AgentGrantGranter", fields: [granted_by], references: [id])
      created_at     DateTime @default(now())
      expires_at     DateTime // 24h voor brainstorm/detail; 7d voor story_execute
    
      @@unique([product_id, agent_user_id, reason])
      @@index([agent_user_id, expires_at])
      @@map("product_agent_grants")
    }
    
  2. Access-uitbreiding in lib/auth/access.ts:

    • Bestaand: userCanAccessProduct(productId, userId) checkt ProductMember
    • Nieuw: als user-role AGENT_WRITER is, valid grant-check via ProductAgentGrant WHERE product_id=… AND agent_user_id=… AND expires_at > now()
  3. Grant-helper grantAgentForBrainstorm(brainstormId):

    • Haal agent-user op (gecachet)
    • Insert grant met reason='brainstorm:<id>', granted_by=brainstorm.created_by, expires_at=now+24h
    • Idempotent via unique-constraint
  4. createBrainstorm-action doet de grant aan in dezelfde transactie als de brainstorm + job. Fase 2 maakt een tweede grant met reason='detail_plan:<id>'.

  5. Cleanup-cron (lichtgewicht — kan in bestaande expire-questions-cron uit M11 ST-1107):

    • DELETE FROM product_agent_grants WHERE expires_at < now()
    • Hergebruik CRON_SECRET-pad

Aandachtspunten

  • Audit-trail: granted_by legt vast welke menselijke user de agent gemachtigd heeft — voor compliance bij eventuele schade-analyse
  • Grant verloopt automatisch — voorkomt dat een lang-stilstaande agent later nog kan schrijven
  • Demo-user kan geen grants aanmaken (hij kan geen brainstorm starten — demo-blok op createBrainstorm)

Verificatie

  • Unit-test: grant binnen window → access ja; grant verlopen → access nee
  • Unit-test: AGENT_WRITER zonder grant → access nee
  • Bestaande user-flows ongewijzigd (regressie)

ST-1208 — Fase 3-integratie + acceptatietests + docs

Bestanden

  • lib/jobs/handlers/story-execute.ts — uitbreiden om story.metadata.plan_path mee te nemen
  • docs/architecture/agent-pipeline.md — nieuw — sequence-diagram + threat-model
  • docs/patterns/agent-pipeline-stage.md — nieuw — herbruikbaar pattern
  • docs/runbooks/mcp-integration.md — uitbreiden met 6 nieuwe tools
  • docs/obsidian-authoring.md — corrigeer "MCP exposes geen docs"-passage
  • docs/backlog/index.md — M12-tabel + sectie
  • prisma/seed-data/parse-backlog.tsM12: 'PROPOSED'
  • CLAUDE.md — patterns quickref-tabel uitbreiden
  • scripts/generate-docs-index.mjs — skip plans/templates/

Stappen

  1. ST-1111 minimale aanpassing: story-execute-handler leest story.metadata.plan_path indien gevuld en includeert "Lees plan_path voor je begint" in de prompt. Backwards-compatible.

  2. Architecture-doc met Mermaid sequence: User → UI → Job → Worker (fase 1) → MCP (DB+docs+brainstorm-Q) → User → Worker schrijft draft → User triggert fase 2 → Worker (fase 2) → write_plan + save_pbi → User triggert fase 3 → bestaande flow.

  3. Pattern-doc "agent-pipeline-stage" — generiek per fase: input-state, agent-context, output-artefact, exit-criteria, escalation-pad, audit-trail.

  4. Obsidian-authoring update — vervang sectie "the mcp server does not expose docs/ content" door verwijzing naar ADR-0009 + de 6 nieuwe tools (list_docs, read_doc, search_docs, write_plan, write_doc_draft, ask_brainstorm_question/get_brainstorm_answer/list_open_brainstorm_questions). Behoud "Obsidian is geen tweede waarheidsbron"-stelling.

  5. Index-generator — skip plans/templates/ zodat templates niet in INDEX.md belanden.

  6. Backlog + parser — M12 als PROPOSED; activeren wanneer M11 + ST-1111 done.

  7. Acceptatie-scenario's (zeven):

    1. Happy path E2E: idee → grill-me → draft → fase 2 → plan + PBI → fase 3 → code
    2. MCP docs-tool: agent vindt via search_docs + read_doc de juiste pattern
    3. Path-safety: prompt-injection via write_plan of read_doc faalt
    4. Demo-block: alle drie de Server Actions geblokkeerd voor demo-user
    5. Cancel mid-flight: brainstorm cancellen kill't subprocess
    6. Plan-overwrite-protectie: bestaand plan niet overschreven
    7. Agent-grant-expiry: agent kan na grant-expiry geen save_pbi meer doen voor dat product

Aandachtspunten

  • Acceptatie 1 vereist M11 + ST-1111 volledig groen
  • Threat-model in architecture-doc: prompt-injection via idea_text (max-length + escape), agent-grant-misbruik (audit-log + auto-expire), schema-divergentie scrum4me ↔ scrum4me-mcp (sync ná merge)
  • Pipeline-pattern is bruikbaar voor toekomstige flows (bug-triage, refactor-planning) — pattern-doc moet generiek genoeg zijn

Verificatie

  • 7/7 acceptatie groen (1+5 handmatig, 2+3+4+6+7 unit-test)
  • npm run docs:index clean — M12-plan, ADR-0009, nieuwe pattern + architecture in INDEX.md, templates niet
  • npm run lint && npm test && npm run build clean op Scrum4Me
  • tsc --noEmit && npm test clean op scrum4me-mcp
  • Submodule-sync ná merge

Branch- en commit-strategie

Per Branch & PR Strategy:

  • Eén branch op Scrum4Me: feat/M12-feature-pipeline afgesplitst van main ná M11-merge
  • Aparte branch op scrum4me-mcp: feat/M12-docs-and-plan-tools
  • MCP-PR pas mergen ná Scrum4Me-PR + submodule-sync
  • Push pas na handmatige acceptatie van scenario 1 (happy path) + 3 (path-safety) + 7 (grant-expiry)

Commit-volgorde:

feat(ST-1201): add list_docs, read_doc, search_docs MCP tools
feat(ST-1201): add DOCS_ROOT env + safeJoin path validator
feat(ST-1202): add JobType enum extension
feat(ST-1202): add Role.AGENT_WRITER + agent-writer seed
feat(ST-1202): add ClaudeBrainstorm + ClaudeBrainstormQuestion models
feat(ST-1202): add notify triggers for brainstorm entities
feat(ST-1203): add ask_brainstorm_question + get_brainstorm_answer + list_open_brainstorm_questions
feat(ST-1204): add agent-writer worker-session helper
feat(ST-1204): add brainstorm-prompt template
feat(ST-1204): add FEATURE_BRAINSTORM job handler
feat(ST-1205): add createBrainstorm + triggerDetailPlan + cancelBrainstorm server actions
feat(ST-1205): add brainstorm Zustand store + realtime hook
feat(ST-1205): add NewIdeaButton + dialog on product page
feat(ST-1205): add BrainstormList component
feat(ST-1205): add DraftPreview modal with read_doc fetch
feat(ST-1206): add write_doc_draft + write_plan MCP tools
docs(ST-1206): add plans/templates/milestone.md + story.md + _README.md
feat(ST-1206): add detail-plan-prompt template
feat(ST-1206): add DETAIL_PLAN job handler
feat(ST-1207): add ProductAgentGrant model + migration
feat(ST-1207): extend userCanAccessProduct with grant-check
feat(ST-1207): wire grantAgentForBrainstorm into createBrainstorm + triggerDetailPlan
feat(ST-1207): add grant-cleanup to expire-questions cron
feat(ST-1208): wire plan_path into story-execute prompt
docs(ST-1208): add agent-pipeline architecture doc
docs(ST-1208): add agent-pipeline-stage pattern
docs(ST-1208): update obsidian-authoring to reflect MCP docs-tools
docs(ST-1208): skip plans/templates from index-generator
chore(ST-1208): backlog M12 + parser PROPOSED

Buiten scope (volgende milestones)

  • Auto-advance fase 1 → 2 wanneer de gebruiker dat per brainstorm aanvinkt (default blijft handmatige checkpoint)
  • Multi-agent-detail-plan (twee agents schrijven elk een variant; user kiest)
  • Idee-clustering via embeddings ("lijken deze 3 brainstorms op elkaar?")
  • Stats-dashboard: gemiddelde tijd per fase, % brainstorms die plan_ready halen, % geïmplementeerd
  • Bulk-import van bestaande backlog-items naar de pipeline
  • Cross-product-pipeline: idee dat impact heeft op meerdere producten
  • Unified-bell die zowel M11- als M12-vragen toont
  • Edit-in-place voor draft in DraftPreview (v1 is read-only; bewerken via Obsidian)