feat(timeline): med-mal chronology view backed by event log

✅ merged · #3 · rmerk/mike ← rmerk/mike · opened 15d ago by rmerk · merged 15d ago by rmerk · self · +485 across 4 files · ↗ on GitHub

From the PR description

Summary

Phase 3 of the med-mal records platform. Adds a Timeline view at /projects/[id]/timeline/[docId] that surfaces the Phase 2 document_events log as a fast, citation-anchored chronology - satisfying the roadmap §Phase 3 verification gate ("+ Medical Chronology on a fully-extracted document takes < 2s, no LLM call; non-extracted docs fall back to existing flow").

  • New route reads the existing GET /extraction/:documentId/events; zero backend changes, no migrations.
  • + Medical Chronology on ProjectPage routes to Timeline when ≥1 PDF is ready: single PDF → direct, multiple → picker modal, zero PDFs → falls back to the existing tabular-create modal.
  • MedMalDocumentEvent widened to expose provider, provider_role, event_time, episode_of_care, key_date_role, event_date_text (the backend already returns these via select *; the frontend type just hadn't kept up).
  • Defense-in-depth: mental_health_144_293 records hidden by default with a header toggle, even though the backend already filters peer_review_145_64 server-side.

Why Rail-A-only

Earlier drafts of docs/PLAN_med_mal_phase3_integration.md included a "Rail B" - tag schemas as eventLogBacked and populate tabular_cells from event-log SQL. Reading the actual MAR schema during planning surfaced that every event-log-backed schema is per-encounter (one row per medication administration / vital sample / line item), while tabular_cells is keyed (review, doc, column) - one row per doc. Collapsing N encounters into a single cell loses sort/filter/per-row inspection - i.e., it isn't really a tabular review anymore.

Rail-A-only ships the chronology Timeline as a separate surface and leaves tabular reviews for what they're good at (per-doc summaries). MAR / vitals / labs views are deferred as Phase 3.5 follow-ups - same Timeline pattern, different lens.

Test plan

  • Manual e2e on an extracted med-mal doc - agent did not run this; needs a running stack + a project with document_extractions.status='complete'.
    • Click + Medical Chronology on an extracted doc → Timeline route loads in <2s (browser devtools network panel).
    • No /chat/* or /tabular-review/*/generate traffic during load.
    • Click an event row → PDF preview scrolls to source_page, bbox highlight overlays the citation.
    • Toggle "Show § 144.293 records" header checkbox → mental-health events appear/disappear.
  • Manual e2e on a non-extracted doc - + Medical Chronology either falls back to the tabular modal (zero PDFs) or routes to a Timeline that shows the "No completed extraction" empty state with a link to /projects/[id]/extraction.
  • Backend npm run build clean (untouched).
  • Frontend npm run build clean; new route listed (/projects/[id]/timeline/[docId]).
  • Frontend npm run lint clean for the new file. (Pre-existing lint errors in unrelated files are out of scope.)

Our analysis

Ship a chronology timeline view as Phase 3 of med-mal extraction — read the full analysis →

Think the analysis missed something the PR description covers?

Capture this PR into my fork

Download a Markdown prompt that tells Claude how to port every commit in this PR into your working tree. Run it via claude -p < capture-pull-3.md from inside the repo you want the changes in.

⬇ Download capture-pull-3.md