# FO/TO/Bouwplan: Cortex Intake Blocks MVP **Projectnaam:** Cortex Intake Blocks - MVP **Versie:** v1.0 **Datum:** 03-02-2026 **Auteur:** Colin Lit (met AI-assistentie) --- ## 1. Doel en Context ### 1.1 Doel van dit document Dit gecombineerde document beschrijft de **functionele specificaties**, **technische architectuur** en **bouwplan** voor de MVP van Cortex Intake Blocks. Het combineert FO, TO en Bouwplan in één referentiedocument. ### 1.2 Context De Cortex Command Center heeft werkende intents voor dagnotities, zoeken en overdracht. De **26 intake-gerelateerde intents** ontbreken volledig (zie `gap-analyse-intake-cortex.md`). Dit document beschrijft de **MVP fase**: de 4 meest waardevolle blocks die het intake-proces via spraak ontsluiten. ### 1.3 Relatie met andere documenten | Document | Relatie | |----------|---------| | `intake-process-intents.md` | Volledige intent definities (26 intents) | | `gap-analyse-intake-cortex.md` | Analyse wat ontbreekt | | `fo-to-cortex-shared-components.md` | Shared components (gebouwd) | | `bouwplan-cortex-shared-components.md` | Bouwplan shared components (afgerond) | ### 1.4 Scope **In scope (MVP):** - `IntakeStatusBlock` - Checklist voortgang - `RisicoBlock` - Risico's met severity levels - `DiagnoseBlock` - Diagnoses lijst - `intake_navigeer` intent - Navigatie naar tabs **Buiten scope (Fase 2+):** - ScreeningBlock, KindcheckBlock, AnamneseBlock - BehandeladviesBlock, IntakeListBlock - IntakeSamenvattingBlock (AI) - Actie-intents (toevoegen via spraak) --- ## 1.5 Roadmap: Alle Intake Fases > **Let op:** Dit MVP dekt alleen Fase 3. De overige fases staan hieronder gepland voor toekomstige iteraties. ### Overzicht Fases ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ INTAKE PROCES ROADMAP │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │ │ │ FASE 1 │ │ FASE 2 │ │ FASE 3 │ │ FASE 4 │ │ │ │ SCREENING │───▶│ INTAKE START │───▶│ UITVOERING │───▶│ AFSLUITEN │ │ │ │ │ │ │ │ │ │ │ │ │ │ ⏳ Later │ │ ⏳ Later │ │ ✅ MVP │ │ ⏳ Later │ │ │ │ 4 intents │ │ 2 intents │ │ 4 intents │ │ 3 intents │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ └───────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ### Fase 1: Screening (⏳ Toekomstig) | Intent | Type | Beschrijving | Block | |--------|------|--------------|-------| | `screening_query` | Query | Toon screening overzicht | ScreeningBlock | | `hulpvraag_invoer` | Actie | Hulpvraag invullen | - | | `screening_besluit` | Actie | Geschikt/niet geschikt | - | | `screening_activiteit` | Actie | Activiteit toevoegen | - | **Prioriteit:** Middel (eenmalige actie per patiënt) ### Fase 2: Intake Starten (⏳ Toekomstig) | Intent | Type | Beschrijving | Block | |--------|------|--------------|-------| | `intake_starten` | Actie | Nieuwe intake aanmaken | NewIntakeForm | | `intake_lijst` | Query | Alle intakes van patiënt | IntakeListBlock | **Prioriteit:** Middel (eenmalige actie per intake) ### Fase 3: Intake Uitvoering (✅ MVP) | Intent | Type | Beschrijving | Block | Status | |--------|------|--------------|-------|--------| | `intake_status` | Query | Checklist voortgang | IntakeStatusBlock | ✅ MVP | | `intake_navigeer` | Navigatie | Naar specifieke tab | - | ✅ MVP | | `risico_query` | Query | Risico's tonen | RisicoBlock | ✅ MVP | | `diagnose_query` | Query | Diagnoses tonen | DiagnoseBlock | ✅ MVP | | `kindcheck_query` | Query | Kindcheck status | KindcheckBlock | ⏳ Fase 3b | | `anamnese_query` | Query | Anamnese overzicht | AnamneseBlock | ⏳ Fase 3b | | `behandeladvies_query` | Query | Behandeladvies | BehandeladviesBlock | ⏳ Fase 3b | | `contacten_query` | Query | Contactmomenten | - | ⏳ Fase 3c | | `onderzoeken_query` | Query | Onderzoeken | - | ⏳ Fase 3c | | `rom_query` | Query | ROM scores | - | ⏳ Fase 3c | | `*_toevoegen` (6x) | Actie | Data invoeren via spraak | - | ⏳ Fase 3d | ### Fase 4: Intake Afsluiten (⏳ Toekomstig) | Intent | Type | Beschrijving | Block | |--------|------|--------------|-------| | `intake_afsluiten` | Actie | Intake afronden | - | | `intake_samenvatting` | Query | AI-samenvatting | IntakeSamenvattingBlock | | `intake_checklist` | Query | Wat nog te doen | IntakeStatusBlock (hergebruik) | **Prioriteit:** Middel-Hoog (AI-samenvatting is waardevol) ### Iteratie Planning | Iteratie | Fases | Intents | Geschatte effort | |----------|-------|---------|------------------| | **MVP (nu)** | 3a | 4 | 16 uur | | Iteratie 2 | 3b | +3 | 8 uur | | Iteratie 3 | 1 + 4 | +7 | 12 uur | | Iteratie 4 | 2 + 3c | +5 | 10 uur | | Iteratie 5 | 3d (acties) | +6 | 16 uur | | **Totaal** | Alle | 26 | ~62 uur | --- ## 2. Overzicht MVP Blocks ``` ┌─────────────────────────────────────────────────────────────────┐ │ CORTEX MVP │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ "Wat moet ik nog doen?" "Wat zijn de risico's?" │ │ ↓ ↓ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ IntakeStatus │ │ RisicoBlock │ │ │ │ Block │ │ │ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ │ │ ✅ Algemeen │ │ │ │Suïcide [M] │ │ │ │ │ │ ❌ Kindcheck│ │ │ │Agressie [L] │ │ │ │ │ │ ❌ Risico │ │ │ └─────────────┘ │ │ │ │ │ ✅ Diagnose │ │ │ │ │ │ │ └─────────────┘ │ │ [Bekijk] [+] │ │ │ └─────────────────┘ └─────────────────┘ │ │ │ │ "Welke diagnoses?" "Ga naar risicotaxatie" │ │ ↓ ↓ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ DiagnoseBlock │ │ Navigation │ │ │ │ │ │ (geen block) │ │ │ │ ┌─────────────┐ │ │ │ │ │ │ │F32.1 Depr. │ │ │ router.push() │ │ │ │ │F41.1 Angst │ │ │ naar intake tab │ │ │ │ └─────────────┘ │ │ │ │ │ │ [Bekijk] [+] │ └─────────────────┘ │ │ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 3. User Stories | ID | Rol | Doel / Actie | Verwachte waarde | Prioriteit | |----|-----|--------------|------------------|------------| | US-IB-01 | Behandelaar | "Wat moet ik nog doen?" vragen | Ziet checklist van intake voortgang | Hoog | | US-IB-02 | Behandelaar | "Wat zijn de risico's?" vragen | Ziet risico's met severity levels | Hoog | | US-IB-03 | Behandelaar | "Welke diagnoses heeft Jan?" vragen | Ziet diagnoses met ICD-10 codes | Hoog | | US-IB-04 | Behandelaar | "Ga naar diagnose" zeggen | Navigeert direct naar diagnose tab | Hoog | | US-IB-05 | Behandelaar | Op "Bekijk in dossier" klikken | Opent volledige EPD view | Middel | | US-IB-06 | Behandelaar | Zien welke secties verplicht zijn | Weet wat minimaal ingevuld moet | Middel | --- ## 4. Functionele Specificaties per Block ### 4.1 IntakeStatusBlock **Intent:** `intake_status` **Trigger voorbeelden:** "Wat moet ik nog doen?", "Is de intake compleet?", "Intake checklist" **Functioneel gedrag:** 1. **Context check:** Block vereist actieve intake (intakeId) 2. **Data laden:** Haal completion status op per sectie 3. **Weergave:** - Progress bar met percentage - Lijst van alle 9 secties met status (✅/❌) - Verplichte secties gemarkeerd - Onvolledige verplichte secties highlighted (amber) 4. **Interactie:** - Klik op sectie → navigeer naar die tab in EPD - "Intake afsluiten" knop (disabled als niet compleet) **Visueel:** ``` ┌─────────────────────────────────────────────────────┐ │ Intake Status - Jan de Vries [X] │ ├─────────────────────────────────────────────────────┤ │ │ │ Voortgang 6/9 (67%) │ │ [████████████░░░░░░] │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ ⚠️ Nog te voltooien (3) │ │ │ │ │ │ │ │ Kindcheck [>] │ │ │ │ Risicotaxatie [>] │ │ │ │ Behandeladvies [>] │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ ✅ Algemeen │ │ ✅ Contactmomenten │ │ ❌ Kindcheck [Verplicht] │ │ ❌ Risicotaxatie [Verplicht] │ │ ✅ Anamnese │ │ ✅ Onderzoeken │ │ ✅ ROM │ │ ✅ Diagnose │ │ ❌ Behandeladvies [Verplicht] │ │ │ └─────────────────────────────────────────────────────┘ ``` **States:** - Loading: `BlockLoading` met "Status laden..." - Error: `BlockError` met retry - No intake: `BlockEmpty` met "Geen actieve intake gevonden" - Complete: Groene banner "Intake is compleet!" --- ### 4.2 RisicoBlock **Intent:** `risico_query` **Trigger voorbeelden:** "Wat zijn de risico's?", "Risico's van Jan", "Toon risicotaxatie" **Functioneel gedrag:** 1. **Context check:** Block vereist actieve patient (patientId) en intake (intakeId) 2. **Data laden:** Haal risico assessments op 3. **Weergave:** - Lijst van risico's met type en severity level - Color-coded badges (groen/oranje/rood) - Datum en beoordelaar per risico 4. **Interactie:** - "Bekijk in dossier" → navigeer naar risicotaxatie tab - "Toevoegen" → navigeer naar risicotaxatie tab (fase 2: inline toevoegen) **Risico levels en kleuren:** | Level | Badge | Kleur | |-------|-------|-------| | Laag | `success` | Groen | | Gemiddeld/Matig | `warning` | Oranje | | Hoog | `danger` | Rood | | Zeer hoog | `danger` | Rood | **Visueel:** ``` ┌─────────────────────────────────────────────────────┐ │ Risicotaxatie [X] │ ├─────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ ⚠️ Huidige risico's (3) │ │ │ │ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ Suïcidaliteit [Matig] │ │ │ │ │ │ 12 jan 2026 • Dr. Jansen │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ Agressie [Laag] │ │ │ │ │ │ 10 jan 2026 • Dr. Bakker │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ Zelfverwaarlozing [Laag] │ │ │ │ │ │ 10 jan 2026 • Dr. Bakker │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ ───────────────────────────────────────────────── │ │ [🔗 Bekijk in dossier] [+ Toevoegen] │ │ │ └─────────────────────────────────────────────────────┘ ``` **States:** - Loading: `BlockLoading` met "Risico's laden..." - Error: `BlockError` met retry - No patient: `BlockEmpty` met "Selecteer eerst een patiënt" - No risks: `BlockEmpty` met "Geen risico's geregistreerd" + actie --- ### 4.3 DiagnoseBlock **Intent:** `diagnose_query` **Trigger voorbeelden:** "Welke diagnoses?", "Diagnose van Jan", "Toon diagnoses" **Functioneel gedrag:** 1. **Context check:** Block vereist patient en intake 2. **Data laden:** Haal diagnoses op met ICD-10 codes 3. **Weergave:** - Hoofddiagnose vs bijdiagnoses - ICD-10 code + omschrijving - Datum vastgesteld 4. **Interactie:** - "Bekijk in dossier" → navigeer naar diagnose tab - "Toevoegen" → navigeer naar diagnose tab **Visueel:** ``` ┌─────────────────────────────────────────────────────┐ │ Diagnoses [X] │ ├─────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ 🏥 Hoofddiagnose │ │ │ │ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ F32.1 Depressieve stoornis, matig │ │ │ │ │ │ 15 jan 2026 │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ 📋 Nevendiagnoses (2) │ │ │ │ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ F41.1 Gegeneraliseerde angststoornis │ │ │ │ │ │ 15 jan 2026 │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ Z73.0 Burnout │ │ │ │ │ │ 12 jan 2026 │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ ───────────────────────────────────────────────── │ │ [🔗 Bekijk in dossier] [+ Toevoegen] │ │ │ └─────────────────────────────────────────────────────┘ ``` --- ### 4.4 Intake Navigatie (geen block) **Intent:** `intake_navigeer` **Trigger voorbeelden:** "Ga naar diagnose", "Open kindcheck", "Naar risicotaxatie" **Functioneel gedrag:** 1. **Context check:** Vereist actieve patient en intake 2. **Tab mapping:** Parse target tab uit input 3. **Navigatie:** `router.push()` naar correcte URL 4. **Feedback:** Toast "Navigeren naar [tab]..." **Tab mapping:** | Input keywords | Target tab | URL path | |----------------|------------|----------| | algemeen, basis | algemeen | `/intakes/[id]` | | contact, gesprek | contactmomenten | `/intakes/[id]/contacts` | | kindcheck, kinderen | kindcheck | `/intakes/[id]/kindcheck` | | risico, risicotaxatie | risicotaxatie | `/intakes/[id]/risks` | | anamnese, voorgeschiedenis | anamnese | `/intakes/[id]/anamnese` | | onderzoek | onderzoeken | `/intakes/[id]/examinations` | | rom, vragenlijst | rom | `/intakes/[id]/rom` | | diagnose | diagnose | `/intakes/[id]/diagnosis` | | behandeladvies, advies | behandeladvies | `/intakes/[id]/advice` | --- ## 5. Technische Architectuur ### 5.1 Component Structuur ``` components/cortex/blocks/ ├── block-container.tsx ✅ Bestaat ├── intake-status-block.tsx 🆕 Nieuw ├── risico-block.tsx 🆕 Nieuw ├── diagnose-block.tsx 🆕 Nieuw └── ... (bestaande blocks) lib/cortex/ ├── types.ts 📝 Update (nieuwe intents) ├── reflex-classifier.ts 📝 Update (nieuwe patterns) ├── handlers/ │ └── intake-navigator.ts 🆕 Nieuw (navigatie handler) └── hooks/ ├── use-block-data.ts ✅ Bestaat (shared components) └── use-intake-context.ts ✅ Bestaat (shared components) app/api/cortex/ ├── intake/ │ ├── [intakeId]/ │ │ ├── status/route.ts 🆕 Nieuw │ │ ├── risks/route.ts 🆕 Nieuw │ │ └── diagnoses/route.ts 🆕 Nieuw ``` ### 5.2 Data Flow ``` User Input Cortex EPD │ │ │ │ "Wat zijn de risico's?" │ │ │ ─────────────────────────> │ │ │ │ │ Reflex Classifier │ │ intent: risico_query │ │ confidence: 0.95 │ │ │ │ │ Open RisicoBlock │ │ │ │ │ │ GET /api/cortex/intake/ │ │ │ {id}/risks │ │ │ ─────────────────────────────> │ │ │ │ │ getRiskAssessments() │ │ │ <───────────────────────────── │ │ │ │ Render RisicoBlock │ │ │ <───────────────────────── │ ``` ### 5.3 Bestaande Data Functies Deze server actions bestaan al en kunnen hergebruikt worden: | Functie | Bestand | Gebruikt door | |---------|---------|---------------| | `getIntakeById()` | `lib/actions/intake-actions.ts` | IntakeStatusBlock | | `getRiskAssessments()` | `lib/actions/intake-actions.ts` | RisicoBlock | | `getDiagnoses()` | `lib/actions/intake-actions.ts` | DiagnoseBlock | | `getKindcheck()` | `lib/actions/intake-actions.ts` | IntakeStatusBlock | | `getTreatmentAdvice()` | `lib/actions/intake-actions.ts` | IntakeStatusBlock | --- ## 6. API Ontwerp ### 6.1 Nieuwe Endpoints #### GET `/api/cortex/intake/[intakeId]/status` **Doel:** Intake completion status voor IntakeStatusBlock **Response:** ```typescript interface IntakeStatusResponse { intakeId: string; intakeTitle: string; patientId: string; patientName: string; completedCount: number; totalCount: number; sections: Array<{ key: string; // 'algemeen' | 'kindcheck' | etc. label: string; // 'Kindcheck' completed: boolean; required: boolean; path: string; // 'kindcheck' (for URL) }>; } ``` **Logica per sectie:** | Sectie | Completed wanneer | Verplicht | |--------|-------------------|-----------| | algemeen | Intake bestaat | ✅ | | contactmomenten | ≥1 contact | ❌ | | kindcheck | `hasChildren !== null` | ✅* | | risicotaxatie | ≥1 risico assessment | ✅ | | anamnese | ≥1 anamnese entry | ✅ | | onderzoeken | ≥1 onderzoek | ❌ | | rom | ≥1 ROM meting | ❌ | | diagnose | ≥1 diagnose | ✅ | | behandeladvies | advice niet leeg | ✅ | *Kindcheck wettelijk verplicht bij patiënten met kinderen --- #### GET `/api/cortex/intake/[intakeId]/risks` **Doel:** Risico assessments voor RisicoBlock **Response:** ```typescript interface RisksResponse { intakeId: string; patientId: string; risks: Array<{ id: string; type: string; // 'suicidaliteit' | 'agressie' | etc. typeLabel: string; // 'Suïcidaliteit' level: string; // 'laag' | 'gemiddeld' | 'hoog' | 'zeer_hoog' levelLabel: string; // 'Matig' rationale?: string; assessedAt: string; // ISO date assessedBy?: string; // Naam beoordelaar }>; } ``` --- #### GET `/api/cortex/intake/[intakeId]/diagnoses` **Doel:** Diagnoses voor DiagnoseBlock **Response:** ```typescript interface DiagnosesResponse { intakeId: string; patientId: string; primaryDiagnosis: Diagnosis | null; secondaryDiagnoses: Diagnosis[]; } interface Diagnosis { id: string; code: string; // ICD-10 code: 'F32.1' description: string; // 'Depressieve stoornis, matig' isPrimary: boolean; diagnosedAt: string; // ISO date diagnosedBy?: string; } ``` --- ## 7. Intent & Pattern Configuratie ### 7.1 Nieuwe Intent Types ```typescript // lib/cortex/types.ts - toevoegen aan CortexIntent type CortexIntent = | 'dagnotitie' | 'zoeken' | 'overdracht' | 'agenda_query' | 'create_appointment' | 'cancel_appointment' | 'reschedule_appointment' // MVP Intake intents | 'intake_status' // 🆕 | 'risico_query' // 🆕 | 'diagnose_query' // 🆕 | 'intake_navigeer' // 🆕 | 'unknown'; ``` ### 7.2 Reflex Patterns ```typescript // lib/cortex/reflex-classifier.ts - toevoegen // intake_status { pattern: /^(wat\s+)?moet\s+ik\s+nog\s+(doen|invullen)/i, intent: 'intake_status', weight: 1.0 }, { pattern: /^is\s+(de\s+)?intake\s+compleet/i, intent: 'intake_status', weight: 0.95 }, { pattern: /^intake\s+(checklist|status|voortgang)/i, intent: 'intake_status', weight: 0.9 }, { pattern: /^welke\s+secties\s+(zijn|nog)/i, intent: 'intake_status', weight: 0.85 }, // risico_query { pattern: /^(wat\s+zijn\s+)?(de\s+)?risico'?s/i, intent: 'risico_query', weight: 1.0 }, { pattern: /^(toon|show)\s+risico/i, intent: 'risico_query', weight: 0.95 }, { pattern: /^risicotaxatie/i, intent: 'risico_query', weight: 0.9 }, // diagnose_query { pattern: /^(welke\s+)?diagnose[ns]?(\s+heeft)?/i, intent: 'diagnose_query', weight: 1.0 }, { pattern: /^(toon|show)\s+diagnose/i, intent: 'diagnose_query', weight: 0.95 }, { pattern: /^wat\s+is\s+(de\s+)?diagnose/i, intent: 'diagnose_query', weight: 0.9 }, // intake_navigeer { pattern: /^ga\s+naar\s+(de\s+)?(risico|diagnose|kindcheck|anamnese|rom|behandel)/i, intent: 'intake_navigeer', weight: 1.0 }, { pattern: /^open\s+(de\s+)?(risico|diagnose|kindcheck|anamnese)/i, intent: 'intake_navigeer', weight: 0.95 }, { pattern: /^naar\s+(risico|diagnose|kindcheck)/i, intent: 'intake_navigeer', weight: 0.9 }, ``` ### 7.3 Block Configs ```typescript // lib/cortex/types.ts - toevoegen aan BLOCK_CONFIGS 'intake-status': { type: 'intake-status', title: 'Intake Status', size: 'md', icon: 'ClipboardList', }, 'risico-query': { type: 'risico-query', title: 'Risicotaxatie', size: 'md', icon: 'AlertTriangle', }, 'diagnose-query': { type: 'diagnose-query', title: 'Diagnoses', size: 'md', icon: 'Stethoscope', }, ``` --- ## 8. Epics & Stories ### 8.1 Overzicht | Epic ID | Titel | Doel | Stories | Geschat | Status | |---------|-------|------|---------|---------|--------| | E0 | Intent Setup | Types, patterns, configs | 3 | 2 uur | ✅ Done | | E1 | API Routes | Endpoints voor data | 3 | 3 uur | ✅ Done | | E2 | IntakeStatusBlock | Checklist block | 2 | 3 uur | ✅ Done | | E3 | RisicoBlock | Risico's block | 2 | 2 uur | ✅ Done | | E4 | DiagnoseBlock | Diagnoses block | 2 | 2 uur | ✅ Done | | E5 | Navigatie | intake_navigeer handler | 2 | 2 uur | ✅ Done | | E6 | Integratie | Canvas-area + testing | 2 | 2 uur | ⚠️ Partial | **Totaal geschat:** ~16 uur (2 werkdagen) **Status:** MVP functioneel (6/7 epics done), E2E testing nog te doen --- ### 8.2 Epic 0 — Intent Setup ✅ **Doel:** Cortex kan de nieuwe intents herkennen. | Story ID | Beschrijving | Acceptatiecriteria | Status | SP | |----------|--------------|---------------------|--------|-----| | E0.S1 | Intent types toevoegen | 4 nieuwe intents in `CortexIntent` type | ✅ | 1 | | E0.S2 | Reflex patterns toevoegen | Patterns voor alle 4 intents, confidence ≥0.85 | ✅ | 2 | | E0.S3 | Block configs toevoegen | BLOCK_CONFIGS voor 3 blocks | ✅ | 1 | **Afhankelijkheden:** Geen **Geïmplementeerd:** `lib/cortex/types.ts`, `reflex-classifier.ts`, `intent-classifier.ts`, `intent-labels.ts` --- ### 8.3 Epic 1 — API Routes ✅ **Doel:** Backend endpoints voor block data. | Story ID | Beschrijving | Acceptatiecriteria | Status | SP | |----------|--------------|---------------------|--------|-----| | E1.S1 | `/api/cortex/intake/status` | Returns completion status, tested | ✅ | 3 | | E1.S2 | `/api/cortex/intake/risico` | Returns risks array, tested | ✅ | 2 | | E1.S3 | `/api/cortex/intake/diagnose` | Returns diagnoses, tested | ✅ | 2 | **Afhankelijkheden:** E0 **Geïmplementeerd:** `app/api/cortex/intake/status/route.ts`, `risico/route.ts`, `diagnose/route.ts` **Opmerking:** URL structuur gewijzigd naar `?patientId=xxx&intakeId=xxx` ipv `[intakeId]` path param --- ### 8.4 Epic 2 — IntakeStatusBlock ✅ **Doel:** Werkend IntakeStatusBlock component. | Story ID | Beschrijving | Acceptatiecriteria | Status | SP | |----------|--------------|---------------------|--------|-----| | E2.S1 | Block component bouwen | Gebruikt shared components, alle states | ✅ | 5 | | E2.S2 | Navigatie naar secties | Klik op sectie opent EPD tab | ✅ | 2 | **Afhankelijkheden:** E0, E1.S1 **Geïmplementeerd:** `components/cortex/blocks/intake-status-block.tsx` **Features:** CompletionRing (SVG), verplichte/optionele secties, "Naar intake" footer actie --- ### 8.5 Epic 3 — RisicoBlock ✅ **Doel:** Werkend RisicoBlock component. | Story ID | Beschrijving | Acceptatiecriteria | Status | SP | |----------|--------------|---------------------|--------|-----| | E3.S1 | Block component bouwen | Gebruikt shared components, color-coded badges | ✅ | 3 | | E3.S2 | Footer acties | "Bekijk in dossier" werkt | ✅ | 1 | **Afhankelijkheden:** E0, E1.S2 **Geïmplementeerd:** `components/cortex/blocks/risico-block.tsx` **Features:** RiskSummaryCard (suïcide/zelfbeschadiging/agressie flags), severity badges, "Naar risicotaxaties" footer --- ### 8.6 Epic 4 — DiagnoseBlock ✅ **Doel:** Werkend DiagnoseBlock component. | Story ID | Beschrijving | Acceptatiecriteria | Status | SP | |----------|--------------|---------------------|--------|-----| | E4.S1 | Block component bouwen | Hoofddiagnose + nevendiagnoses gescheiden | ✅ | 3 | | E4.S2 | Footer acties | "Bekijk in dossier" werkt | ✅ | 1 | **Afhankelijkheden:** E0, E1.S3 **Geïmplementeerd:** `components/cortex/blocks/diagnose-block.tsx` **Features:** PrimaryDiagnosisCard, clinical status badges, ICD-10 codes, "Naar diagnoses" footer --- ### 8.7 Epic 5 — Navigatie Handler ✅ **Doel:** `intake_navigeer` intent werkt. | Story ID | Beschrijving | Acceptatiecriteria | Status | SP | |----------|--------------|---------------------|--------|-----| | E5.S1 | Tab parser bouwen | Extraheert target tab uit input | ✅ | 2 | | E5.S2 | Navigation handler | router.push() naar correcte URL, toast feedback | ✅ | 2 | **Afhankelijkheden:** E0 **Geïmplementeerd:** - Entity extraction in `lib/cortex/entity-extractor.ts` (INTAKE_TAB_KEYWORDS, extractIntakeNavigeerEntities) - `navigationTarget` field toegevoegd aan ExtractedEntities type - `lib/cortex/action-parser.ts` - intake intents toegevoegd aan schema en routing - `components/cortex/command-center/command-center.tsx` - navigation handler met router.push() en toast feedback **Opmerking:** Navigeert naar `/epd/patients/{id}/intakes` (intake lijst). Volledige tab-navigatie vereist intakeId selectie. --- ### 8.8 Epic 6 — Integratie ⚠️ **Doel:** Alles werkt samen in Cortex. | Story ID | Beschrijving | Acceptatiecriteria | Status | SP | |----------|--------------|---------------------|--------|-----| | E6.S1 | Canvas-area updaten | Rendert nieuwe blocks op basis van intent | ✅ | 2 | | E6.S2 | E2E testing | Alle 4 intents werken via voice/text input | ⏳ | 3 | **Afhankelijkheden:** E2, E3, E4, E5 **Geïmplementeerd:** - `components/cortex/command-center/canvas-area.tsx` - imports en switch cases voor 3 blocks - `components/cortex/command-center/recent-strip.tsx` - INTENT_CONFIG voor nieuwe intents **TODO:** E2E testing met echte voice/text input --- ## 9. Implementatie Volgorde ``` Week 1: ┌─────────────────────────────────────────────────────────────────┐ │ Dag 1 │ │ ├── E0.S1 Intent types │ │ ├── E0.S2 Reflex patterns │ │ ├── E0.S3 Block configs │ │ └── E1.S1 /status API route │ │ │ │ Dag 2 │ │ ├── E1.S2 /risks API route │ │ ├── E1.S3 /diagnoses API route │ │ ├── E2.S1 IntakeStatusBlock │ │ └── E2.S2 Status navigatie │ │ │ │ Dag 3 (half) │ │ ├── E3.S1 RisicoBlock │ │ ├── E3.S2 Risico footer │ │ ├── E4.S1 DiagnoseBlock │ │ └── E4.S2 Diagnose footer │ │ │ │ Dag 3 (half) + Buffer │ │ ├── E5.S1 Tab parser │ │ ├── E5.S2 Navigation handler │ │ ├── E6.S1 Canvas-area update │ │ └── E6.S2 E2E testing │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 10. Dependencies Check ### 10.1 Bestaande code (hergebruiken) | Dependency | Pad | Status | |------------|-----|--------| | BlockContainer | `components/cortex/blocks/block-container.tsx` | ✅ | | BlockLoading, BlockError, BlockEmpty | `components/cortex/shared/block-states.tsx` | ✅ | | BlockSection, BlockItem, BlockFooter | `components/cortex/shared/` | ✅ | | useBlockData, useIntakeContext | `lib/cortex/hooks/` | ✅ | | useCortexStore | `stores/cortex-store.ts` | ✅ | | safeFetch, getErrorInfo | `lib/cortex/error-handler.ts` | ✅ | | getRiskAssessments | `lib/actions/intake-actions.ts` | ✅ | | getDiagnoses | `lib/actions/intake-actions.ts` | ✅ | ### 10.2 Nieuw te bouwen | Item | Type | Epic | |------|------|------| | 4 intent types | TypeScript | E0 | | ~12 reflex patterns | Config | E0 | | 3 block configs | Config | E0 | | 3 API routes | Next.js API | E1 | | IntakeStatusBlock | React component | E2 | | RisicoBlock | React component | E3 | | DiagnoseBlock | React component | E4 | | Navigation handler | TypeScript | E5 | --- ## 11. Risico's & Mitigatie | Risico | Kans | Impact | Mitigatie | |--------|------|--------|-----------| | Intake context niet beschikbaar | Middel | Hoog | Fallback naar patient-selectie block | | Meerdere intakes per patient | Middel | Middel | Gebruik meest recente of vraag clarificatie | | Bestaande actions niet compatible | Laag | Hoog | Wrapper functies voor Cortex API | | Pattern overlap met bestaande intents | Laag | Middel | Specifieke patterns, hogere weights | --- ## 12. Definition of Done **Per Story:** - [x] Code geschreven volgens specs - [x] TypeScript compileert zonder errors - [x] ESLint geen errors - [x] Component werkt in browser - [ ] Alle states getest (loading, error, empty, data) **Per Epic:** - [x] E0-E4 stories DONE - [x] Integratie met andere epics getest - [ ] Code reviewed **Project DONE:** - [x] 6/7 epics volledig DONE (E0-E5) - [x] 1/7 epic partial (E6 - testing) - [x] Alle 4 intents werken (3 blocks + 1 navigatie) - [x] `pnpm build` succesvol - [ ] Demo scenario werkt (E2E testing) - [x] Commit: `b095b1e` feat(cortex): add Intake Blocks MVP --- ## 13. Referenties **Project documenten:** - `docs/intent/intake-intent-proces/intake-process-intents.md` - `docs/intent/intake-intent-proces/gap-analyse-intake-cortex.md` - `docs/intent/intake-intent-proces/fo-to-cortex-shared-components.md` **Bestaande code:** - `components/cortex/blocks/` - Block voorbeelden - `lib/cortex/reflex-classifier.ts` - Pattern voorbeelden - `lib/actions/intake-actions.ts` - Data functies --- ## Versiehistorie | Versie | Datum | Auteur | Wijziging | |--------|-------|--------|-----------| | v1.0 | 03-02-2026 | Colin Lit | Initiële versie | | v1.1 | 03-02-2026 | Colin Lit | Status update: E0-E4 done, E5-E6 partial | | v1.2 | 03-02-2026 | Colin Lit | E5.S2 done: navigation handler in command-center.tsx |