Session Log¶
Historical record of all development sessions. Moved from CLAUDE.md to reduce context window usage. For the latest session, check
docs/changelog/.
Session 95 — 2026-05-07: Matching Framework Phase 0 + Triage MVP¶
Summary¶
Matching framework planning (ADR-0026) and Phase 0 implementation: doctor-to-Neo4j projection, admin graph rebuild endpoint, triage MVP page, CSP fix for Swagger/ReDoc, and MSO teleconsultation GRANT migration. Audit follow-up PR (#773) hardened tenant scoping on the flags endpoint and extracted projection_service.py.
Architecture Decisions¶
- ADR-0026 — Postgres = canonical source of truth. Neo4j = read-only projection. Parameter registry pattern (
config/matching/parameters/<domain>.yaml) deferred to Phase 1. QStash-driven async sync with on-demand bulk-rebuild fallback viaPOST /api/v1/admin/graph/rebuild.
Significant Changes¶
app/services/graph/provider_graph.py—sync_doctor_to_graphfunction (projects PostgresDoctorrows into Neo4j including procedures, specialties, languages)app/routers/admin_graph.py— new.POST /api/v1/admin/graph/rebuildwithgraph:rebuildpermissionapp/services/graph/projection_service.py— new. Extracted from provider_graph in audit follow-up (#773)app/routers/admin_flags.py—GET /effectiveendpoint;AuditLogon identity overridesapp/middleware/security_headers.py— CSP relaxed for/docsand/redocconfig/feature_flags.yaml— 6 new flags: 5 triage/MSO thresholds +procedure_reqs_from_graphseed_doctors_full.py— backfills 172 doctors into Neo4j- Migration
j4k5l6m7n8o9_grant_graph_rebuild_super_admin.py— grantsgraph:rebuildtosuper_admin - Migration
i3j4k5l6m7n8_grant_mso_telecon_to_curaway_app.py— DML on teleconsultation tables
New Runbooks¶
docs/runbook/triage-tuning.md— threshold reference, adjustment guidance, monitoring steps
Issues Filed¶
-
765 (matching framework epic), #766 (Phase 0), #767 (Phase 1), #768 (triage MVP), #769 (triage live preview), #774 (
_LANGUAGE_NAMESextraction), #775 (audit-log read E2E test)¶
MVP Build Roadmap (Sessions 1–16)¶
| Session | Phase | Deliverables | Tool |
|---|---|---|---|
| 1–2 | Infrastructure Spine | Project skeleton, Docker, FastAPI, config, CI/CD, cloud accounts | Claude.ai Chat |
| 3–4 | Intake Pipeline | 17 models, patient CRUD, consent, FHIR, documents, audit, 70 tests | Claude.ai Chat |
| 5 | Provider + Matching | Provider model, weighted matching v1, strategy pattern, 89 tests | Claude.ai Chat |
| 6 | Railway Deployment | Live API on Railway, Railway PostgreSQL, auto-deploy | Claude.ai Chat |
| 7 | FHIR Validation + GDPR | fhir.resources validation, GDPR deletion, correlation IDs, 106 tests | Claude.ai Chat |
| 8 | Flagsmith + Model Routing | Feature flags, model registry YAML, A/B routing | Claude Code |
| 9 | Email + Currency | Resend email, Frankfurter multicurrency | Claude Code |
| 10 | Idempotency + Swagger | Idempotency keys, Swagger polish | Claude Code |
| 11 | Neo4j Knowledge Graph | Neo4j Aura, graph seeding, traversal queries | Claude Code |
| 12 | Clinical Context Agent | LangGraph + Claude: report parsing, ICD extraction, FHIR generation | Claude Code |
| 13 | Intake + Match + Explain | Conversational intake, agent-enhanced matching, LLM explanations | Claude Code |
| 14 | MCP + Orchestrator | MCP server, agent orchestrator, Langfuse tracing, /chat endpoint | Claude Code |
| 15 | Frontend Rewiring | Lovable frontend rewired to Railway API, deployed on Vercel | Claude Code |
| 16 | Polish + Demo Prep | Metabase dashboards, PostHog, E2E tests, demo script | Both |
Session 17: Case Management + Conversation¶
Architecture Decisions¶
- Conversation-first UX: The entire patient journey (intake, documents, EHR, matching, consent, forwarding) is driven through a single conversational interface per case
- PostgreSQL JSONB for conversations: Messages stored as rows with JSONB rich_content, not a separate document store. Pagination via composite index (conversation_id, created_at). LLM context built from last N messages.
- Configuration-driven procedures: Adding a new procedure = inserting a row in procedure_requirements, not writing code. Parent inheritance (ORTHO_BASE → TKR) merges required_documents, comorbidity_screening, contraindications.
- Voice input architecture: Client-side Web Speech API (MVP default) → OpenAI Whisper API (toggle via feature flag) → Deepgram streaming (future). WebSocket stub at /voice/stream ready for Deepgram.
- Case lifecycle: intake → documents_pending → ehr_complete → matching → matched → provider_selected → consent_given → forwarded → closed. Forward-only transitions (+ any → closed).
New API Endpoints¶
- POST/GET /api/v1/cases — Create and list patient cases
- GET /api/v1/cases/{id} — Case detail with workflow state
- POST /api/v1/cases/{id}/chat — Unified chat (stub orchestrator, voice support)
- GET /api/v1/cases/{id}/messages — Paginated message history
- GET /api/v1/cases/{id}/ehr — EHR snapshot
- GET /api/v1/cases/{id}/confirmation — Case summary
- POST /api/v1/cases/{id}/select-providers — Provider selection
- POST /api/v1/cases/{id}/consent — Consent recording
- GET /api/v1/procedure-requirements/{code} — Procedure requirements with inheritance
- POST /api/v1/voice/transcribe — Whisper STT
- WS /api/v1/voice/stream — Streaming STT stub
Data¶
- 5 new tables: cases, conversations, messages, procedure_requirements, provider_procedures
- 12 procedure requirements seeded (2 base categories + 10 procedures)
- 17 tests passing
Session 18: Provider-Procedure Seeding + Agent Orchestrator¶
- 38 provider-procedure links seeded across 10 procedures and 15 providers
- Neo4j: 10 Procedure nodes, 38 PERFORMS relationships, 7 Specialties, 13 Conditions
- Real agent orchestrator replaces stub — routes through 8 workflow phases
- 4 sub-agents: document_agent, ehr_builder_agent, consent_agent, case_orchestrator
- Rich content types: file_request, ehr_summary, match_results, consent_form, confirmation
- Provider matching queries provider_procedures with procedure-specific filtering
Session 19: Frontend — Conversational UI¶
- Conversation-first UX replacing multi-page dashboard
- ConversationApp: sidebar + message thread + input bar + right panel
- Rich cards inline: match_results, file_request, consent_form, confirmation
- Case sidebar with status, right panel with EHR/Documents/Progress tabs
- Auth redirects to /app, old routes redirect
Session 20: Integration Polish + Demo Readiness¶
- File upload through conversation: paperclip + drag-and-drop
- Voice input via Web Speech API (Chrome/Edge)
- Mobile responsive with safe-area padding
- CSS animations: message slide-in, card fade, panel slide, typing dots
- Intake agent fix: negation detection ("No osteoporosis" no longer detects osteoporosis)
- Question tracking via case metadata (prevents repeating questions)
- 16 E2E tests passing
- MVP investor demo-ready
Session 21: UX Refinements + Intelligent Agent¶
- Frontend: Claude-style interface (no agent bubbles, pulsating logo, 780px column)
- Backend: records-first flow, grouped questions, intake completes after 3+ answers
- Lab analyzer: auto-detects comorbidities from blood reports
- Progressive EHR building, matching when completeness > 50%
Session 21B: File Upload → Chat Integration¶
- Backend: attachments now passed from chat endpoint to case orchestrator
_process_attachments(): fetches doc metadata, runs Clinical Context Agent on OCR text, detects comorbidities via Lab Analyzer_handle_attachment_response(): LLM-powered response summarizing clinical findings from uploaded documentsdocument_reviewphase added to LLM conversation prompts- Frontend: FileAttachmentCard component shows uploaded file badges in user message bubbles
- Frontend: new-case creation path now uploads files and passes attachments to chat
- Full flow: upload → R2 → presign/confirm → chat with attachment metadata → orchestrator processes docs → agent responds with clinical analysis
- Langfuse tracing: session_id=case_id (groups all chat turns per case), user_id=patient_id
- Every LLM call (Claude Haiku) now traced via LangChain callback handler through the full chain: chat endpoint → orchestrator → llm_conversation
Session 22: Critical UX Fixes (8 Issues from Demo Feedback)¶
- Issue 1: Zero state centered input + lazy case creation (no case until first message)
- Issue 2: Enhanced FileAttachmentCard with upload/analyzing/analyzed status states
- Issue 3: Provider match results now have checkboxes + multi-select + "Send Records" submit button
- Issue 4: Missing documents warning shown in match results card
- Issue 5: EHR tab shows full structured content (collapsible sections: demographics, condition, comorbidities, medications, allergies, diagnostics, risk factors, summary)
- Issue 6: Duplicate document names handled — previous versions marked superseded on re-upload
- Issue 7: Summary tab added to right panel (4th tab) — shows what providers will receive
- Issue 8: Sidebar starts collapsed (64px icon strip), expands on click
- "New Case" button navigates to welcome state (no backend call)
- InputBar extracted as shared component between welcome state (centered) and chat (bottom)
- Provider selection calls selectProviders API then triggers consent flow via chat
Session 23: Document Checklist + Contextual Anomaly Detection¶
- New
GET /cases/{id}/document-checklistendpoint: cross-references uploads against procedure requirements app/services/document_validator.py: detects laterality mismatch, document age, wrong body part, patient name mismatch, poor OCR quality- Validator wired into orchestrator
_process_attachments: runs after Clinical Context Agent, stores issues on document - Validation issues passed to LLM context: agent addresses anomalies conversationally
- High/critical issues block workflow advancement until patient clarifies
- Frontend:
DocumentChecklistCardrich card +ChecklistRowcomponent with per-requirement status icons - Documents tab in right panel now shows requirements-based checklist (not flat file list)
document_checklistregistered as rich content type in conversation rendering
Session 23B: Attachment Wiring Fix + Loading UX + Cross-Case Reuse + Panel Sync¶
- Bug fix: inline OCR via PyMuPDF when document OCR hasn't completed yet (was the root cause of "can't see attachment" — OCR queued but not done when chat runs)
- Added
storage_keyto attachment query so R2 download works for inline OCR - Cross-case record reuse:
_check_existing_records()finds valid analyzed docs from previous cases, auto-links them - TypingIndicator now shows rotating context-aware messages (6 attachment-specific, 3 generic) changing every 3s
sendingWithFilesstate tracks whether current send has attachments for indicator- Progress tab now uses real document checklist data: shows "2 of 5 mandatory uploaded" instead of false "Collected"
- Panel sync: document checklist fetched once in CasePanel, shared by Documents + Progress tabs
- Langfuse v4 SDK fix deployed (separate commit) — traces should now appear
Session 23B Continued: Attachment Pipeline Fixes + Real-Time Delivery¶
- Root cause traced via diagnostic logs: scanned PDFs → PyMuPDF returns 0 chars → no analysis → LLM hallucinates "can't see file"
- Fix: immediate acknowledgment when all docs are still processing (no LLM call)
- Root cause 2:
has_issuesstatus (from validator) not counted as analyzed → treated as pending - Fix:
has_issuescounts as analyzed for routing, response generation, workflow advancement - Stronger
document_reviewLLM prompt: mandates reporting specific findings, forbids "can't see" responses - Rich entity context passed to LLM (full details with values, codes, risk levels)
- Event-driven model: QStash OCR callback inserts follow-up assistant message with findings
- Upstash Redis pub/sub:
app/integrations/redis_pubsub.py— RPUSH/LPOP pattern for real-time message delivery - SSE endpoint
/cases/{id}/messages/streambacked by Redis (zero DB polling per client) - Frontend: EventSource listens for
new_messageevents + refetches after each send - Flagsmith cache (60s TTL) + Qdrant version update to fix Railway deploy failures
- PostHog proxy via Vercel
/ingest/*rewrites to bypass ad blockers
Session 24: Agent Guardrails + File Upload Validation¶
config/guardrails.yaml: single source of truth for all guardrail rules (classifier categories, response templates, forbidden output patterns, medical keywords, file limits)- Input classifier (
message_classifier.py): Claude Haiku classifies messages into 8 categories before reaching the agent. Off-topic/medical-advice/prompt-injection → warm redirect. Fails open. - Output validator (
output_validator.py): regex-based check for forbidden patterns (diagnosis, treatment recommendations, outcome predictions, breaking character). Uses allowed exceptions to avoid false positives. - Guardrail responses (
guardrail_responses.py): brand-voiced redirect templates loaded from YAML - File validator (
file_validator.py): metadata-only validation at presign (extension, MIME, size). No R2 download. - Frontend file validation: rejects wrong extensions, >20MB, <5KB before upload with inline error toast
- System prompt updated with safety guardrails (never diagnose, never recommend treatment, never predict outcomes)
- 3 feature flags:
guardrail_input_classifier_enabled,guardrail_output_validator_enabled,guardrail_file_validation_enabled - All rules configurable via YAML — zero code changes to add categories, patterns, or keywords
- LLM conversation history filtering: removes toxic "can't see file" messages before LLM context
- Per-document dedup: sync response stores processed_document_ids, async callback skips if already handled
Session 25: UI/UX Overhaul¶
- Icon Rail (56px) + Left Panel (360px) + Chat (720px) + Progress Strip (48/280px)
- EHR Panel: fixed React hooks ordering bug (#310), collapsible sections, conditions table
- Progress Strip: continuous background line, 3-state documents step, unique Lucide icons
- Summary Panel: 3 cards (Patient Info, AI Observations, Provider Brief)
- Consent card with T&C checkbox + overlay
- Ghost skeleton loading during case switches
- PostHog error capture in ErrorBoundary
Session 25B: Document Matching + EHR Fixes¶
- Document matching evolution: keyword → strict → balanced → embedding-based (Option 6)
- EHR completeness scoring fix:
>= 0→> 0, excluded "Unknown" procedure - Embedding-based matching: Voyage AI → Qdrant
requirement_embeddings(70 vectors) → cosine similarity - QStash OCR callback enriched with embedding step after Clinical Context Agent
_match_doc_by_embeddings()in cases.py with keyword fallback
Session 26: Doctors Schema, Language Services & Matching Pipeline¶
- New tables:
doctors(8 rows),doctor_procedures(8 rows) - New columns:
providers.language_services(JSONB),provider_procedures.lead_surgeon_id - New endpoints: 9 under
/api/v1/doctors/ - New services:
doctor_service.py,data_completeness.py,language_concordance.py,weight_redistribution.py - 8 seed doctors, 6 providers with language_services
- Neo4j: Doctor nodes + AFFILIATED_WITH, PERFORMS, SPECIALIZES_IN, SPEAKS relationships
- Matching engine: doctor-level scoring behind
DOCTORS_IN_MATCHINGfeature flag - 15 tests passing
Session 27: Living Documentation Site¶
- MkDocs Material site at
docs.curaway.ai(auto-deploys via Vercel) - 11 architecture docs, 12 ADRs, API reference, runbook
- GitHub Actions:
docs.yml(deploy),docs-drift.yml(PR warning) - Session discipline: Every session that changes architecture must update relevant doc file(s) and/or add an ADR
Session 27B: Bug Fixes (First-Message Attachments, EHR Dedup, New Case Button)¶
- fix: first-message attachment ignored — Orchestrator now processes both inline
- fix: EHR showing 53 duplicate conditions — deduplication by ICD-10
- fix: New Case button redirected to active case —
intentionalNewCaseRef - fix: agent re-asks city/country already provided — checks EHR demographics first
- fix: blood work flagged as wrong body part — exempts systemic tests
- feat: auto case title from procedure_name
- 5 new tests in
tests/test_ehr_dedup.py
Session 28: Traceability & Context Engine (Phases 1-3)¶
- Patient State Object, Decision Recorder, Outcome Tracker, Feedback Service
- Feedback Records table with decision-outcome links
- 6 new endpoints under feedback router
- Orchestrator wiring: patient state built before routing, decision recorded after every turn
Session 29: Provider Storefront + JSON Leak Fix¶
- Provider Storefront Backend: 9 public GET endpoints under
/api/v1/public/ - Full data enrichment: 42 providers, 91 doctors, 12 treatments, 52 provider-procedure links
- Storefront Frontend: 11 pages
- JSON leak fix: LLM raw JSON stripped from chat responses
- Parameter-level document matching: 13 parameter sets
- Auto-reviewer activated: 16 cases reviewed, 88 feedback records
Session 30: Agent Pipeline + Local Dev + Procedure Requirements¶
- Local dev environment: docker-compose.dev.yml, .env.local.example, Makefile
- 7 Claude Code Subagents in
.claude/agents/ - Chat Extractor, LLM Requirement Matcher, rewritten agent prompts
- System Landscape Page at
/landscape - Procedure requirements: 137 test mappings, 7 provider overrides
- 42 tests passing
Session 31: Test Coverage Sprint + Latency Optimization + Neo4j Wiring¶
- 760 backend tests (0 failures), 32 frontend tests
- Latency: 13.2s → 7.9s average (-41%)
- Neo4j procedure requirements wiring with CPT→slug mapping
- Smart document validation with validity windows
- Feature flags:
enable_timing_middleware,enable_chat_cache,enable_parallel_pipeline,enable_deferred_extraction,enable_response_streaming,enable_inline_ocr,procedure_reqs_from_graph
Session 32: SSE Upload Progress Streaming¶
- Progress schema with 6 steps, Redis-backed SSE
- Dual-source stream: Redis fast path (300ms) + DB poll (5s)
- Frontend: DocProgressStep interface, second EventSource
- Feature flag:
enable_inline_ocr
Session 33: Risk assessor, conversation flow gates v2, full EHR drawer, voice fixes¶
- 15 PRs merged (8 backend, 5 frontend, 2 docs)
- ~50 unit tests added (24 gates_v2 + 26 risk_assessor)
- Rule-based risk assessor (
risk_assessor.py): ~30 rules, source provenance,is_blocking - Conversation flow gates v2: 5-condition intake gate, explicit advance phrases
- Full EHR drawer (FullEHRDrawer.tsx, 1184 LOC)
- 2 prod outages caught and fixed
- Feature flags:
gates_v2,VITE_FULL_EHR_VIEW
Session 34: LLM gateway service, clinical extraction timeout handling¶
- LLM gateway service centralises all Anthropic API calls
- Clinical extraction timeout handling with graceful degradation
- Split clinical findings SSE messages
- 2 production bug fixes via Langfuse traces
Session 35: FHIR provenance, DataForwardingAudit, sender_type¶
- FHIR provenance: document_id + case_id on fhir_resources
- DataForwardingAudit table for forwarding events
- sender_type on messages (patient/agent/coordinator)
- ADR: Coordinator interaction model
Session 36: Prompt abstraction, production 500 fixes¶
- Prompt abstraction: conversation_v2.yaml + per-phase context YAMLs
- 2 production 500s patched
- Voice rules updates
Session 37: EHR drawer V2 wiring, theme system, mobile responsive¶
- EHR drawer V2 prototype wired end-to-end
- Theme system: 3 themes (default, dark, high-contrast)
- Mobile responsive fixes
- Auth pages redesign
Session 38: EHR drawer rewrite, Lab Results + Documents tabs, asyncpg fix¶
- asyncpg SQL fix unblocked all EHR rebuilds
- FHIR dedup scoped to same resource_type
- EHR drawer rewrite with dynamic SECTION_REGISTRY
- 22 PRs merged, 26 new tests
Session 39: Case record porting, DICOM Phase 1 spec, DocumentViewer¶
- Case porting shipped end-to-end (26 tests)
- OCR failure handling with graceful degradation
- DocumentViewer surfaced from chat, EHR drawer, all source links
- 20 live conversation issues caught and fixed
- Feature flag:
case_porting_enabled
Session 40: Gap report sweep, ADR-0019, security hardening¶
- 21 of 31 gaps closed
- ADR-0019: GDPR Article 17 full cascade (6 missing tables)
- Security headers middleware, consent gate middleware, QStash HMAC verification
- Event Type Registry (35 known event types)
- RTL support, extraction indicators
- Gap report: 21/31 done (68%)
Session 41: DAO Layer + Repository Pattern¶
- DAO repository layer implemented:
BaseRepository(tenant-scoped),BaseUnscopedRepository(global catalogs) - All PostgreSQL access routed through
app/repositories/ - Models → Repositories → Services → Routers hierarchy enforced
TenantIsolationViolationraised iftenant_idis None/empty- ADR-0016: DAO / Repository Pattern accepted
- ADR-0017: Multicurrency Architecture accepted
- ADR-0020: HAPI FHIR Adoption deferred with trigger-based evaluation
Session 42: Multicurrency + Provider Portal Design¶
- Multicurrency architecture: all money in USD cents + ISO 4217
- No floating-point currency math enforced
- Provider Portal design brief: ADR-0018 amended to cover facility capabilities
- Provider Portal architecture doc (
docs/architecture/13-provider-portal.md)
Session 43: Wave 1 — Triage Agent Wiring + Production Fixes¶
- Triage Agent wired into
case_orchestratorentry point; replaces old orchestrator routing - SSE tenant_id read from query param (EventSource compatibility)
- Production fixes: RLS tenant context via
set_config(), deployment unblocker, runtime warning cleanup - Extractor hallucination fix; travel scoring default tier removed
- Triage Agent uses minimal prompt to reduce latency
Session 44: Wave 1 Stabilisation + LLM Gateway Cleanup¶
- LLM Gateway cleanup: E2E tests + input validation hardened
- All LLM calls confirmed routing through
llm_gateway.invoke() - Wave 1 intake restructuring marked complete; spec deviations documented
- Ruff + format clean pass
Session 45: Multi-Tenancy Phase 0 — RBAC, Case Shares, Redaction, State Machine¶
- RBAC middleware + JWT extraction (Pydantic V2 Field deprecation fixed)
- Case sharing model:
case_sharestable with role-scoped access - Redacted snapshot column on forwarded cases
- Case state machine formalised; Phase 0 wiring: migrations, API, feature flags
- Provider onboarding cross-tenant RLS context switch; invite_staff RLS fix
- Feature flags:
rbac_enforcement,case_state_machine_v2,redaction_engine,wave2_layer_ui
Session 46: Wave 2 Frontend — Design System + 8 UI Components¶
- Design system audit: Teal/Coral/Deep Ocean tokens verified across all components
- 8 new UI components: QuoteCard, ForwardingTimeline, ProviderInboxCard, StaffInviteModal, CaseSharePanel, RedactionPreview, StateChip, PortalShell
- Motion system: framer-motion spring presets (
curaway-spring,curaway-fade) - Theme audit sweep; Montserrat + Crimson Pro verified on all new components
- Pydantic V2
Field(example=)deprecation fixed across routers
Session 47: Phase 1 Provider Flow — Quote Model, Forwarding, Provider Portal¶
provider_quotestable + Alembic migration;redacted_snapshotcolumn addedCaseForwardingService: class-based service replacing module-level functions- Provider portal API: quote submission, inbox query, audit log
- Patient quotes endpoint: RLS context switch to read provider quotes cross-tenant
- Null
actor_idin audit logs fixed (getattr pattern); provider inbox target_tenant_id fix - Feature flags:
provider_forwarding_v1,provider_clerk_integration,provider_portal_v1
Session 48: Phase 1 Completion — Clerk, Notifications, E2E Validation, Test Mocks¶
- Real Clerk API integration for provider org creation
- Notification wiring: provider receives email on quote submission; patient on forwarding
- Admin API + patient quotes endpoint wired end-to-end
- 98 stale test mocks fixed:
ChatAnthropic→llm_gateway.invoke(32 mocks) + document/GDPR/lab/e2e mocks (66 mocks) - Platform health sweep: voice compliance, dependency pin, docs, changelog updated
Session 49: Phase 2 — Risk Assessment + MSO Second Opinion¶
- Phase 2 design briefs created: Risk Reviewer portal + MSO Second Opinion portal
- Phase 2 implementation spec created
- Full backend shipped:
risk_review.pyrouter (4 endpoints),mso_portal.pyrouter (6 endpoints) - New models:
RiskReview,RiskFactor,MSOConsultation - Case state machine extended:
risk_review_pending→risk_cleared→mso_offered→mso_complete - Missing medical extractor added to triage; decision recording fixed
- Voice fix: forced empathy replaced with tone matching in triage prompts
- Documents stuck at pending: silent OCR failure addressed
- Feature flags:
risk_assessment_enabled,risk_review_human_required,risk_blocking_override_allowed,mso_consultation_enabled,mso_video_embedded
Session 50: Phase 3 — Facilitators + Coordinators¶
- Phase 2 integration tests:
tenant_idadded tosubmit_document+request_recordscalls - Phase 2 security hardening: tenant-scoped lookups,
patient_idvalidation, JSONB migration fix - Phase 3 full backend shipped:
coordinator_portal.pyrouter (15 endpoints),facilitator_portal.pyrouter (4 endpoints) - New models:
Coordinator,CoordinatorAssignment,TransportVendor,TransportBooking,TimelineMilestone,CoordinatorNote,Escalation,Rating,FacilitatorConsent - Coordinator auto-assignment at
payment_locked: ranking by workload, tier, language, availability - Transport vendor directory + booking CRUD
- Timeline milestones + coordinator notes
- Escalation routing:
coordinator_manual+system_overduetrigger types - CSAT/ratings collection for coordinators and facilitators
- Feature flags:
facilitator_consent_enabled,coordinator_assignment_enabled,coordinator_queue_enabled,coordinator_services_transport_v1,coordinator_timeline_enabled,coordinator_escalation_enabled,coordinator_csat_enabled - Ruff lint auto-fix: 11 auto-fixed, 44 files formatted
Session 51: Phase 3 Full Backend — Facilitators + Coordinators¶
- Phase 3 backend complete:
coordinator_portal.py(15 endpoints),facilitator_portal.py(4 endpoints) - Coordinator auto-assignment at
payment_locked: ranking by workload, tier, language, availability - Transport vendor directory + TimelineMilestones, CoordinatorNotes, Escalations, CSAT ratings
- 4 models added: Coordinator, CoordinatorAssignment, TransportVendor, TransportBooking
- 21 of 31 gap report items closed; ADR-0019 (GDPR Article 17) accepted, ADR-0020 (HAPI FHIR) deferred
Session 52: EHR Builder Service + WebSocket Streaming + Batch Tracking¶
- EHR Builder Service: incremental rebuild from
layer_state(demographics, medications, conditions, allergies, diagnostics, risk factors) - Layer state field mapping: bridges extracted triage data → FHIR resources
- WebSocket endpoint
/cases/{case_id}/ws: real-time message streaming, chat token delivery, batch progress events - Batch tracking via Redis: atomic INCR counter, completion signals, consolidated follow-up messages
- RLS tenant context via
curaway_servicerole with BYPASSRLS; safe [0] access on FHIR lists - Platform restructuring Wave 1: cost estimate API, financial gate, pre-travel checklist service
- 22 ruff errors fixed to unblock CI
Session 53: Batch Tracking Hardening + Layer State Injection + Intake Gates v2¶
- Batch tracker hardening: URL encoding, TTL, persistent receive task, concurrent sender/receiver (fixes reconnect storms)
- Layer state injection into triage agent: prevents hallucinated file uploads, patient name supersedes account name
- Intake gates v2: empty list = confirmation for meds/allergies, procedure_code assignment hardened
- Conditions deduplication via keyword overlap; fuzzy procedure_code lookup (contains fallback)
- Prompt examples cleaned: removed specific numbers to prevent hallucination
- 15 broad exception catches narrowed to specific types; cross-domain imports reduced (13 → 8 in llm_conversation.py)
Session 54: Prompt Quality + Intake Fixes + Live Monitoring Collation¶
- Intake target: 10 minutes alongside one-question-per-turn rule (restored after quality analysis)
- 5 prompt improvements collated from live monitoring: intent capture (acknowledge procedure), classifier context, question format
- Allergies gate fixed: was blocking intake_complete — agent never asked
- 10-min intake target + allergies routing + output validator abbreviations wired
- Response formatting rules + demo narrative sections 7-8
- Conversation history now loaded before batch orchestrator call; response saved after batch complete
Session 55: P1 Intake Fixes + Clinical Image Analysis + Medical Extractor¶
- P1 intake flow fixes (34 tests added):
- Laterality detection: extracted findings injected into triage agent (prevents fabrication)
- OCR pipeline: skip PyMuPDF for images, tighten validation, signal extraction failure
- JPEG OCR + extractor weight rebalancing: max 20%, financial empty inflation fixed
- Findings now passed to agent; QStash callback enriched with embedding step
- Clinical image analysis pathway: wound photos, X-rays, EXIF stripping (all formats), flag logic, .tif support
- Medical extractor: diagnoses mapped to ICD-10 codes; patient demographics added
- FHIR retry queue via QStash with exponential backoff; findings_incorporated WS event
- GDPR erasure: Neo4j + Qdrant deletion wired; 7 test cases added
Session 56: Langfuse Auto-Trace + LLM Metadata + Token Burn Sync + Alerting¶
- Langfuse auto-trace: every LLM call traced automatically (no handler required); sessionId=case_id, userId=patient_id
- LLM metadata in messages: tier, provider, fallback stored for all chat turns (enables cost tracking + provider audit)
- Token burn sync: PostgreSQL llm_usage table with Langfuse → DB sync job; per-case token tracking endpoints
- Telegram alerts: critical path failures (FHIR retry, GDPR erasure, Neo4j, Qdrant, QStash), LLM fallback notifications
- Voice rules exceptions wrapped; Langfuse rate-limit backoff (429 retry with exponential backoff)
- Prompt dependency graph documented: 5 conflicts identified, resolution plan established
Session 57: LLM Gateway Migration + Definition of Done Formalized¶
- All agents migrated to
llm_gateway.invoke()+astream(); dead code removed from ChatAnthropic references - Definition of Done: exhaustive checklist (ALWAYS + CODE QUALITY + TESTING + DATABASE + LLM + PROMPTS + FEATURE FLAGS + FRONTEND/UI + SECURITY + ANALYTICS + OBSERVABILITY + DOCS + DEPLOYMENT + MULTI-TENANCY + ARCHITECTURE)
- DoD enforced: Before You Start pre-flight + Alembic unique revision ID fix + analytics/PostHog/Grafana split documented
- Model tier guidance: Opus for architecture/compliance, Sonnet for implementation, Haiku for housekeeping
- Multi-tenancy + multilingual + multicurrency gates added; microservice readiness gate added
- Direct Axiom log integration: structured JSON, batched, non-blocking
Session 68: God File Cleanup (9 Files) + Prompt Version Metadata¶
- 9 god files split (87% reduction in max file size):
clinical_context.py→ extraction + FHIR generation modulesgraph_service.py→ driver, provider, clinical, matching sub-modulesintake.py→ triage, findings, gates modulesinternal.py→ OCR, sync, ops sub-routerspublic.py→ provider, treatment, marketing sub-routershealth_checks.py→ focused modulescase_orchestrator.py→ routing + state managementspend_report_service.py→ per-provider modules- Prompt version metadata: recorded in message metadata for rollback capability (enables A/B testing of prompt versions)
- Feature flags: added 4 missing flags to configuration
- Patient ID removed from Telegram alert payloads (GDPR compliance)