Nieuwe client-component met multi-select statusfilter popover voor het
Ideeënscherm; hergebruikt MultiFilterPills uit backlog-filter-popover.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(ideas): upload-plan knop — short-circuit van Make-Plan AI-flow
Voegt een 'Upload plan' knop toe in idea-row-actions (verschijnt in zowel
list als idea-detail). Klik → file picker → kies .md → server-side parse +
opslaan; idea-status springt naar PLAN_READY. Vandaaruit de bestaande
'Maak PBI' knop voor materialize.
Server (uploadPlanMdAction):
- Toegestaan vanuit DRAFT, GRILLED, PLAN_FAILED, PLAN_READY
- DRAFT → skip-grill: status gaat direct naar PLAN_READY
- PLAN_READY overschrijft het bestaande plan (consistent met
updatePlanMdAction, geen confirmation)
- Geblokkeerd in GRILLING/PLANNING (job loopt), PLANNED (al gematerialiseerd)
- Parse-failure → 422 + details (NIET opslaan, zodat een onparseerbaar plan
nooit in de DB belandt)
- Empty / >100k chars → 422
- Schrijft IdeaLog NOTE met from_status + length
- Rate-limit + demo-guard + ownership-check via loadOwnedIdea (zelfde
patroon als updatePlanMdAction)
UI (idea-row-actions.tsx):
- Hidden <input type=file accept=".md,.markdown,text/markdown,text/plain">
- FileReader → text → action
- Toast bij success + router.refresh()
- Blocked-tooltip in andere statussen
Tests: 10 nieuwe in __tests__/actions/ideas-crud.test.ts dekkend voor:
happy paths (DRAFT/GRILLED/PLAN_READY-overwrite/PLAN_FAILED), blocks
(PLANNED/GRILLING), validation (empty/oversized/parse-fail), 404.
Full suite groen: 849/849.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add reviews for Bootstrap-wizard plans v3.2 to v3.4
- Review v3.2: Addressed executor model, fire-and-forget issues, and PAT handling.
- Review v3.3: Improved transaction handling, stale recovery, and ID generation.
- Review v3.4: Finalized GitHub permissions, catalog versioning, and E2E verification queries.
- Updated recommendations for each version to enhance implementation readiness.
* docs(plans): M8 bootstrap-wizard upload-variant v1.4 — backtick-paden
Upload-variant van het volledige technische plan (docs/plans/M8-bootstrap-wizard.md),
bedoeld voor de "Upload plan"-functie. Genereert 1 PBI + 4 Stories + 22 Tasks
via materializeIdeaPlanAction.
v1.4-aanpassingen tov eerdere generatie-iteratie:
- Alle bestandspaden in implementation_plan in backticks (path-extractor matchen)
- Expliciete "Bestanden:" blok per task vóór de stappen
- Alle tasks op verify_required: ALIGNED_OR_PARTIAL (was deels ALIGNED — te strict
voor ADR-stubs en multi-file edits)
Fixt forward-only: T-963 cancelled_by_self door DIVERGENT verifier-verdict.
Re-upload van dit bestand produceert tasks die door verify_task_against_plan
als ALIGNED of PARTIAL geclassificeerd kunnen worden.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* PBI-67: Add review-plan support to Idea model and job config
- Add plan_review_log and reviewed_at fields to Idea model
- Add REVIEWING_PLAN, PLAN_REVIEW_FAILED, PLAN_REVIEWED to IdeaStatus enum
- Add IDEA_REVIEW_PLAN to ClaudeJobKind enum
- Add IDEA_REVIEW_PLAN config to job-config.ts with model=opus, thinking_budget=6000
- Create migration record for schema changes (applied via db push)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* PBI-67 Phase 2: Add update-idea-plan-reviewed MCP tool
- Create src/tools/update-idea-plan-reviewed.ts: saves review-log and transitions idea status to PLAN_REVIEWED
- Add PLAN_REVIEW_RESULT to IdeaLogType enum (both repos)
- Register tool in src/index.ts
- Update Prisma schemas (both repos): add plan_review_log and reviewed_at fields to Idea model
- Add REVIEWING_PLAN, PLAN_REVIEW_FAILED, PLAN_REVIEWED to IdeaStatus enum (MCP schema)
- Add IDEA_REVIEW_PLAN to ClaudeJobKind enum (MCP schema)
- Tool includes transaction safety and convergence metrics logging
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* feat(PBI-67): IDEA_REVIEW_PLAN Phases 3-6 — server actions, UI components, prompt & tests
- Phase 3: startReviewPlanJobAction, cancelIdeaJobAction, status transitions
(REVIEWING_PLAN / PLAN_REVIEWED / PLAN_REVIEW_FAILED), status colors,
job-card/jobs-column filters, idea-list status tabs
- Phase 4: review-plan-job.md prompt (multi-model orchestration with codex
injection + active plan revision via update_idea_plan_md after each round),
runbook, 13 unit tests
- Phase 5: ReviewLogViewer component (rounds, convergence, approval, issues),
idea-detail integration, proper ReviewLog TypeScript types exported from component
- Phase 6.1: wait-for-job discriminator wired (IDEA_REVIEW_PLAN), plan-revision
step made mandatory in prompt (was previously optional/missing)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Voegt een 'Upload plan' knop toe in idea-row-actions (verschijnt in zowel
list als idea-detail). Klik → file picker → kies .md → server-side parse +
opslaan; idea-status springt naar PLAN_READY. Vandaaruit de bestaande
'Maak PBI' knop voor materialize.
Server (uploadPlanMdAction):
- Toegestaan vanuit DRAFT, GRILLED, PLAN_FAILED, PLAN_READY
- DRAFT → skip-grill: status gaat direct naar PLAN_READY
- PLAN_READY overschrijft het bestaande plan (consistent met
updatePlanMdAction, geen confirmation)
- Geblokkeerd in GRILLING/PLANNING (job loopt), PLANNED (al gematerialiseerd)
- Parse-failure → 422 + details (NIET opslaan, zodat een onparseerbaar plan
nooit in de DB belandt)
- Empty / >100k chars → 422
- Schrijft IdeaLog NOTE met from_status + length
- Rate-limit + demo-guard + ownership-check via loadOwnedIdea (zelfde
patroon als updatePlanMdAction)
UI (idea-row-actions.tsx):
- Hidden <input type=file accept=".md,.markdown,text/markdown,text/plain">
- FileReader → text → action
- Toast bij success + router.refresh()
- Blocked-tooltip in andere statussen
Tests: 10 nieuwe in __tests__/actions/ideas-crud.test.ts dekkend voor:
happy paths (DRAFT/GRILLED/PLAN_READY-overwrite/PLAN_FAILED), blocks
(PLANNED/GRILLING), validation (empty/oversized/parse-fail), 404.
Full suite groen: 849/849.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(PBI-82): vervang inline checkboxlijst door Popover in idea-detail-layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(test): update sprint-switcher mock for renamed action + entities.settings shape
switchActiveSprintAction (renamed from setActiveSprintAction) and the new
entities.settings selector were added in PBI-82 but the test mock was not
updated, causing 3 test failures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* ST-cmowjelb1: Parser: bestand-relatieve regel + hint-detectie in YAMLParseError-tak
- Voeg `hint?: string` toe aan PlanParseError type
- Bereken bestand-relatief regelnummer (yamlLine + 1 voor de openings-`---`)
- Detecteer markdown-patronen (numbered/bullet lijst) op de offending regel
- Zet Nederlandstalige hint bij markdown-match
- Render hint als "Tip: …" onder het foutbericht in IdeaMdEditor
* ST-cmowjeq3q: UI: render hint apart onder error-message in IdeaMdEditor
Vervang <span block mt-0.5 text-status-blocked/80> door <div mt-1 text-foreground/80>
voor de Tip-hint per plan-spec (MD3-token, geen status-kleur).
* ST-cmowjewfg: Test: parser geeft hint bij markdown-in-frontmatter
Voeg twee Vitest-cases toe:
- hints when markdown sneaks into frontmatter: fixture met [unclosed op
een genummerde markdown-regel triggert YAMLParseError op die regel
(plain lijst zonder unclosed flow parset als geldig YAML)
- omits hint for non-markdown yaml errors: unclosed bracket zonder
markdown-patroon geeft geen hint
* feat(PBI-33): chat-kanaal UI — IdeaTimeline merge + UserChatInput
Voltooit de UI-laag van PLAN_CHAT (gebruikersvragen over plan, Claude
antwoordt async). Backend (UserQuestion model, createUserQuestionAction,
SSE-handling, server-side prop-passing) was al aanwezig — alleen de
UI-koppeling ontbrak waardoor userQuestions ongebruikt bleven.
- IdeaDetailLayout geeft userQuestions/planMd/ideaId/isDemo door aan
IdeaTimeline en telt user-questions mee in de tab-count
- IdeaTimeline mergt user-questions chronologisch met logs+questions,
rendert ze met MessageCircle-icoon en pending/answered status, en
toont onderaan UserChatInput wanneer plan_md aanwezig is
- UserChatInput nieuw component met textarea + verzend-knop dat
createUserQuestionAction aanroept en op success router.refresh()
triggert zodat SSE de pending-state oppikt
- useNotificationsRealtime: router toegevoegd aan useEffect-deps zodat
router.refresh() op user_question/idea-job events werkt zonder
stale-closure waarschuwing
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(lint): unused vars/imports + react-hook-form watch incompatibility
Resolves de overige lint-warnings van de gefaalde sprint-build die los
staan van PBI-33. Eslint-config staat unused vars/args toe als ze met
'_' prefixen, dus required interface-params krijgen een prefix terwijl
losse dode constantes/imports verwijderd worden.
- sprint-header: productId is required prop maar nog niet gebruikt
→ prefix _productId i.p.v. verwijderen (caller passeert het door)
- agent-throughput: STATUSES-constante was dood — verwijderd, queries
gebruiken hardcoded status-velden in de perDay-loop
- claude-jobs: productAccessFilter en enforceUserRateLimit waren
dode imports — verwijderd
- story-log.test: ongebruikte 'data' binding vervangen door bare
await res.json() zodat de stream nog wel geconsumeerd wordt
- product-dialog: form.watch('auto_pr') vervangen door useWatch met
control-prop — useWatch is veilig voor React Compiler memoization
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(ST-cmovhveef): add PLANNED to GRILL_TRIGGERABLE_FROM and PLANNED→GRILLING transition
- GRILL_TRIGGERABLE_FROM now includes 'PLANNED' in actions/ideas.ts
- ALLOWED_TRANSITIONS PLANNED entry extended with 'GRILLING' in lib/idea-status.ts
- Updated canTransition test to reflect the new re-grill-from-PLANNED behavior
* test(ST-cmovhvef3): add exhaustive re-grill canTransition test covering PLANNED
Adds a loop test that asserts canTransition(status, 'GRILLING') for all
statuses in GRILL_TRIGGERABLE_FROM that support the transition, explicitly
documenting PLANNED as a valid re-grill entry point.
* feat(ST-cmovhvegf): add existingPbi pre-check in materializeIdeaPlanAction
- Adds options.allowAlongside parameter to control behaviour when a PBI
with executed tasks already exists.
- Returns 409 PBI_HAS_ACTIVE_TASKS:<code> when tasks are DONE/IN_PROGRESS
and allowAlongside is not set.
- Auto-deletes the old PBI inside the transaction when no tasks have been
executed (atomic replace).
- Alongside mode (allowAlongside=true) skips deletion and creates a new PBI.
* test(ST-cmovhveh3): add pre-check integration tests for materializeIdeaPlanAction
Three new scenarios in ideas-crud.test.ts:
- auto-vervang: old PBI deleted in transaction when no executed tasks
- conflict-409: returns PBI_HAS_ACTIVE_TASKS:<code> with active tasks
- alongside: skips delete and creates new PBI when allowAlongside=true
Also adds task.count, pbi.findUnique, pbi.delete to prisma mock.
* feat(ST-cmovhveih): remove PLANNED-blokkering in idea-row-actions, add inline Bekijk-PBI button
- Removed grillBlockedReason guard for status==='planned', enabling re-grill from PLANNED
- Removed the early return for PLANNED that hid all standard buttons
- Added conditional 'Bekijk <code>' button at the start of the standard button set,
visible only when status==='planned' and PBI + product_id are present
* feat(ST-cmovhvej7): add PBI_HAS_ACTIVE_TASKS alongside-dialoog in materialize handler
When materializeIdeaPlanAction returns code 409 with PBI_HAS_ACTIVE_TASKS:<code>,
a confirm dialog offers the user a choice: create new PBI alongside the existing one
or cancel. Alongside=true retries the action; cancel leaves the idea in PLAN_READY.
- Voeg showQuick/quickTitle/quickDescription state toe
- Voeg handleQuickCreate toe die createIdeaAction met product_id=null aanroept
- Voeg Snel idee-knop (variant=outline) toe naast Nieuw idee in de top-bar
- Voeg inline snel-form toe zonder product-dropdown, met Enter-to-submit
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(ideas): multi-select secundaire producten + badges in IdeaDetailLayout
Voegt checkbox-lijst toe voor extra producten (exclusief primaire) in
de Idee-tab, geïntegreerd in bestaande save/reset flow via
updateSecondaryProductsAction. Toont secundaire product-badges in de
detail-header. Bevat ook schema/dto/action-dependencies (IdeaProduct
junction, secondary_products in IdeaDto).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(ideas): lijst-filter matcht op primair én secundaire producten
Breidt productFilter-logica in IdeaList uit: naast product_id
wordt ook idea.secondary_products gecheckt, zodat ideeën zichtbaar
blijven bij filteren op een secundair gekoppeld product.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- TabKey union uitgebreid met 'sync'.
- Sync-tab alleen zichtbaar als syncData !== null && idea.status === 'planned'
(M12 keuze 6: na Materialiseer-actie).
- page.tsx roept loadIdeaSyncData alleen aan bij PLANNED + pbi_id, anders
null doorgeven aan layout.
- showSync-flag bepaalt of de tab in TAB_KEYS array zit en in de UI
gerenderd wordt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Toont per Story onder de gekoppelde PBI: status-badge, taak-rij met
job-status (incl. SKIPPED), branch, pushed_at, pr_url, en bestaande
<StoryLog>-component voor activity-log. PBI-header met PR-link en
gemerged-badge.
Realtime: subscribed op /api/realtime/notifications. Bij story_log-
event waar story_id matcht, of claude_job_status voor dit idea →
router.refresh() (server-render levert nieuwe data).
MD3-tokens overal: bg-status-todo/in-progress/done, bg-surface-
container, bg-muted/60. Geen bg-blue-500.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Nav-label 'Ideeën' hernoemd naar 'Ideas'; breadcrumb idem
- Grill/Plan tabs disabled (grijs, cursor-not-allowed) zolang er geen
content is; groene stip zodra grill_md resp. plan_md beschikbaar is
- SSE hook roept router.refresh() aan bij job done/failed zodat de
Timeline automatisch de nieuwe GRILL_RESULT/PLAN_RESULT logs toont
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three places linked to \`/products/[id]/backlog#pbi-{pbi_code}\` after
materializing or in the planned-state link-card. That route doesn't
exist (product backlog lives at \`/products/[id]\` directly), and the
hash was double-prefixed (\`#pbi-PBI-32\`) since pbi_code already starts
with PBI-. Result: 404 for the user.
Fix: route to \`/products/[id]\` without anchor. The new PBI is the most
recent so visible near the top. Per-PBI anchor scrolling is a follow-up
once we add \`id="pbi-{id}"\` attributes to pbi-list rows.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
\`new Date(...).toLocaleString()\` zonder expliciete locale gebruikt de
default-locale van runtime: server (Node) levert nl-NL formaat
(\`05/05/2026, 13:21:51\`), browser CSR levert en-US (\`5/5/2026, 1:21:51 PM\`).
React detecteert dat als hydration-mismatch en regenereert de tree.
Fix: pass \`'nl-NL'\` met expliciete date/time-style. Server en client
produceren nu identieke output.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two gaps discovered during the first live grill-session of IDEA-002:
the agent posted a question, but the user had no UI to answer it.
1. Idea-questions only appeared on the Timeline-tab as read-only entries
2. Notifications-bell fetched + handled story-questions only
This fix:
**Inline answer-form in IdeaTimeline** (components/ideas/idea-timeline.tsx)
- Open questions now render an AnswerForm directly under the question text
- Multi-choice options become clickable buttons (one-click submit); free-text
fallback via collapsed details/textarea
- Plain free-text questions render textarea + Verzend
- Calls existing answerQuestion server-action; toast + router.refresh on success
**Notifications-bell extended for idea-questions**
- stores/notifications-store.ts: NotificationQuestion → discriminated union
(kind: 'story' | 'idea'); forYouCount treats idea-questions as always-for-you
(idea is strictly user_id-only — only the owner sees them)
- components/notifications/notifications-bridge.tsx: parallel fetch of
story-questions (productAccessFilter) + idea-questions (idea.user_id ===
session.userId); merged + sorted by created_at
- components/notifications/notifications-sheet.tsx: renders idea_code/title
for kind='idea'
- components/notifications/answer-modal.tsx: header + open-link branch on
kind (idea → /ideas/[id]?tab=timeline; story → existing /sprint link)
- lib/realtime/use-notifications-realtime.ts: idea-question events also
trigger close+reconnect on 'open' (loads fresh detail) and remove(id) on
non-open — same pattern story-questions already use
- components/shared/notifications-bell.tsx: badge counts idea-questions as
for-you regardless of assignee
**Security gap closed (actions/questions.ts answerQuestion)**
Before: accepted any answer if user has product-access.
After: idea-questions require idea.user_id === session.userId; story-
questions keep the existing productAccessFilter path. (Prisma 7 rejects
\`{ not: null }\` in WHERE; routing happens app-level after a single fetch.)
Tests: 546/546 still green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
components/ideas/idea-md-editor.tsx:
- Textarea-based editor with monospace styling for grill_md / plan_md
- kind='plan': live yaml-frontmatter validation as derived state via
useMemo (no setState-in-effect); inline errors with line numbers
- kind='grill': free markdown, no validation
- localStorage draft per (ideaId, kind) — lazy initial-value seeded on
mount; toast notice if drift from server
- Cmd/Ctrl+S keyboard shortcut to save
- Server-action 422 details surface as separate submitErrors state
components/ideas/idea-detail-layout.tsx:
- Grill/Plan tabs flip into edit-mode via "Bewerk" button when:
- grill: status in [GRILLED, PLAN_READY] (M12 grill-keuze 12)
- plan: status === PLAN_READY
- Empty-state offers "Schrijf zelf" when md is null + editable
- Demo always read-only
Tests: 546/546 still green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
components/ideas/idea-row-actions.tsx — replaces T-507 placeholder:
- Grill Me: disabled in GRILLING/PLANNING/PLANNED, requires
product-with-repo + connectedWorkers > 0; tooltip shows specific reason
("Grill loopt al", "Idee heeft een product met repo nodig", "Geen
Claude-worker actief")
- Make Plan: enabled only in GRILLED/PLAN_FAILED/PLAN_READY; same
prerequisites as Grill
- Materialiseer: enabled only in PLAN_READY (no worker needed — synchrone
server-side parser); confirm-dialog before action; navigates to product
backlog PBI anchor on success
- *_FAILED: dedicated "Probeer opnieuw" rotate-icon button
- PLANNED: replaces all three with "Bekijk {PBI-code}" link + open-detail
- Demo: every mutating button wrapped in DemoTooltip with disabled state
- connectedWorkers read directly via useSoloStore (per M12 grill-keuze 16)
Tests: 546/546 still green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
app/(app)/ideas/page.tsx (server-component):
- user_id-only fetch (no productAccessFilter — Idee is privé)
- products fetched with productAccessFilter for filter-dropdown + create-form
components/ideas/idea-list.tsx (client-component):
- Search by title, product-dropdown filter, status multi-chip filter
- Inline create form with title/description/product (optional)
- Native shadcn Table + status badge via getIdeaStatusBadge (T-509)
- Row click navigates to /ideas/[id]
- Sonner toasts for success/error; router.refresh() after mutations
- DemoTooltip + disabled on Nieuw + Archive
- Empty-state + filtered-empty messaging
components/ideas/idea-row-actions.tsx (placeholder for T-508):
- "Open" navigation + "Archive" button only — Grill / Make Plan /
Materialiseer come in T-508 with full disabled-rules
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>