Skip to content

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 via POST /api/v1/admin/graph/rebuild.

Significant Changes

  • app/services/graph/provider_graph.pysync_doctor_to_graph function (projects Postgres Doctor rows into Neo4j including procedures, specialties, languages)
  • app/routers/admin_graph.py — new. POST /api/v1/admin/graph/rebuild with graph:rebuild permission
  • app/services/graph/projection_service.py — new. Extracted from provider_graph in audit follow-up (#773)
  • app/routers/admin_flags.pyGET /effective endpoint; AuditLog on identity overrides
  • app/middleware/security_headers.py — CSP relaxed for /docs and /redoc
  • config/feature_flags.yaml — 6 new flags: 5 triage/MSO thresholds + procedure_reqs_from_graph
  • seed_doctors_full.py — backfills 172 doctors into Neo4j
  • Migration j4k5l6m7n8o9_grant_graph_rebuild_super_admin.py — grants graph:rebuild to super_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_NAMES extraction), #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 documents
  • document_review phase 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-checklist endpoint: 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: DocumentChecklistCard rich card + ChecklistRow component with per-requirement status icons
  • Documents tab in right panel now shows requirements-based checklist (not flat file list)
  • document_checklist registered 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_key to 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
  • sendingWithFiles state 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_issues status (from validator) not counted as analyzed → treated as pending
  • Fix: has_issues counts as analyzed for routing, response generation, workflow advancement
  • Stronger document_review LLM 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/stream backed by Redis (zero DB polling per client)
  • Frontend: EventSource listens for new_message events + 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_MATCHING feature 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
  • TenantIsolationViolation raised if tenant_id is 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_orchestrator entry 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_shares table 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_quotes table + Alembic migration; redacted_snapshot column added
  • CaseForwardingService: 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_id in 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: ChatAnthropicllm_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.py router (4 endpoints), mso_portal.py router (6 endpoints)
  • New models: RiskReview, RiskFactor, MSOConsultation
  • Case state machine extended: risk_review_pendingrisk_clearedmso_offeredmso_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_id added to submit_document + request_records calls
  • Phase 2 security hardening: tenant-scoped lookups, patient_id validation, JSONB migration fix
  • Phase 3 full backend shipped: coordinator_portal.py router (15 endpoints), facilitator_portal.py router (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_overdue trigger 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_service role 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 modules
  • graph_service.py → driver, provider, clinical, matching sub-modules
  • intake.py → triage, findings, gates modules
  • internal.py → OCR, sync, ops sub-routers
  • public.py → provider, treatment, marketing sub-routers
  • health_checks.py → focused modules
  • case_orchestrator.py → routing + state management
  • spend_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)