feature: Self-Service Clinical Testing Sessions
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
A production-quality clinical backend built with ASP.NET Core 8, PostgreSQL, Apache Kafka, RabbitMQ, Elasticsearch, Redis, and MinIO. The domain models the observe-alert-acknowledge lifecycle at the center of any clinical monitoring system: patient encounters, continuous vital sign and lab result ingest, real-time sepsis and NEWS2 scoring, and clinician notification with automatic escalation.
|
||||
|
||||
**Implementation status:** Thirty-three planned phases are complete through Phase 35 (plus Phases 20–23) — from schema and CRUD through Kafka, Elasticsearch CQRS, sepsis detection, RabbitMQ paging with DLQ escalation, reconciliation jobs, Prometheus/Grafana observability, the MinIO Parquet data lake, clinical data model expansion, warning alerts and orders, the NEWS2 composite scoring engine, trend detection with alert suppression, qSOFA bedside screening, medication administration with alert correlation annotations, the console replay simulator, the **Vue 3 ward dashboard**, clinician feedback mode, **Glasgow Coma Scale (GCS) scoring**, **SOFA organ-dysfunction scoring with baseline tracking and delta sepsis alerts**, the **Sepsis-3 clinical refactor** (SIRS removed, qSOFA repositioned as screening, SOFA delta ≥ 2 triggers bundles), **frontend GCS entry and SOFA display**, **expanded simulator scenarios with clinical validation**, the **Site & Gateway Registry** with dual authentication, shared clinical sync contracts, and fleet health Prometheus gauges, the **Ward Gateway Service** (local-first clinical path with offline buffering and central sync), the **FHIR R4 Inbound Facade** for EHR integration, **Role-Based Access Control (RBAC) with clinical audit logging**, the **Dashboard Gap Analysis Fixes** (SOFA/GCS/qSOFA history charts, patient banner, encounter timeline, medication markers on vital charts), the **Enhanced Dashboard** (department overview, sepsis bundle board, critical alert notifications, shift handoff reports, vitals entry form, sortable/filterable ward table), **Degraded Operations Visibility** (gateway fleet operations panel, stale gateway auto-detection, discharge summary API, admin panels for user/threshold/audit/reconciliation management, degraded-mode banner), **Alert Quality Analytics** (server-side clinician feedback with `AlertFeedback` entity, `AlertQualityAggregatorService` background metrics, quality metrics API, Grafana alert quality dashboard), **Explainable Alerts** (immutable JSONB `explanation` on composite alerts with score contributors, trend context, structured medication context, and bedside `NarrativeSummary`; `AlertResponse` DTO on GET/list/acknowledge/resolve; dashboard `AlertReasoning.vue`; ES indexer and data lake propagation; ward gateway sync), and **MIMIC-IV Replay Scenario Generator** (offline CLI tool converting real de-identified ICU data from MIT PhysioNet into VigilCare scenario JSONs; streaming CSV parser for 668K-row chartevents; 17 chart + 8 lab item ID mappings to VigilCare observation codes; GCS text-to-numeric conversion; Fahrenheit-to-Celsius; blood pressure deduplication preferring non-invasive over arterial; 10-observation cluster limit enforcement; `mimic-list` and `mimic-generate` CLI commands with Spectre.Console output; 100 patients / 140 ICU stays available for replay through NEWS2, SOFA, GCS, qSOFA, trend detection, and alerting). Post-phase hardening includes health check endpoints, Kafka poison pill protection, outbox dead-letter with retry tracking, data lake partial-commit safety, MRN sequence-based generation, FHIR bundle transaction rollback, **FHIR R4 read/search endpoints** (Patient and Encounter), **alert threshold deletion with audit trail**, **FHIR API key rotation** (constant-time multi-key validation), **authorization failure logging** with Prometheus metrics, **JWT signing key validation** at startup, **token refresh and revocation** (short-lived access tokens with rotating refresh tokens, server-side logout, proactive frontend refresh), and **concurrency hardening** (transactional sepsis bundle creation, unique active encounter constraint). See [Implemented Phases](#implemented-phases) for the full breakdown. Guides: [dashboard-guide.md](docs/dashboard-guide.md) (technical), [clinical-testing-guide.md](docs/clinical-testing-guide.md) (doctors & nurses).
|
||||
**Implementation status:** Phases **1–38** are complete — from schema and CRUD through Kafka, Elasticsearch CQRS, sepsis detection, RabbitMQ paging with DLQ escalation, reconciliation jobs, Prometheus/Grafana observability, the MinIO Parquet data lake, clinical data model expansion, warning alerts and orders, the NEWS2 composite scoring engine, trend detection with alert suppression, qSOFA bedside screening, medication administration with alert correlation annotations, the console replay simulator, the **Vue 3 ward dashboard**, clinician feedback mode, **Glasgow Coma Scale (GCS) scoring**, **SOFA organ-dysfunction scoring with baseline tracking and delta sepsis alerts**, the **Sepsis-3 clinical refactor** (SIRS removed, qSOFA repositioned as screening, SOFA delta ≥ 2 triggers bundles), **frontend GCS entry and SOFA display**, **expanded simulator scenarios with clinical validation**, the **Site & Gateway Registry** with dual authentication, shared clinical sync contracts, and fleet health Prometheus gauges, the **Ward Gateway Service** (local-first clinical path with offline buffering and central sync), the **FHIR R4 Inbound Facade** for EHR integration, **Role-Based Access Control (RBAC) with clinical audit logging**, the **Dashboard Gap Analysis Fixes** (SOFA/GCS/qSOFA history charts, patient banner, encounter timeline, medication markers on vital charts), the **Enhanced Dashboard** (department overview, sepsis bundle board, critical alert notifications, shift handoff reports, vitals entry form, sortable/filterable ward table), **Degraded Operations Visibility** (gateway fleet operations panel, stale gateway auto-detection, discharge summary API, admin panels for user/threshold/audit/reconciliation management, degraded-mode banner), **Alert Quality Analytics** (server-side clinician feedback with `AlertFeedback` entity, `AlertQualityAggregatorService` background metrics, quality metrics API, Grafana alert quality dashboard, **scenario-attributed feedback** for simulated alerts), **Explainable Alerts** (immutable JSONB `explanation` on composite alerts with score contributors, trend context, structured medication context, and bedside `NarrativeSummary`; `AlertResponse` DTO on GET/list/acknowledge/resolve; dashboard `AlertReasoning.vue`; ES indexer and data lake propagation; ward gateway sync), **MIMIC-IV Replay Scenario Generator** (offline CLI tool converting real de-identified ICU data from MIT PhysioNet into VigilCare scenario JSONs; streaming CSV parser for 668K-row chartevents; 17 chart + 8 lab item ID mappings to VigilCare observation codes; GCS text-to-numeric conversion; Fahrenheit-to-Celsius; blood pressure deduplication preferring non-invasive over arterial; 10-observation cluster limit enforcement; `mimic-list` and `mimic-generate` CLI commands with Spectre.Console output; 100 patients / 140 ICU stays available for replay through NEWS2, SOFA, GCS, qSOFA, trend detection, and alerting), and **self-service clinical simulation** (Phases 36–38: default-off in-app runner, Simulation control UI, session presets A–D, ward purge/reset, and a rewritten clinical testing guide so clinicians complete sessions with no terminal). Post-phase hardening includes health check endpoints, Kafka poison pill protection, outbox dead-letter with retry tracking, data lake partial-commit safety, MRN sequence-based generation, FHIR bundle transaction rollback, **FHIR R4 read/search endpoints** (Patient and Encounter), **alert threshold deletion with audit trail**, **FHIR API key rotation** (constant-time multi-key validation), **authorization failure logging** with Prometheus metrics, **JWT signing key validation** at startup, **token refresh and revocation** (short-lived access tokens with rotating refresh tokens, server-side logout, proactive frontend refresh), and **concurrency hardening** (transactional sepsis bundle creation, unique active encounter constraint). See [Implemented Phases](#implemented-phases) for the full breakdown. Guides: [dashboard-guide.md](docs/dashboard-guide.md) (technical), [clinical-testing-guide.md](docs/clinical-testing-guide.md) (doctors & nurses — self-service Simulation sessions), [simulator-guide.md](docs/simulator-guide.md) (CLI / CI), [vigilcare-clinical-roadmap.md](docs/plans/vigilcare-clinical-roadmap.md) (Phases 36–38 order).
|
||||
|
||||
## Domain Model — How It Maps to a Real Clinical System
|
||||
|
||||
@@ -72,7 +72,7 @@ An `OutboxEvent` is written in the same transaction as any observation or alert,
|
||||
- **Medication Administration** — `POST /encounters/:id/medications` records drug administrations (name, dose, route, timestamp, administered-by); `GET /encounters/:id/medications` lists with optional `since` filter; `GET /medications/:id` detail; active-encounter guard; FluentValidation on request DTOs
|
||||
- **Medication Correlation Annotations** — `MedicationCorrelationHelper` appends medication context to warning alert `details` when a mapped drug was administered within the correlation window (default 90 min); explainable alerts (NEWS2, SOFA, GCS, rapid deterioration) receive structured `MedicationContext` in the JSONB `explanation` via `TryGetContextAsync()`; drug-to-vital mappings in `MedicationCorrelation` config (`appsettings.json`); annotates rather than suppresses — alerts still fire; sepsis, trend, and critical sync-path alerts are never annotated; design rationale in `docs/decisions/medication-correlation-design.md`
|
||||
- **Ward Dashboard APIs** — `GET /encounters` returns paginated `WardEncounterSummary` rows (patient name/MRN, room/bed, department, status, latest NEWS2 score, live qSOFA criteria count from Redis, sepsis bundle status, open alert count, SOFA score/delta, GCS score/classification, attending physician, admitted-at, last observation time); filterable by `status` and `department`; `GET /encounters/:id/qsofa/current` exposes Redis-backed qSOFA state; `GET /sepsis-bundles` lists bundles hospital-wide with optional `status` filter (returns `SepsisBundleSummary` with patient demographics, elements, and deadlines); CORS policy `Dashboard` allows configured origins (default `http://localhost:5173`)
|
||||
- **Ward Dashboard Frontend** — Vue 3 SPA (`vigilcare-dashboard/`) with virtual ward table (multi-column sortable, patient search, quick-filters for critical/alerts/sepsis), patient detail (vitals, scores, alerts, orders, sepsis bundle, GCS entry form, SOFA score panel, patient banner with demographics/allergies/emergency contact, encounter timeline, vitals entry form for manual observation recording, discharge summary panel), alert center (global acknowledge/resolve with role-aware modal and acknowledgment note preview), department overview (unit-level snapshot cards with acuity bars, patient/alert/bundle counts per department), sepsis bundle board (real-time countdown timers, on-track/at-risk/overdue urgency sorting), critical alert banner with browser notifications and audible tone, shift handoff report generator (SBAR format with ward summary, exportable via print/PDF), vital sign trend charts with medication administration markers and local replay scrubbing, NEWS2 history chart, SOFA history chart with organ-system breakdown, GCS history chart with component tracking, qSOFA evaluation history, structured alert reasoning (`AlertReasoning.vue` — score contributors, trend context, medication context, narrative summary from `explanation`), clinician feedback on every alert, admin panels (threshold management, user management, audit log viewer, reconciliation viewer), gateway operations dashboard with degraded-mode banner, and alert quality analytics with quality charts; role-aware sidebar navigation; polls API every 5–10 s; guides in `docs/dashboard-guide.md` and `docs/clinical-testing-guide.md`
|
||||
- **Ward Dashboard Frontend** — Vue 3 SPA (`vigilcare-dashboard/`) with virtual ward table (multi-column sortable, patient search, quick-filters for critical/alerts/sepsis, **SIM badge** on simulated patients), patient detail (vitals, scores, alerts, orders, sepsis bundle, GCS entry form, SOFA score panel, patient banner with demographics/allergies/emergency contact, encounter timeline, vitals entry form for manual observation recording, discharge summary panel), alert center (global acknowledge/resolve with role-aware modal and acknowledgment note preview), department overview (unit-level snapshot cards with acuity bars, patient/alert/bundle counts per department), sepsis bundle board (real-time countdown timers, on-track/at-risk/overdue urgency sorting), critical alert banner with browser notifications and audible tone, shift handoff report generator (SBAR format with ward summary, exportable via print/PDF), vital sign trend charts with medication administration markers and local replay scrubbing, NEWS2 history chart, SOFA history chart with organ-system breakdown, GCS history chart with component tracking, qSOFA evaluation history, structured alert reasoning (`AlertReasoning.vue` — score contributors, trend context, medication context, narrative summary from `explanation`), clinician feedback on every alert, **Simulation control** (`SimulationControlView` — Sessions / Scenarios tabs, speed control, run progress, typed ward reset), admin panels (threshold management, user management, audit log viewer, reconciliation viewer), gateway operations dashboard with degraded-mode banner, and alert quality analytics with quality charts **and by-scenario breakdown**; role-aware sidebar navigation; polls API every 5–10 s; guides in `docs/dashboard-guide.md` and `docs/clinical-testing-guide.md`
|
||||
- **FHIR R4 Inbound Facade** — `POST /fhir/R4/{Patient,Encounter,Observation,MedicationAdministration}` accepts FHIR R4 JSON resources (`application/fhir+json`); `POST /fhir/R4` processes transaction Bundles (Patient → Encounter → Observation in dependency order); `GET /fhir/R4/metadata` returns a CapabilityStatement; LOINC-to-internal code mapping (19 observation codes + SNOMED CT fallbacks); Fahrenheit-to-Celsius unit conversion; `ExternalResourceIdentifier` table links hospital MRNs and visit numbers to internal UUIDs for idempotent upserts; `FhirApiKeyOrJwtMiddleware` authenticates via JWT bearer or `X-Api-Key` header (supports multiple keys via `Fhir:ApiKeys` array for zero-downtime rotation; constant-time comparison via `CryptographicOperations.FixedTimeEquals`); `FhirExceptionFilter` returns FHIR `OperationOutcome` on errors; configurable identifier systems, department codes, and encounter class mappings via `Fhir` config section; Prometheus `fhir_ingest_total` and `fhir_mapping_errors_total`; integration guide for Mirth Connect HL7v2→FHIR channels in `docs/integration/mirth-fhir-channels.md`
|
||||
- **FHIR R4 Read/Search** — `GET /fhir/R4/Patient/{id}` reads a Patient by internal ID; `GET /fhir/R4/Patient` searches by `identifier` (system|value) or lists all patients; `GET /fhir/R4/Encounter/{id}` reads an Encounter by internal ID; `GET /fhir/R4/Encounter` searches by `patient` (UUID) and/or `status` (`in-progress`, `finished`, `cancelled`); all return FHIR R4 JSON (`application/fhir+json`); search endpoints return `Bundle.type=searchset`; requires `fhir:read` permission (Admin and Integration roles); internal resources mapped back to FHIR via `PatientFhirMapper.ToFhirResponse` / `EncounterFhirMapper.ToFhirResponse` with hospital identifier resolution; Prometheus `fhir_read_total` counter with `resource_type`, `interaction`, `outcome` labels
|
||||
- **Role-Based Access Control (RBAC)** — JWT bearer authentication (`POST /auth/login`); four clinical roles (`Nurse`, `Physician`, `Admin`, `Integration`) with 18 granular permissions (`patients:read`, `alerts:acknowledge`, `alerts:feedback`, `thresholds:write`, `fhir:ingest`, `fhir:read`, `audit:read`, etc.); `AuthorizePermission` attribute on every controller action; `PermissionAuthorizationHandler` resolves role → permission at runtime from `ClinicalRolePermissionMap` and logs authorization failures with structured details (user, role, permission, endpoint) plus `authorization_failures_total` Prometheus counter; `CurrentUserService` exposes authenticated identity (user ID, display name, role, IP address) to services; nurses and physicians get clinical read/write permissions; admins additionally get `thresholds:write`, `fhir:read`, `audit:read`, and `users:admin`; integration accounts get FHIR ingest and read access; FHIR endpoints accept both JWT and `X-Api-Key` authentication via `FhirApiKeyOrJwtMiddleware`; alert `acknowledgedBy` is set from the authenticated user identity, not the request body; startup validates JWT signing key is at least 256 bits (HMAC-SHA256 minimum); **token refresh and revocation** — short-lived access tokens (15 min) paired with rotating opaque refresh tokens (7 days) stored in the `refresh_tokens` table; `POST /auth/refresh` exchanges a valid refresh token for a new access + refresh token pair (rotation on every use revokes the previous token); `POST /auth/logout` revokes the refresh token server-side with `USER_LOGOUT` audit log; frontend auto-refreshes 1 minute before expiry, retries on 401, and redirects to login when the refresh token is exhausted; logout button in header, sidebar, and mobile nav; four seeded demo users (`nurse.demo`, `physician.demo`, `admin.demo`, `integration.mirth`)
|
||||
@@ -87,12 +87,13 @@ An `OutboxEvent` is written in the same transaction as any observation or alert,
|
||||
- **MRN Sequence Generation** — MRN numbers are generated via a PostgreSQL sequence (`mrn_seq`) instead of MAX+1 queries; eliminates race conditions under concurrent patient registration; configurable prefix and digit count via `PatientOptions`
|
||||
- **FHIR Bundle Transaction Rollback** — `FhirBundleProcessor` wraps all bundle entry processing in a database transaction; on any entry failure, the transaction is rolled back and the response includes the `OperationOutcome` for the failed entry; prevents partial state from orphaned Patient/Encounter records
|
||||
- **Clinician Feedback Mode** — six quick ratings per alert (useful, too early, too late, false positive, missing context, would act); optional notes; server-side `AlertFeedback` entity persisted per user per alert (`POST /alerts/{id}/feedback`); `alerts:feedback` permission for Nurse, Physician, and Admin roles; Feedback Summary with aggregate stats and JSON/CSV export; client-side persistence for product research
|
||||
- **Alert Quality Analytics** — `AlertQualityAggregatorService` periodically computes per-alert-type quality metrics (acknowledgement rate, false positive rate, useful rate, would-act rate, avg seconds to acknowledge/resolve) into `alert_quality_metrics` table; `AlertQualityMetricsController` exposes `GET /alerts/quality-metrics` (time-range filterable, optional alert type) and `GET /alerts/quality-metrics/summary`; Grafana alert quality dashboard (`infra/grafana/dashboards/alert-quality-dashboard.json`); frontend `AlertQualityAnalytics.vue` with `AlertQualityChart.vue`; Prometheus `alert_quality_useful_rate` and `alert_quality_false_positive_rate` gauges
|
||||
- **Alert Quality Analytics** — `AlertQualityAggregatorService` periodically computes per-alert-type quality metrics (acknowledgement rate, false positive rate, useful rate, would-act rate, avg seconds to acknowledge/resolve) into `alert_quality_metrics` table; `AlertQualityMetricsController` exposes `GET /alerts/quality-metrics` (time-range filterable, optional alert type), `GET /alerts/quality-metrics/summary`, and `GET /alerts/quality-metrics/feedback` (per-alert feedback rows with optional `?scenarioId=` filter and `scenarioId`/`sessionId` attribution when simulation is enabled); Grafana alert quality dashboard (`infra/grafana/dashboards/alert-quality-dashboard.json`); frontend `AlertQualityAnalytics.vue` with `AlertQualityChart.vue`, scenario filter, by-scenario breakdown, and CSV export including attribution columns; Prometheus `alert_quality_useful_rate` and `alert_quality_false_positive_rate` gauges
|
||||
- **Explainable Alerts** — `AlertExplanation` value object (`ScoreContributor`, `TrendContext`, `MedicationContext`, `NarrativeSummary`) serialized as JSONB on `ClinicalAlert.Explanation` at creation time; `AlertExplanationBuilder` and contributor builders (NEWS2, SOFA, GCS, trend) assemble explanation from scoring outputs; `ClinicalAlertFactory` idempotent INSERT with explanation; NEWS2, SOFA, GCS, and `TrendDetector` wire explanation and include `explanation` in `alert.generated` outbox payloads; `AlertResponse` DTO exposes optional `Explanation` on GET/list/acknowledge/resolve; Elasticsearch indexes `NarrativeSummary`; data lake Parquet includes `explanation_json`; ward gateway `LocalClinicalAlert.ExplanationJson` synced via `ClinicalSyncBatchProcessor`; dashboard `AlertReasoning.vue` + `alertExplanation.js` composable render structured reasoning; simulator `ExpectedOutcomeValidator` supports `narrativeContains` on key scenarios; `ExplainableAlertsTests` (10 tests) + `run-phase34-verification.sh`
|
||||
- **Degraded Operations Visibility** — `GatewayStaleDetectorService` auto-marks gateways OFFLINE when heartbeat exceeds configurable `StaleThresholdMinutes`; `OperationsController` (`GET /operations/gateways`, `GET /operations/gateways/{id}`, `GET /operations/sites/{siteId}/summary`) provides fleet management API; `DischargeSummaryService` with `GET /encounters/{id}/discharge-summary` (info) and `GET /encounters/{id}/discharge-summary/content` (MinIO PDF download); `DischargeSummaryPanel.vue` on patient detail; `DegradedModeBanner.vue` warns when gateways are offline; `GatewayOperations.vue` operations dashboard
|
||||
- **User Management** — `UsersController` (`GET /users`, `POST /users`, `PATCH /users/{id}`) for admin user account CRUD; `UserService` with BCrypt password hashing; `UserManagementView.vue` with `UserFormModal.vue` (create/edit users, role assignment, active toggle)
|
||||
- **Admin Dashboard Panels** — `ThresholdManagementView.vue` with `ThresholdFormModal.vue` (create/edit alert thresholds); `AuditLogView.vue` (filterable audit log viewer with action/entity/user/date filters); `ReconciliationView.vue` (safety finding viewer); sidebar navigation with role-aware admin section; `CollapsibleSection.vue` and `SeverityBadge.vue` UI components
|
||||
- **Console Replay Simulator** — standalone `VigilCare.Simulator` .NET console app replays JSON scenario files against the live API with configurable speed (`--speed 0` instant, `60` = 60× faster); commands: `replay`, `replay-all`, `validate`, `dry-run`, `mimic-list`, `mimic-generate`; optional `--poll` shows alerts, NEWS2, GCS, SOFA, and sepsis bundle state during replay; `--gateway` targets the ward gateway (`http://localhost:5081`) with `--encounter-id`, `--skip-setup`, and `--gateway-token`; `alert_ack` events poll for open alerts on central before acknowledging (handles async alert pipeline at `--speed 0`); `ExpectedOutcomeValidator` validates alert `narrativeContains` on key scenarios; twelve sample scenarios in `VigilCare.Simulator/Scenarios/List/` (including ward outage reconnect, GCS neurological decline, SOFA sepsis progression, and SpO₂/FiO₂ fallback); MIMIC-IV scenario generation from real ICU data; user guide in `docs/simulator-guide.md`
|
||||
- **In-App Clinical Simulation (Phases 36–38)** — default-off `Simulation:Enabled` gate; `ScenarioCatalog` / `SessionCatalog` load scenario JSON and `sessions.json` presets; `SimulationRunner` hosted service replays via loopback API client; patients marked `IsSimulated`; `simulation_runs` with optional `SessionId`; REST under `/api/v1/simulation` (config, scenarios, sessions start, runs, data summary, purge); dashboard **Simulation** page (Sessions default tab, Scenarios catalogue, speed control, run panel, typed **Reset ward**); all-or-nothing multi-run session start with staggered launch; purge deletes only simulated patients and dependents and audits `SIMULATION_DATA_PURGED`; clinicians follow `docs/clinical-testing-guide.md` with no terminal
|
||||
- **Console Replay Simulator** — standalone `VigilCare.Simulator` .NET console app (developer/CI tool — clinicians use the in-app Simulation page) replays JSON scenario files against the live API with configurable speed (`--speed 0` instant, `60` = 60× faster); commands: `replay`, `replay-all`, `validate`, `dry-run`, `mimic-list`, `mimic-generate`; optional `--poll` shows alerts, NEWS2, GCS, SOFA, and sepsis bundle state during replay; `--gateway` targets the ward gateway (`http://localhost:5081`) with `--encounter-id`, `--skip-setup`, and `--gateway-token`; `alert_ack` events poll for open alerts on central before acknowledging (handles async alert pipeline at `--speed 0`); `ExpectedOutcomeValidator` validates alert `narrativeContains` on key scenarios; twelve sample scenarios in `VigilCare.Simulator/Scenarios/List/` (including ward outage reconnect, GCS neurological decline, SOFA sepsis progression, and SpO₂/FiO₂ fallback); session presets in `VigilCare.Simulator/Scenarios/sessions.json`; MIMIC-IV scenario generation from real ICU data; user guide in `docs/simulator-guide.md`
|
||||
- **MIMIC-IV Scenario Generator** — offline CLI tool that reads MIMIC-IV CSV files (`docs/MIMIC-IV/`, 100 patients, 140 ICU stays, 668K chart events, 107K lab events) and generates VigilCare scenario JSONs; `mimic-list <dir>` displays a Spectre.Console table of available stays with demographics, care unit, LOS, and outcome; `mimic-generate <dir> --stay-id <id>` produces a scenario with options for `--max-hours`, `--no-medications`, `--no-labs`, `--validate`; streaming CSV parser (`MimicCsvReader`) filters 668K-row chartevents by stay_id and item ID set at the string level before allocating records; `MimicItemMap` maps 17 chart event items (vitals, GCS, FiO₂, PaO₂, labs) and 8 lab event items to VigilCare observation codes; GCS text labels ("Obeys Commands" → 6, "To Speech" → 3) resolved from `valuenum` with text-to-numeric fallback dictionary; Fahrenheit temperature converted to Celsius; blood pressure deduplication prefers non-invasive (NBP) over arterial (ABP); 10-observation-per-cluster limit enforced by priority-based splitting (vitals first, labs spill to next offset); medications from prescriptions with dose parsing; generated scenarios pass `ScenarioValidator` and replay through the standard `replay` command
|
||||
- **RabbitMQ Notification Workers** — `NotificationPublisherService` reads `alert.generated` from Kafka and publishes paging jobs to `alerts.paging.queue`; `PagingWorkerService` sends the page and waits for acknowledgment; if no ack arrives before timeout it NACKs to `alerts.paging.dlq` with `x-message-ttl = 300000ms`; if the host is stopping, in-flight paging messages are NACKed with `requeue=true` so they are retried after restart and do not false-escalate; `EscalationWorkerService` pages the on-call backup and sets alert status to `escalated`; `DischargeSummaryWorkerService` reads `encounter.status.changed`, generates a discharge summary, and stores it in MinIO under `/discharge-summaries/{encounterId}/summary.pdf`
|
||||
- **Data Lake Writer** — `DataLakeWriterService` (consumer group `data-lake-writer`) buffers `observation.recorded`, `alert.generated`, and `encounter.status.changed` events, flushes date-partitioned Parquet files to MinIO (`/observations/`, `/alerts/`, `/encounters/`), and commits Kafka offsets only for topic-partitions where all uploads succeeded; failed partition buffers are retained in memory and retried on the next flush cycle (prevents data loss from partial upload failures); shutdown flush uses an uncanceled token so MinIO writes complete on Ctrl+C; `kafka_partition` and `kafka_offset` columns provide audit lineage
|
||||
@@ -149,6 +150,7 @@ IHostedServices (background):
|
||||
WardGatewayMetricsCollector → polls gateway status/buffer depth every 60s → ward_gateways_offline_gauge, ward_gateway_buffer_depth
|
||||
GatewayStaleDetectorService → polls gateways on interval → marks OFFLINE when heartbeat exceeds StaleThresholdMinutes
|
||||
AlertQualityAggregatorService → periodically computes per-alert-type quality metrics → alert_quality_metrics table + Prometheus gauges
|
||||
SimulationRunner (when Simulation:Enabled) → in-app scenario/session replay via loopback API; marks patients IsSimulated
|
||||
ClinicalMetrics (singleton) → inline counters/histogram from ingest, qSOFA, NEWS2, GCS, SOFA, trend, suppression, bundle compliance, escalation paths, alert quality
|
||||
|
||||
Ward Gateway (VigilCare.WardGateway — separate deployable on port 5081):
|
||||
@@ -610,7 +612,7 @@ vigilcare-dashboard/ # Phases 17–19, 22, 23, 27
|
||||
│ ├── composables/ # useChartData, useReplayControls, usePolling, useFeedback, useGcs, useSofa, useApiMode, useChartTheme, useFocusTrap, chartFormat, patientFormat, timelineFormat, chartMedications, wardSort, wardFilter, departmentFormat, sepsisFormat, alertAcknowledge, alertExplanation, criticalAlertDetect, useAlertNotification, useCriticalAlertPolling, handoffReport, vitalsForm, roleAccess, auditFormat, reconciliationFormat, thresholdForm, userForm
|
||||
│ ├── plugins/ # medicationMarkerPlugin (Chart.js plugin for medication administration markers on vital charts)
|
||||
│ ├── stores/ # Pinia — ward (sort + filter + search), alerts (banner + polling), settings (sort prefs + sound mute), feedback, scoring, auth (login + refresh token rotation + logout + expiry redirect), departments, sepsis, operationsStore, alertQuality
|
||||
│ ├── views/ # LoginView, WardDashboard, PatientDetail, AlertCenter, FeedbackSummary, DepartmentOverviewView, SepsisBoardView, ThresholdManagementView, UserManagementView, AuditLogView, ReconciliationView, GatewayOperations, AlertQualityAnalytics
|
||||
│ ├── views/ # LoginView, WardDashboard, PatientDetail, AlertCenter, FeedbackSummary, DepartmentOverviewView, SepsisBoardView, SimulationControlView, ThresholdManagementView, UserManagementView, AuditLogView, ReconciliationView, GatewayOperations, AlertQualityAnalytics
|
||||
│ └── __tests__/ # Vitest — tests (store, feedback, replay, charts, alerts, ward, GCS, SOFA, qSOFA, PatientBanner, EncounterTimeline, patientFormat, timelineFormat, chartMedications, wardSort, wardFilter, departmentFormat, sepsisFormat, alertAcknowledge, criticalAlertDetect, HandoffReport, handoffReport, VitalsEntryForm, vitalsForm, useAlertStore, useWardStore, DepartmentOverviewView, SepsisBoardView, AcknowledgeModal, CriticalAlertBanner, roleAccess, ThresholdManagementView, thresholdForm, DischargeSummaryPanel, GatewayOperations, alertQuality)
|
||||
├── vite.config.js
|
||||
└── README.md # Dev quick start → docs/dashboard-guide.md
|
||||
@@ -649,11 +651,13 @@ scripts/
|
||||
|
||||
docs/
|
||||
├── plans/ # Phase implementation and verification guides
|
||||
├── clinical-testing-guide.md # Doctor/nurse guide — alert review & feedback sessions
|
||||
│ ├── vigilcare-clinical-roadmap.md # Phases 36–38 implementation order
|
||||
│ └── phase-*-plan.md # Per-phase plans (incl. phase-36/37/38 simulation)
|
||||
├── clinical-testing-guide.md # Doctor/nurse guide — self-service Simulation sessions A–D
|
||||
├── dashboard-guide.md # VigilCare Dashboard user guide (ward, patient detail, charts)
|
||||
├── dashboard-gap-analysis.md # Comprehensive gap analysis — P0–P5 clinical usefulness assessment
|
||||
├── patient-encounter-api-lifecycle.md # Full API walkthrough: registration → active stay → discharge
|
||||
├── simulator-guide.md # VigilCare.Simulator user guide
|
||||
├── simulator-guide.md # VigilCare.Simulator CLI / CI user guide (clinicians use dashboard Simulation)
|
||||
├── integration/
|
||||
│ └── mirth-fhir-channels.md # Mirth Connect HL7v2→FHIR channel mapping (ADT A01/A03/A08, ORU R01)
|
||||
├── decisions/
|
||||
@@ -806,6 +810,12 @@ Without this, Prometheus may show target errors like:
|
||||
For full Docker troubleshooting and recovery steps, see:
|
||||
- `docs/docker-compose-usage-and-troubleshooting.md`
|
||||
|
||||
### Simulation mode (default off)
|
||||
|
||||
In-app scenario replay for clinical testing is controlled by the `Simulation` section in `appsettings.json` (or environment variables). **`Simulation:Enabled` defaults to `false`.** When enabled, the API registers session/scenario/purge endpoints and a loopback runner; clinicians use the dashboard **Simulation** page (session presets A–D, individual scenarios, speed control, ward reset — see `docs/clinical-testing-guide.md`). Never enable simulation against a database with real patient data — purge and replay only touch rows marked `IsSimulated`, but the feature is intended for evaluation environments only.
|
||||
|
||||
Key settings: `Simulation:ScenarioDirectory` (flat folder of scenario JSON; `sessions.json` may sit in that directory or its parent), `Simulation:MaxConcurrentRuns` (default 8 — enough for Session C’s seven concurrent patients), `Simulation:LoopbackBaseUrl`, and the `simulation.runner` service account password.
|
||||
|
||||
### Install and Run
|
||||
|
||||
```bash
|
||||
@@ -829,9 +839,11 @@ Health checks (anonymous, no JWT required):
|
||||
- `GET /health/live` — liveness probe (always 200 if process is running)
|
||||
- `GET /health/ready` — readiness probe (checks PostgreSQL, Redis, Kafka, RabbitMQ, Elasticsearch)
|
||||
|
||||
### Run the Simulator
|
||||
### Run the Simulator (CLI / CI)
|
||||
|
||||
With the API running, replay a scenario from the repository root:
|
||||
> **Clinicians:** prefer the dashboard **Simulation** page (Sessions / Scenarios / Reset ward). The CLI is for developers, CI, `validate` / `dry-run` / `replay-all` / `mimic-generate`, and `scripts/run-phase*-verification.sh`. See `docs/simulator-guide.md` §12.
|
||||
|
||||
With the API running and (for in-app use) `Simulation:Enabled=true`, replay a scenario from the repository root via CLI:
|
||||
|
||||
```bash
|
||||
dotnet run --project VigilCare.Simulator -- replay \
|
||||
@@ -874,9 +886,11 @@ npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Open `http://localhost:5173` — log in with a demo account (e.g. `nurse.demo` / `DemoNurse1!`). **Virtual Ward** lists active patients sorted by NEWS2 score. Click a row for patient detail (vitals, alerts, charts, replay scrubbing, alert reasoning). Use **Alert Center** for hospital-wide triage. After reviewing alerts, rate them with the six feedback buttons and export results from **Feedback Summary** (`/feedback`).
|
||||
Open `http://localhost:5173` — log in with a demo account (e.g. `nurse.demo` / `DemoNurse1!`). **Virtual Ward** lists active patients sorted by NEWS2 score. Click a row for patient detail (vitals, alerts, charts, replay scrubbing, alert reasoning). Use **Alert Center** for hospital-wide triage. After reviewing alerts, rate them with the six feedback buttons and export results from **Feedback Summary** or **Alert Quality**.
|
||||
|
||||
Replay a simulator scenario in another terminal to watch charts and alerts populate in real time. Run dashboard tests with `cd vigilcare-dashboard && npm test`. See `docs/dashboard-guide.md` for technical documentation and `docs/clinical-testing-guide.md` for structured clinician evaluation sessions.
|
||||
With `Simulation:Enabled=true`, open **Simulation** in the sidebar: start a **Sessions** preset (A–D) or an individual scenario, watch runs on the progress panel, then **Reset ward** (type `RESET`) between testers. See `docs/clinical-testing-guide.md`.
|
||||
|
||||
Run dashboard tests with `cd vigilcare-dashboard && npm test`. See `docs/dashboard-guide.md` for technical documentation.
|
||||
|
||||
### Run Tests
|
||||
|
||||
@@ -1603,6 +1617,24 @@ Each audit log entry includes `action`, `entityType`, `entityId`, `userId`, `use
|
||||
|---|---|---|
|
||||
| GET | `/alerts/quality-metrics` | Per-alert-type quality metric snapshots; optional `alertType`, `from`, `to` filters |
|
||||
| GET | `/alerts/quality-metrics/summary` | Aggregate alert quality rates across all alert types; optional `from`, `to` |
|
||||
| GET | `/alerts/quality-metrics/feedback` | Per-alert feedback rows; optional `scenarioId`, `from`, `to`; includes `scenarioId`/`sessionId` when `Simulation:Enabled` |
|
||||
|
||||
### Simulation (requires `Simulation:Enabled=true`)
|
||||
|
||||
| Method | Path | Description |
|
||||
|---|---|---|
|
||||
| GET | `/simulation/config` | Feature probe — `{ enabled }` (always 200; `enabled=false` when off) |
|
||||
| GET | `/simulation/scenarios` | Scenario catalogue |
|
||||
| GET | `/simulation/sessions` | Session presets with resolved scenario summaries |
|
||||
| POST | `/simulation/sessions/{sessionId}/start` | Start all scenarios in a preset (optional `{ speed }`); all-or-nothing capacity check |
|
||||
| POST | `/simulation/runs` | Start a single scenario run |
|
||||
| GET | `/simulation/runs` | Active and recent runs |
|
||||
| GET | `/simulation/runs/{runId}` | One run |
|
||||
| POST | `/simulation/runs/{runId}/stop` | Cancel a run |
|
||||
| GET | `/simulation/data/summary` | Simulated patient / observation / alert counts |
|
||||
| DELETE | `/simulation/data` | Purge simulated patients and dependents (409 if runs active) |
|
||||
|
||||
Requires `simulation:run` (except `GET /simulation/config`, which needs `alerts:read`). Endpoints return 404 when simulation is disabled.
|
||||
|
||||
### Alert Feedback
|
||||
|
||||
@@ -2292,7 +2324,7 @@ Observation history uses cursor pagination on `(recorded_at DESC, id DESC)`. Off
|
||||
|
||||
## Implemented Phases
|
||||
|
||||
Thirty-three phases from the project roadmap are implemented and verified, including the **Site & Gateway Registry** (Phase 20), the **Ward Gateway Service** (Phase 21), the **Dashboard Gap Analysis Fixes** (Phase 22), the **Degraded Operations Visibility** (Phase 23), the **Sepsis-3 clinical refactor** (Phases 27–29), the **FHIR R4 Inbound Facade** (Phase 30), **RBAC with clinical audit logging** (Phase 31), the **Alert Quality Analytics** (Phase 33), the **Explainable Alerts** (Phase 34), the **MIMIC-IV Replay Scenario Generator** (Phase 35), and the **Enhanced Dashboard** (department overview, sepsis bundle board, critical alert notifications, shift handoff reports, vitals entry, sortable/filterable ward table). Integration tests (`dotnet test`) and per-phase verification scripts cover Phases 8–15, 20–23, 25–31, 33–35. Phases 17–19 add the Vue dashboard and clinician feedback (Vitest in `vigilcare-dashboard/`).
|
||||
Phases **1–38** from the project roadmap are implemented and verified, including the **Site & Gateway Registry** (Phase 20), the **Ward Gateway Service** (Phase 21), the **Dashboard Gap Analysis Fixes** (Phase 22), the **Degraded Operations Visibility** (Phase 23), the **Sepsis-3 clinical refactor** (Phases 27–29), the **FHIR R4 Inbound Facade** (Phase 30), **RBAC with clinical audit logging** (Phase 31), the **Alert Quality Analytics** (Phase 33), the **Explainable Alerts** (Phase 34), the **MIMIC-IV Replay Scenario Generator** (Phase 35), the **Enhanced Dashboard** (department overview, sepsis bundle board, critical alert notifications, shift handoff reports, vitals entry, sortable/filterable ward table), and **self-service clinical simulation** (Phases 36–38 — in-app runner, Simulation UI, session presets, ward purge, scenario-attributed feedback). Integration tests (`dotnet test`) and per-phase verification scripts cover Phases 8–15, 20–23, 25–31, 33–38. Phases 17–19 add the Vue dashboard and clinician feedback (Vitest in `vigilcare-dashboard/`). See also `docs/plans/vigilcare-clinical-roadmap.md`.
|
||||
|
||||
| Phase | Feature | Status |
|
||||
|---|---|---|
|
||||
@@ -2329,8 +2361,11 @@ Thirty-three phases from the project roadmap are implemented and verified, inclu
|
||||
| 33 | **Alert Quality Analytics** — `AlertFeedback` entity with per-user-per-alert constraint; `POST /alerts/{id}/feedback` server-side feedback submission with `alerts:feedback` permission (Nurse, Physician, Admin); `AlertQualityMetric` entity stores per-alert-type quality snapshots (acknowledgement rate, false positive rate, useful rate, would-act rate, avg seconds to acknowledge/resolve); `AlertQualityAggregatorService` background service computes metrics periodically; `AlertQualityMetricsController` exposes `GET /alerts/quality-metrics` (time-range + alert type filter) and `GET /alerts/quality-metrics/summary`; `AlertFeedbackConfiguration` and `AlertQualityMetricConfiguration` EF Core configs; `SubmitAlertFeedbackRequestValidator`; Prometheus `alert_quality_useful_rate` and `alert_quality_false_positive_rate` gauges; Grafana `alert-quality-dashboard.json`; frontend `AlertQualityAnalytics.vue` with `AlertQualityChart.vue` and `alertQuality` Pinia store; `AlertQualityAnalyticsTests`; `run-phase33-verification.sh` | Done |
|
||||
| 34 | **Explainable Alerts** — `AlertExplanation` value object (`ScoreContributor`, `TrendContext`, `MedicationContext`, `NarrativeSummary`); JSONB `ClinicalAlert.Explanation` column (immutable at creation); contributor builders for NEWS2, SOFA, GCS; `TrendContextBuilder`; `AlertExplanationBuilder` + `ClinicalAlertFactory`; NEWS2, SOFA, GCS, and `TrendDetector` wire explanation and include `explanation` in `alert.generated` outbox; `MedicationCorrelationHelper.TryGetContextAsync()` for structured medication context; `AlertResponse` DTO + `AlertResponseMapper`; GET/list/acknowledge/resolve return `AlertResponse`; ES indexer projects `NarrativeSummary`; data lake Parquet `explanation_json`; ward gateway `LocalClinicalAlert.ExplanationJson` + sync; dashboard `AlertReasoning.vue` + `alertExplanation.js`; simulator `ExpectedOutcomeValidator` with `narrativeContains`; `ExplainableAlertsTests`; `run-phase34-verification.sh` | Done |
|
||||
| 35 | **MIMIC-IV Replay Scenario Generator** — offline CLI tool in `VigilCare.Simulator/Mimic/` that reads MIMIC-IV CSV files (100 patients, 140 ICU stays, 668K chart events, 107K lab events from `docs/MIMIC-IV/`) and generates standard VigilCare scenario JSONs; `MimicCsvReader` streaming CSV parser with header-index lookup and filter predicate (memory-efficient for large files); `MimicItemMap` maps 17 chart event items (vitals, GCS, FiO₂, PaO₂, labs) and 8 lab event items to VigilCare observation codes with GCS text-to-numeric fallback dictionary, Fahrenheit-to-Celsius conversion, and blood pressure priority (non-invasive preferred over arterial); `MimicCareUnitMap` maps care units to departments and generates tags; `MimicDataLoader` streams chartevents/labevents/prescriptions filtered by stay_id + item ID set; `MimicScenarioBuilder` deduplicates BP, enforces 10-observation-per-cluster limit with priority-based splitting, computes offsetMinutes, parses medication doses; `MimicListCommand` (`mimic-list`) displays Spectre.Console table of available stays; `MimicGenerateCommand` (`mimic-generate`) produces scenario JSON with `--max-hours`, `--no-medications`, `--no-labs`, `--validate` options; generated scenarios pass `ScenarioValidator` and replay through the standard `replay` command | Done |
|
||||
| 36 | **In-app simulation runner** — `Simulation:Enabled` gate; `ScenarioCatalog` + `SimulationRunner` hosted service; loopback API client; `IsSimulated` patient flag + filtered index; `simulation_runs` table; `GET/POST /api/v1/simulation/*` (config, scenarios, runs); `simulation:run` permission | Done |
|
||||
| 37 | **Simulation control UI** — dashboard Simulation page with scenario catalogue, speed control, run progress panel, SIM badge / simulation mode banner | Done |
|
||||
| 38 | **Self-service clinical testing sessions** — `sessions.json` presets; multi-run session start (all-or-nothing, staggered); simulated-data purge + typed reset UI; scenario attribution on alert-quality feedback/CSV; clinical testing guide rewritten for self-service | Done |
|
||||
|
||||
**Ward dashboard:** backend APIs (`GET /encounters` ward list with extended summary fields including SOFA/GCS/attending/admitted-at, `GET /qsofa/current`, `GET /qsofa/history`, `GET /gcs/history`, `GET /sepsis-bundles` hospital-wide list, `GET /operations/gateways` fleet management, `GET /users` user management, `GET /alerts/quality-metrics` alert quality, `GET /alerts/{id}` with structured explanation, CORS) and frontend SPA — `EncountersListTests`, `QsofaCurrentTests`, `GapAnalysisFixTests`, `OperationsApiTests`, `AlertQualityAnalyticsTests`, `ExplainableAlertsTests`, `vigilcare-dashboard` Vitest suite (replay scrubbing, feedback store, FeedbackButtons, FeedbackSummary, alert components, AlertReasoning, charts, ward table, ward sort, ward filter, department format, sepsis format, alert acknowledge, critical alert detect, handoff report, vitals form, GCS entry/history, SOFA panel/history, qSOFA history, scores panel, alert labels, PatientBanner, EncounterTimeline, medication chart markers, AcknowledgeModal, CriticalAlertBanner, DepartmentOverviewView, SepsisBoardView, VitalsEntryForm, useAlertStore, useWardStore, roleAccess, ThresholdManagementView, DischargeSummaryPanel, GatewayOperations, alertQuality).
|
||||
**Ward dashboard:** backend APIs (`GET /encounters` ward list with extended summary fields including SOFA/GCS/attending/admitted-at/`isSimulated`, `GET /qsofa/current`, `GET /qsofa/history`, `GET /gcs/history`, `GET /sepsis-bundles` hospital-wide list, `GET /operations/gateways` fleet management, `GET /users` user management, `GET /alerts/quality-metrics` alert quality (+ `/feedback` with scenario attribution), `GET /alerts/{id}` with structured explanation, `/api/v1/simulation/*` when enabled, CORS) and frontend SPA — `EncountersListTests`, `QsofaCurrentTests`, `GapAnalysisFixTests`, `OperationsApiTests`, `AlertQualityAnalyticsTests`, `ExplainableAlertsTests`, simulation suite (`SimulationRunnerTests`, `SimulationSessionTests`, `SimulationPurgeTests`, `SessionCatalogTests`, `AlertQualityScenarioAttributionTests`), `vigilcare-dashboard` Vitest suite (replay scrubbing, feedback store, FeedbackButtons, FeedbackSummary, alert components, AlertReasoning, charts, ward table, ward sort, ward filter, department format, sepsis format, alert acknowledge, critical alert detect, handoff report, vitals form, GCS entry/history, SOFA panel/history, qSOFA history, scores panel, alert labels, PatientBanner, EncounterTimeline, medication chart markers, AcknowledgeModal, CriticalAlertBanner, DepartmentOverviewView, SepsisBoardView, VitalsEntryForm, useAlertStore, useWardStore, roleAccess, ThresholdManagementView, DischargeSummaryPanel, GatewayOperations, alertQuality, SimulationControlView, SessionCard, ResetWardPanel, ScenarioCard, SimulationRunPanel, SimulationModeBanner, useSimulationStore).
|
||||
|
||||
**Enhanced Dashboard (post-Phase 22):** Major dashboard feature expansion addressing clinical workflow gaps. **Department Overview** (`/departments`) — unit-level snapshot cards showing patient count, critical/alert/bundle totals per department with acuity distribution bars; click-through to ward filtered by department. **Sepsis Bundle Board** (`/sepsis`) — real-time bundle compliance tracking with countdown timers to 1-hour deadline, urgency-sorted (overdue → at-risk → on-track), live 1-second tick updates. **Critical Alert Notifications** — `CriticalAlertBanner` surfaces new critical alerts from polling cycle with audible 880Hz two-tone alert, browser title flash, and native `Notification` API integration; mute toggle persisted in settings. **Shift Handoff Report** — `HandoffReport.vue` generates SBAR-format (Situation, Background, Assessment, Recommendation) structured reports for all ward patients, enriched with latest vitals, open alerts, pending orders, and sepsis bundle status; ward summary with department stats; print/PDF export. **Vitals Entry Form** — `VitalsEntryForm.vue` on patient detail page enables manual observation recording (7 vital parameters with AVPU dropdown) with client-side plausibility validation matching server-side ranges. **Ward Table Enhancements** — multi-column sorting (room, patient, department, NEWS2, qSOFA, sepsis, alerts) with sortable column headers, debounced patient search (name/MRN), quick-filter toggles (critical, has alerts, active sepsis), clear-all filters. **Acknowledge Modal** — role-aware acknowledgment with clinician identity pre-populated from JWT, role-specific guidance text, and acknowledgment note preview. Backend additions: `GET /sepsis-bundles` paginated hospital-wide list with `SepsisBundleSummary` (patient demographics, elements, deadlines); `WardEncounterSummary` extended with `sofaScore`, `sofaDelta`, `gcsScore`, `gcsClassification`, `lastObservationAt`, `attendingPhysician`, `admittedAt`.
|
||||
|
||||
@@ -2350,11 +2385,13 @@ Thirty-three phases from the project roadmap are implemented and verified, inclu
|
||||
|
||||
**Degraded Operations Visibility (Phase 23):** Gateway fleet operations panel with stale gateway auto-detection (`GatewayStaleDetectorService`), discharge summary API with MinIO PDF retrieval, admin panels for user management, threshold management, audit log browsing, and reconciliation viewing. Frontend adds role-aware sidebar navigation, degraded-mode banner for offline gateways, and comprehensive admin CRUD views.
|
||||
|
||||
**Alert Quality Analytics (Phase 33):** Server-side clinician feedback persisted as `AlertFeedback` entities (one per user per alert, six feedback types). `AlertQualityAggregatorService` periodically computes per-alert-type quality metrics (acknowledgement rate, false positive rate, useful rate, would-act rate, response times). REST API exposes quality metric snapshots and aggregate summaries. Grafana dashboard visualizes alert quality trends. Frontend analytics view with quality charts.
|
||||
**Alert Quality Analytics (Phase 33):** Server-side clinician feedback persisted as `AlertFeedback` entities (one per user per alert, six feedback types). `AlertQualityAggregatorService` periodically computes per-alert-type quality metrics (acknowledgement rate, false positive rate, useful rate, would-act rate, response times). REST API exposes quality metric snapshots and aggregate summaries. Grafana dashboard visualizes alert quality trends. Frontend analytics view with quality charts. Phase 38 extends this with `GET /alerts/quality-metrics/feedback` scenario attribution (`scenarioId` / `sessionId` via `SimulationRun.EncounterId` join), scenario filter, by-scenario breakdown, and CSV columns.
|
||||
|
||||
**Explainable Alerts (Phase 34):** Composite alerts (NEWS2, SOFA, GCS, rapid deterioration) carry an immutable JSONB `explanation` snapshot at creation — score contributors with raw values and normal ranges, trend context (percent change, duration, direction), structured medication context, and a bedside `NarrativeSummary`. `AlertResponse` exposes explanation on GET/list/acknowledge/resolve. Downstream consumers (Elasticsearch indexer, data lake Parquet, ward gateway sync, Kafka `alert.generated`) propagate explanation without breaking legacy consumers. Dashboard `AlertReasoning.vue` renders structured reasoning. Simulator validates `narrativeContains` on key scenarios.
|
||||
|
||||
**MIMIC-IV Replay Scenario Generator (Phase 35):** Offline CLI tool that converts real de-identified ICU data from MIT's MIMIC-IV dataset into VigilCare scenario JSONs. `mimic-list` browses 140 ICU stays across 100 patients with demographics, care unit, LOS, and outcome. `mimic-generate` produces a scenario from a specific stay ID with options for duration capping, medication/lab exclusion, and inline validation. The streaming CSV parser handles 668K-row chartevents efficiently by filtering at the string level before allocating records. Item mappings cover 17 chart event items (vitals, GCS text-to-numeric, FiO₂, PaO₂, ICU labs) and 8 lab event items (creatinine, platelets, bilirubin, lactate, WBC, potassium, glucose, PaO₂). Blood pressure deduplication prefers non-invasive over arterial readings. The 10-observation-per-cluster limit is enforced by priority-based splitting (vitals first, labs spill to the next offset). Generated scenarios are structurally identical to hand-crafted ones and replay through the existing `replay` command, driving NEWS2, SOFA, GCS, qSOFA, trend detection, and alerting on real patient trajectories.
|
||||
**MIMIC-IV Replay Scenario Generator (Phase 35):** Offline CLI tool that converts real de-identified ICU data from MIT's MIMIC-IV dataset into VigilCare scenario JSONs. `mimic-list` browses 140 ICU stays across 100 patients with demographics, care unit, LOS, and outcome. `mimic-generate` produces a scenario from a specific stay ID with options for duration capping, medication/lab exclusion, and inline validation. The streaming CSV parser handles 668K-row chartevents efficiently by filtering at the string level before allocating records. Item mappings cover 17 chart event items (vitals, GCS text-to-numeric, FiO₂, PaO₂, ICU labs) and 8 lab event items (creatinine, platelets, bilirubin, lactate, WBC, potassium, glucose, PaO₂). Blood pressure deduplication prefers non-invasive over arterial readings. The 10-observation-per-cluster limit is enforced by priority-based splitting (vitals first, labs spill to the next offset). Generated scenarios are structurally identical to hand-crafted ones and replay through the existing `replay` command (or in-app Simulation), driving NEWS2, SOFA, GCS, qSOFA, trend detection, and alerting on real patient trajectories.
|
||||
|
||||
**Self-service clinical simulation (Phases 36–38):** Default-off in-app runner (`Simulation:Enabled`) loads scenario JSON and `sessions.json` presets, replays via loopback as `simulation.runner`, and marks patients `IsSimulated`. Dashboard **Simulation** page offers Sessions (A–D presets with all-or-nothing staggered multi-run start), Scenarios catalogue, speed control, run progress, and typed ward reset that purges only simulated data (`SIMULATION_DATA_PURGED` audit). Alert Quality feedback joins to `SimulationRun` for scenario/session attribution. Clinical testing guide rewritten so doctors and nurses complete Sessions A–D with no terminal; CLI remains the developer/CI tool (`docs/simulator-guide.md` §12). Roadmap: `docs/plans/vigilcare-clinical-roadmap.md`.
|
||||
|
||||
**Post-phase hardening (after Phase 31):**
|
||||
- **FHIR R4 read/search** — `FhirReadController` adds `GET /fhir/R4/Patient/{id}`, `GET /fhir/R4/Patient` (search by `identifier`), `GET /fhir/R4/Encounter/{id}`, `GET /fhir/R4/Encounter` (search by `patient`/`status`); new `fhir:read` permission for Admin and Integration roles; CapabilityStatement updated to advertise `read` and `searchType` interactions for Patient and Encounter
|
||||
|
||||
Reference in New Issue
Block a user