* feat(jobs): voeg lib/jobs-time-filter.ts toe met tijdvenster-predikaat
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(user-settings): voeg views.jobs.timeFilter toe aan UserSettingsSchema
Breidt ViewsPrefs uit met een jobs-object (JobsViewPrefs) dat timeFilter
accepteert met waarden '1h' | '24h' | 'all'. ViewsPrefs blijft .strict().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(jobs-time-filter): voeg unit-tests toe voor isWithinTimeWindow en UserSettings-schema
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(jobs-time-filter): voeg JobsTimeFilterControl component toe
Nieuw client-component dat views.jobs.timeFilter leest/schrijft
via useUserSettingsStore met pill-stijl (MD3-tokens).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(jobs): wire JobsTimeFilter in jobs page header
Plaatst het tijdfilter-component rechts van de Jobs-kop via justify-between op de header-div.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(jobs): pas tijdvenster-filter toe in JobsColumn
Lees views.jobs.timeFilter uit de store en filter jobs op createdAt via isWithinTimeWindow, als eerste check vóór de bestaande kind/status-filters.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
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>
* feat(PBI-76): one-shot localStorage→user-settings migration helper
Reads all legacy keys (sprint_pb_*, pbi_*, story_sort, debug-mode,
and dynamic *_filter_kind/*_filter_status for jobs columns) and
returns a typed UserSettings patch plus the keys to clear.
Idempotent via scrum4me:settings_migrated=v1 marker. Skips invalid
values silently so existing corrupt entries do not block migration.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(PBI-76): bridge runs one-shot localStorage migration
After hydrate, scans legacy localStorage keys via buildMigrationPatch
and, if any data is found, pushes one bulk patch to the server,
applies it locally, then removes the legacy keys. Demo accounts skip
the migration entirely. Cancellable on unmount to avoid setState on
unmounted component.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(PBI-76): migrate sprint-backlog to user-settings store
Replaces six useState+useEffect+localStorage flows with selectors
from useUserSettingsStore. Defaults are applied at the selector
level (filterStatus 'OPEN', sort 'code', etc) so the component
matches its previous behaviour. The collapsed Set is derived from
the persisted array, falling back to auto-collapse-DONE when no
preference exists yet. setPref calls are fire-and-forget — the
optimistic flow handles the local state update.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(PBI-76): migrate pbi-list to user-settings store
Same pattern as sprint-backlog: replaces local useState +
localStorage hydration/persist with selectors from
useUserSettingsStore. filterPopoverOpen blijft lokaal — die
was nooit gepersisteerd in pbi-list.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(PBI-76): migrate story-panel sort to user-settings store
Single pref (sortMode) — replaces sync localStorage useState
initializer with a selector. Default 'priority' applied at
the read site.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(PBI-76): migrate jobs-column to user-settings store
Per-instance filter state (kinds + statuses) now lives under
views.jobsColumns[storageKeyPrefix] in user-settings. Removes
the local CSV-encoding helpers — store keeps arrays natively.
A single persist() call writes both fields together so the
two arrays cannot drift in optimistic mid-flight updates.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(PBI-76): migrate debug-mode to user-settings store
DebugToggle reads debugMode from user-settings.devTools and
toggles via setPref. Removes the standalone stores/debug-store.ts
(no consumers left). Body classlist update only fires after the
store is hydrated to avoid a flash on initial paint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(PBI-76): remove unused readLocalStoragePref helper
No consumers left after migrating sprint-backlog, pbi-list,
story-panel, jobs-column, and debug-store to user-settings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(PBI-76): mock user-settings action in backlog integration test
PbiList now imports the user-settings store, which transitively
loads actions/user-settings.ts → lib/prisma. The vitest jsdom
environment has no DATABASE_URL, so we add a mock alongside the
existing action mocks.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(docs): allow balanced parens in markdown link URLs
Previously the link-checker regex stopped at the first ')',
breaking on Next.js route-group paths like `app/(app)/...`. The
new regex matches one level of balanced parens inside the URL.
Caught by CI on PR #188 — pre-existing breakage from PBI-78 plan
doc that was already merged on main.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Move sprint switcher into sprint header, centered between title and actions
- Extract BacklogFilterPopover as shared component used by sprint and product backlog
- Add sort options (code/priority/status) with single-pill asc/desc toggle
- Default sprint backlog status filter to OPEN, remove "alleen niet klaar" button
- Persist collapsed state and filter popover open in localStorage
- Fix hydration flicker: defer localStorage read to useEffect with prefsLoaded gate for writes
- Increase sprint switcher text size for readability
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(PBI-jobs): voeg isDemo-prop door aan JobsBoard en JobDetailPane
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-jobs): voeg 'Opnieuw starten'-knop toe aan JobDetailPane
Toont een restart-knop voor jobs met status FAILED, CANCELLED of SKIPPED.
Gebruikt useTransition voor loading-state en DemoTooltip voor demo-modus.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(PBI-jobs): voeg component-test toe voor JobDetailPane restart-knop
Test: knop zichtbaar voor FAILED, verborgen voor DONE, aanroep met juist id, disabled in demo-modus.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(PBI-jobs): voeg F-14 restart-acceptatiecriteria toe aan functional.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Filter-pills zijn nu toggle-knoppen; meerdere waardes per dimensie selecteerbaar
- "Alle"-pill wist de selectie binnen die dimensie
- Eén active-badge per geselecteerde waarde, klikbaar om losse selectie te wissen
- localStorage formaat is nu CSV met whitelist-validatie (oude 'all'-waarde valt vanzelf weg → leeg = geen filter)
- Filtercount in trigger toont som van actieve selecties
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Nieuwe JobsColumn met Kind/Status filter-popover per kolom (Actief/Klaar)
- Filterstate persistent in localStorage (whitelist-validatie tegen corrupte waardes)
- Active-filter badges in kolomheader, klikbaar om te wissen
- Aanmaakdatum + tijd rechtsonder op elke JobCard (nl-NL short formaat)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Voegt een verplicht code-veld toe aan Sprint, sequentieel per product
(consistent met PBI-N, ST-NNN, T-N).
- **Schema** — `Sprint.code String @db.VarChar(30)` + `@@unique([product_id, code])`
- **Migratie** — voegt kolom toe als nullable, backfillt bestaande sprints
via `ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY created_at)`
als `SP-N`, en zet daarna NOT NULL + UNIQUE.
- **Generator** — `generateNextSprintCode(productId)` in lib/code-server.ts
volgt het patroon van story/pbi/task; createSprintAction gebruikt
`createWithCodeRetry` voor race-bescherming.
- **Seed** — sprint-counter per product (`SP-1`, `SP-2`, ...).
Zichtbaar in:
- Sprint-header (`Product › Sprint actief · SP-3`)
- JobCard + JobDetailPane voor SPRINT_IMPLEMENTATION jobs
- Insights: VelocityChart x-axis (compacter dan goal-truncated),
AlignmentTrend tooltip, SprintInfoStrip
- actions/jobs-page.ts: `sprintCode` is weer een echte code i.p.v. null
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Splits het middenpaneel van de jobs-pagina in twee views (zoals admin/jobs):
- **Detail** — alle metadata (status, kind, product, branch, PR, dates,
errors, summary, verify-result) plus een kind-aware beschrijving:
TASK → implementation_plan, IDEA_GRILL → grill_md, IDEA_MAKE_PLAN →
plan_md, PLAN_CHAT → idea.description.
- **Usage** — model, tokens (in/uit/cache/totaal), berekende kosten in
USD via ModelPrice-tabel, en duur (started→finished).
SprintSubTasksPane blijft als sticky header boven beide views.
Server action `fetchJobsPageData` haalt nu ook ModelPrices op en
selecteert task.{description,implementation_plan} +
idea.{description,grill_md,plan_md} zodat de description en costUsd in
JobWithRelations gevuld kunnen worden.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(PBI-58): Vitest-tests voor SoloTaskCard veldmapping en 4-regels layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): server action fetchJobsPageData voor jobs-pagina
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): SSE-route /api/realtime/jobs voor user-scoped job-events
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): JobCard component voor jobs-pagina
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): JobDetailPane component voor jobs-pagina
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): API route GET /api/jobs/[id]/sub-tasks voor sprint task executions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): SprintSubTasksPane component voor jobs-pagina
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): Zustand store useJobsStore voor jobs-pagina
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): useJobsRealtime hook met SSE-verbinding en store-updates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): JobsBoard 3-kolom SplitPane client component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): /jobs server page met JobsBoard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): Jobs nav-link toevoegen aan NavBar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-58): Vitest-tests voor SoloTaskCard veldmapping en 4-regels layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): server action fetchJobsPageData voor jobs-pagina
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): SSE-route /api/realtime/jobs voor user-scoped job-events
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): JobCard component voor jobs-pagina
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): JobDetailPane component voor jobs-pagina
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(PBI-59): API route GET /api/jobs/[id]/sub-tasks voor sprint task executions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>