Uh oh!
There was an error while loading. Please reload this page.
feat(S5): Population Dashboard + drill-in (Director) - #6
Merged
manjula25 merged 7 commits intoJul 5, 2026
Merged
Conversation
A1: deterministic ~500-patient cohort (diabetes/CHF/depression) with per-patient RiskAssessment from a documented heuristic and US Core race/ethnicity; wired into the existing $batch import (idempotent PUT). B1: roleHome routes Director -> /population; Director-only /population route via RoleGuard role prop. Placeholder Population page pending B2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A2: audited population/ aggregate service over HAPI (RiskAssessment + Encounter, paginated via _count + link[rel=next]) — getPopulationScatter and getPopulationSummary, Director-only (explicit role check + denial audit, since hasScope grants coordinator the same domains), cost-avoidance from a pure documented formula over real risk counts. Also fixes import-fhir.ts to chunk the $batch POST (250/request) so the ~2500-entry cohort import no longer exceeds the client's headers timeout. B2: W02 Population Dashboard — native Canvas risk x urgency scatter (no chart library, GD10), KPI tiles computed from the summary API, mockup fidelity ~83% against reference-materials/caresync-population.html with deviations documented in Population.tsx/PopulationScatterChart.tsx (Care Team/HEDIS/Activity as S6+ placeholders, no fabricated numbers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clicking a scatter point's risk/urgency quadrant (thresholds >=60/>=60, reusing lib/patient.ts's amber-risk cutoff) filters the already-fetched scatter array client-side and navigates to /population/patients with the filtered ids in router state. pixelToQuadrant/unprojectPoint are exact inverses of the existing paint projection, so hit-testing can't drift from what's drawn. The new list page reuses the existing GET /api/patients/:id per id (useQueries, isolated failures) and links into the unmodified PatientDetail route — no new backend endpoint. Also hoists the shared risk-dot Tailwind class map (previously duplicated in PatientPanel) into lib/patient.ts as RISK_DOT_CLASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Login -> W02 dashboard (asserts computed KPI values, not the mockup's hardcoded 23/$247,400/847) -> click the critical risk/urgency quadrant on the native Canvas scatter -> filtered "Critical -- Act Now" list -> PatientDetail. Drives the click via the same padding/threshold constants the scatter paints with, so the test can't drift from the real projection. Passes standalone and under the full 5-worker parallel suite (bumped the KPI-tile assertion timeout to 15s -- the population aggregate bulk-reads ~500 patients from HAPI and is the suite's slowest fetch). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Rotates the prior slice's verification.md/review.md to verification-s4.md/ review-s4.md (this repo's established per-slice naming convention) and adds a fresh verification.md documenting S5's evidence: apps/api 23/23 suites (106/106 tests, serial) against the live-imported ~500-patient cohort, apps/web 12/12 files (108/108 tests), and the full Playwright E2E suite (8/8, including the new Director population flow) both standalone and under parallel load. Also flips the stale S5 checkboxes in issues.md and implementation-plan.md now that every acceptance bullet is independently confirmed against the code and this session's live evidence. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Both axes reviewed as parallel sub-agents over 9e2f01c...HEAD. Standards: 0 hard violations, 4 non-blocking Fowler-smell judgement calls. Spec: 0 missing/wrong acceptance-bullet requirements, 2 low-severity already- disclosed deviations (procedural cohort vs literal "Synthea"; team KPIs deferred to S6/S7). No blocking findings — none require a code change before shipping S5. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merged
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
S5 — Population Dashboard + drill-in (Director)
Delivers the Director's entry narrative (W02), stacked on S4.
On login a Director now lands on a Population Dashboard: ~500 patients as a native-Canvas risk×urgency scatter, a critical-zone count, a projected cost-avoidance figure, and KPI tiles — all computed live from a population aggregate API over HAPI (no chart library per GD10; no precomputed store). Clicking a scatter quadrant drills to a filtered patient list → the existing patient detail view.
What's in it
mulberry32) generator of 500 diabetes/CHF/depression patients with US Core race/ethnicity and a per-patientRiskAssessmentfrom a documented heuristic. (User-approved procedural generator in place of real Synthea, for testability/reproducibility.) Also fixes a real import bug: the single ~2,500-entry$batchPOST exceeded undici's headers timeout even though HAPI committed everything — now chunked at 250/request, idempotent.GET /api/population/scatter+/summary. Paginated HAPI reads (_count=1000+link[rel=next]), critical-zone count from real scores vsCRITICAL_RISK_THRESHOLD, cost-avoidance from a pure documented formula (fixture-tested). Director-only enforced via explicit role check + denial audit (sincehasScopegrants coordinators the same domains).roleHomedirector →/population, Director-only route guard.23/$247,400), honest placeholders for S6+ panels. ~83% mockup fidelity, deviations documented in-file./population/patientslist (reuses existinggetPatient/PatientDetail, no new backend endpoint).pixelToQuadrantis a true mathematical inverse of the paint projection.Acceptance criteria (issues.md S5) — all met
Verification (local mock / packaged-UI strength)
apps/api: 23/23 suites, 106/106 tests (serial; parallel is pre-existing shared-HAPI flake)apps/web: 12/12 files, 108/108 testsFull evidence in
docs/plans/caresync-ai/verification.md; two-axis code-review (0 hard/blocking findings) indocs/plans/caresync-ai/review.md; changelog underdocs/superpowers/specs/feature-caresync-s5-population-dashboard/.Base
Stacked on
feature/caresync-s4-agent-graph-cache— review that PR first; the diff here is S5-only (7 commits).🤖 Generated with Claude Code