Platform Restructuring Design — Intelligent Triage Engine¶
Status: In progress (brainstorming phase) Date: 2026-04-16 Session: 41 Author: SD + Claude Code Origin: Gap analysis from Dr. Shrikanth meetings (April 2026) — 14 gaps identified against current platform state
Executive Summary¶
Curaway's current platform is a strong agentic pipeline (intake → clinical extraction → matching → forwarding) with 42 providers, 87+ API endpoints, and live patient data flowing. However, mapping against Dr. Shrikanth's clinical intelligence framework reveals 14 gaps that collectively represent a restructuring of the intake-to-coordination pipeline into an intelligent triage engine.
This is not 14 separate features. It is a layered system redesign with a new scoring model (PFS/HSS/FMS), structured intake (5 assessment dimensions), coordinator tooling, and a frontend monorepo supporting multiple stakeholders.
Gap Classification¶
The 14 gaps cluster into four groups:
| Cluster | Gaps | Nature |
|---|---|---|
| A — Intake Intelligence | #1 (PFS/HSS/FMS), #2 (5-Layer Intake), #3 (Intent/Emotional), #4 (Travel Readiness), #5 (Logistics), #6 (Financial) | Revolution — new intake spine |
| B — Coordination & Services | #10 (Pre-Travel Checklist), #11 (Post-Op Manual), #12 (On-Ground Support), #13 (Long-Term Engagement) | Evolution — new features on existing platform |
| C — Provider Trust & Economics | #7 (Consultation Routing), #8 (Provider Reports), #9 (Cost Estimate) | Evolution — new features + new stakeholder views |
| D — Operational Polish | #14 (Channel Preference) | Evolution — enhancement to existing notification system |
Approach: Cluster A gets the revolution treatment (new data model, new agent architecture, new scoring). Clusters B/C/D evolve on top — new features that consume the restructured data.
Part 1: 5-Layer Intake Architecture¶
Layers as dimensions, not a strict sequence¶
The 5 layers are independent assessment dimensions tracked in patient_state. Each has its own completion score. The agent advances layers adaptively, not in a rigid pipeline.
{
"layers": {
"intent_capture": { "status": "complete", "completion": 1.0 },
"medical_status": { "status": "in_progress", "completion": 0.6 },
"travel_readiness": { "status": "not_started", "completion": 0.0 },
"logistics": { "status": "not_started", "completion": 0.0 },
"financial_readiness": { "status": "not_started", "completion": 0.0 }
}
}
Layer definitions¶
| Layer | What it captures | Key outputs |
|---|---|---|
| 1. Intent Capture | Why the patient is here, emotional state, fears, hopes, case type (elective/selective/urgent) | Urgency score, emotional readiness score, case classification |
| 2. Medical Status | Clinical data — diagnoses, reports, labs, comorbidities, medications, allergies | FHIR resources, ICD codes, risk factors, EHR snapshot |
| 3. Travel Readiness | Physical fitness for travel — mobility, oxygen, hospitalization history, escort needs | Transport tier (T1-T4), travel fitness score, medical escort flag |
| 4. Logistics | Passport status, visa requirements, preferred timeline, companion arrangements | Travel risk score, timeline feasibility, visa assistance flag |
| 5. Financial Readiness | Funding source, budget range, insurance status, payment preferences | Patient Pricing Band (PV), budget qualification gate |
Adaptive routing¶
The agent follows a preferred sequence (1 → 2 → 3 → 4 → 5) but adapts to patient behavior:
| Trigger | Behavior |
|---|---|
| Patient uploads medical report first | Layer 2 advances immediately. Agent acknowledges, then circles back to Layer 1. |
| Patient expresses anxiety in first message | Layer 1 captures emotional state on the fly. Agent responds empathetically. |
| Patient asks about cost immediately | Signal bookmarked in Layer 5. Agent captures it, returns after medical/travel established. |
| Urgent case (cancer, trauma) | Compress layers — ask only mandatory questions, skip Layer 1's "hopes" (tone-deaf for urgent). |
Completion gates¶
The state machine enforces two hard rules:
- Matching cannot happen until Layers 1-4 are each ≥ 0.6 completion — replaces the current
intake_complete_v2gate - Financial (Layer 5) must be captured before provider comparison is shown — anti-drop-off rule
Everything else is soft routing — the agent decides based on signals.
What already exists and maps to layers¶
| Layer | Existing code | What's new |
|---|---|---|
| 1. Intent | Nothing | New extractor for emotional signals, case type, aspirations, fears |
| 2. Medical | Clinical Context Agent, chat_extractor, lab_analyzer, risk_assessor, EHR builder | No new agent — reuse everything |
| 3. Travel | Partial (risk_assessor covers comorbidity risks) | New extractor for travel-specific fitness (oxygen, mobility, escort) |
| 4. Logistics | Nothing | New extractor for passport, visa, timeline, preferred dates |
| 5. Financial | Multicurrency exists, no qualification logic | New extractor for funding source, budget range → Patient Pricing Band |
Part 2: Agent Architecture (A3 Model)¶
One Triage Agent + per-layer extractors¶
Decision: Single conversational agent (existing Intake Agent renamed to Triage Agent) with layer-aware prompting. Per-layer extractors pull structured data from each turn.
Rationale: - Conversations cross layers naturally — one agent handles this gracefully - Cost: one LLM call per turn, not five - Voice consistency: one brand voice across the whole journey - Matches existing architecture pattern (LLM handles conversation, specialized services extract structured data)
Conversation LLM (single Triage Agent)
├── Receives full layer state in context
├── Has layer-specific prompt snippets injected per turn
└── Produces patient-facing response
Parallel extraction (after response):
├── Layer 1 extractor (emotional/urgency signals) — NEW
├── Clinical Context Agent — EXISTING, owns Layer 2
├── Layer 3 extractor (travel fitness) — NEW
├── Layer 4 extractor (logistics) — NEW
└── Layer 5 extractor (financial) — NEW
Layer routing logic¶
# Conceptual:
next_layer = choose_next_layer(
patient_state.layers,
preferred_sequence=["intent", "medical", "travel", "logistics", "financial"],
recent_signals=recent_messages,
urgency=patient_state.urgency_score
)
The existing orchestrator's phase routing (identify_procedure, records_first, intake) evolves into layer-aware routing. The records_first path (Session 33 gates_v2) already does soft routing — this formalizes it.
Part 3: Three-Score System (PFS / HSS / FMS)¶
PFS — Patient Fitness Score (0-100)¶
"Is this patient ready for medical travel?"
Computed from Layers 1-4:
| Layer | Input | Contribution |
|---|---|---|
| Intent | Urgency, case type, emotional readiness | Modifier (urgent cases proceed despite lower fitness) |
| Medical | Age, comorbidities, risk_assessor output, lab values | Dominant component |
| Travel | Mobility, oxygen, escort needs → transport tier T1-T4 | Secondary component |
| Logistics | Passport readiness, visa status, timeline feasibility | Modifier (feasibility gate) |
Output: 0-100 score + transport tier + is_blocking flag
Relationship with risk_assessor: PFS consumes risk_assessor output as one input to Layer 2's contribution. Risk_assessor remains authoritative for clinical risk items. PFS is a scorer, not a rule engine — rules live in dedicated modules. This boundary makes future subsumption easy (~1 week of mechanical work) if PFS ever needs to absorb risk logic.
HSS — Hospital Suitability Score (0-100)¶
"Is this hospital right for this patient?"
Computed per provider for a given patient:
| Input | Source | Contribution |
|---|---|---|
| Clinical fit for diagnosis | Existing matching engine v2.1 (graph traversal, OFFERS) | Primary |
| Outcome data | Existing provider success_rate, annual_cases | Primary |
| Accreditation level | Existing HAS_ACCREDITATION | Secondary |
| Facility capability match | ADR-0018 facility readiness score | Secondary |
| Language/cultural fit | Existing language_services, language_concordance | Modifier |
| Cost band alignment with PV | New — from Layer 5 | Modifier (gates out-of-band hospitals) |
Output: 0-100 score per provider + critical gap flags
FMS — Final Matching Score / Conversion Probability (0-1)¶
"Will this match convert?"
| Input | Source |
|---|---|
| PFS | From layer scoring |
| HSS | From provider scoring |
| Historical conversion rate | Learned from feedback_records table |
| Patient preference alignment | Existing preferences data |
| Channel preference match | Gap #14 — modifies outreach approach |
Output: 0-1 conversion probability, used to rank providers + inform coordinator urgency
Relationship to existing matching engine¶
The existing weighted scoring formula (clinical_relevance 0.25, outcome 0.20, semantic 0.10, cost 0.15, travel 0.10, accreditation 0.10, preferences 0.10) becomes the internal implementation of HSS. PFS and FMS are new. The existing engine is not replaced — it's reframed.
Part 4: Frontend Architecture¶
Monorepo with separate apps¶
frontend/
packages/
shared-core/ ← Types, API client, business logic (pure TS)
shared-web/ ← Web UI components (React + DOM)
shared-native/ ← React Native components (future)
patient-app/ ← curaway.ai
coordinator-app/ ← coordinator.curaway.ai
provider-app/ ← provider.curaway.ai (Phase 1)
facilitator-app/ ← facilitator.curaway.ai (Phase 3)
mso-app/ ← mso.curaway.ai (Phase 2)
admin-app/ ← admin.curaway.ai (Phase 0)
mobile-patient/ ← React Native Expo (post-seed)
Rationale: Clean separation per stakeholder, independent deployment, shared component reuse, mobile-ready. Not micro-frontends — each app runs on its own URL, no runtime composition.
Pragmatic phasing: Start with 3 apps (patient, operations, clinical), extract to 7 as scope diverges:
| Phase | Apps |
|---|---|
| Phase 0-1 | patient-app, operations-app (coordinators + facilitators + admin), clinical-app (providers + MSO) |
| Phase 3+ | Extract facilitator-app, mso-app, admin-app when scope diverges |
Patient app changes¶
Progress rail redesign:
✓ About You ← Layer 1
◉ Health Profile ← Layer 2
○ Travel Readiness ← Layer 3
○ Planning ← Layers 4+5 combined
──────────────────────────
○ Finding Matches
○ Compare & Choose
○ Next Steps
- Per-phase completion ring (reuse existing EHR completeness ring pattern)
- Partially filled state (◑) when patient jumps ahead
- Layer transitions not strictly linear — ring fills as data arrives from any turn
Layer summary cards in chat:
Fires when a layer first reaches completion threshold (0.8):
┌──────────────────────────────────────────────┐
│ ✓ Health Profile Complete │
│ │
│ • Bilateral knee osteoarthritis (ICD M17.11) │
│ • Prediabetes (HbA1c 6.3%) │
│ • No blocking risk factors │
│ • 3 of 5 mandatory documents uploaded │
│ │
│ Anything I got wrong? You can correct me │
│ anytime. │
└──────────────────────────────────────────────┘
Rules: - Fire once per layer (high-water mark — no repeat cards) - Always shown (not skippable) — reinforces progress, builds trust - Includes "anything I got wrong?" prompt for error correction
Summary panel redesign:
Patient's live dashboard of what Curaway understands, organized by layer:
ABOUT YOU
Case type: Elective
Primary concern: Mobility limitation
Emotional readiness: Moderate anxiety about outcomes
HEALTH PROFILE
Diagnosis: Bilateral knee osteoarthritis (M17.11)
Comorbidities: Prediabetes (HbA1c 6.3%)
Risk level: Low (no blocking factors)
Documents: 3 of 5 mandatory uploaded
TRAVEL READINESS
Transport tier: T1 — Standard
Fitness: Cleared for travel
Medical escort: Not required
PLANNING
Passport: Valid until 2028
Preferred dates: June–July 2026
Budget range: $6,000–$10,000
Funding: Out-of-pocket
No changes needed: Sidebar, chat input, rich content cards, EHR drawer, document upload flow.
Coordinator app¶
Case queue dashboard: - All assigned cases at a glance, sorted by urgency - Color-coded alerts: red (escalation), amber (deadline), green (on track) - Filterable by case phase, transport tier, destination city - "Next action" — single most important thing to do
Case detail — 4 tabs:
| Tab | Contents |
|---|---|
| Patient Overview | Layer summary with full detail + PFS/HSS/FMS scores + matched provider |
| Timeline & Transport | Journey timeline, transport bookings, vendor assignment with [+ Book] actions |
| Communication | Human-to-human coordinator ↔ patient chat thread |
| Documents & EHR | Shared EHR viewer + document checklist with coordinator actions (flag missing, request upload) |
Vendor management: Searchable directory filtered by city + capabilities + transport tier. Select → fill booking details → create → patient notified.
Escalation panel: Triggered by recovery alerts (pain ≥7, missed check-in). Shows trigger, history, action buttons (call patient, call facility, dispatch transport, contact surgical provider, log resolution).
Coordinator analytics: Active/completed cases, avg escalation response time, CSAT, vendor reliability.
Coordinator access to patient AI chat — Three-tier model¶
| Tier | Access | Gate |
|---|---|---|
| Tier 1: Summary | Layer completion cards + extracted data | Default for all coordinators |
| Tier 2: Full transcript | Read-only AI conversation | Patient consent (coordinator_chat_access) + Flagsmith flag |
| Tier 3: Annotated | Full transcript + flag messages for review | Tier 2 + elevated role (coordinator_senior) |
Audit trail on every coordinator action:
coordinator_audit_log
id: UUID PK
coordinator_id: UUID FK → tenant_members
case_id: UUID FK → cases
action: ENUM('viewed_summary', 'viewed_transcript', 'flagged_message',
'created_booking', 'dispatched_transport', 'sent_message',
'escalated', 'resolved_escalation', 'modified_case')
target_type: VARCHAR(50)
target_id: UUID
metadata: JSONB
ip_address: VARCHAR(45)
user_agent: TEXT
created_at: TIMESTAMPTZ
Stakeholder app matrix¶
| Stakeholder | Unique views | Shared from shared/ | When | App |
|---|---|---|---|---|
| Patient | Conversation UI, progress rail, transport panel, comparison | EHR viewer, doc viewer, rich cards | Now | patient-app |
| Coordinator | Case queue, timeline, vendor selector, escalation | EHR viewer, doc viewer, patient summary | Phase 5 | operations-app |
| Provider | Case inbox, quote builder, redacted records | EHR viewer (redacted), doc viewer | Phase 1 | clinical-app |
| Facilitator | Delegated case view, task list | Patient summary, doc viewer, chat | Phase 3 | operations-app (initially) |
| MSO Doctor | Clinical review workspace, opinion form | EHR viewer (full clinical), doc viewer | Phase 2 | clinical-app (initially) |
| Admin | Tenant dashboard, RBAC, system health | Minimal | Phase 0 | operations-app (initially) |
| Vendor | Booking inbox, availability | Minimal | If marketplace evolves | — |
EHR viewer redaction levels¶
One component, data filtered by API based on role:
| Viewer | Sees | Hidden |
|---|---|---|
| Patient | Everything | Nothing |
| Coordinator | Everything | Nothing (Curaway staff) |
| MSO Doctor | Full clinical | Non-clinical preferences, financial |
| Provider | Clinical + relevant logistics | Identity (until arrival), financial, other quotes |
| Facilitator | Delegated scope only | Anything outside delegation consent |
Part 5: Transport / Coordinator Services¶
Fully designed in separate spec: docs/specs/deferred/coordinator-services-transport-spec.md
Key decisions:
- Coordinator Services Framework with service_type enum (transport first, then translator, companion, ground_staff)
- Hybrid model: scheduled transfers coordinator-assigned, emergency dispatch coordinator-managed
- Transport tiers T1-T4 driven by travel fitness (Layer 3 → PFS)
- Vendor registry (coordinator_vendors) with migration path to full provider type
- Patient sees assigned provider details but doesn't choose
- Coverage in both origin and destination countries
- Repatriation in scope (air ambulance)
Part 6: Gap Integration Map¶
How all 14 gaps connect and depend on each other:
Layer 1 (Intent/Emotional) ──────────────────────┐
Layer 2 (Medical Status) ────────────────────────┤
Layer 3 (Travel Readiness) ──┬───────────────────┼──→ PFS
Layer 4 (Logistics) ─────────┘ │
│
Existing matching engine ────────────────────────┤──→ HSS
Facility capabilities (ADR-0018) ────────────────┤
Layer 5 (Financial / PV) ───────────────────────┤
│
PFS × HSS × historical conversion ──────────────┼──→ FMS
│
Transport (Gap #12) ←── Layer 3 output │
Cost estimate (Gap #9) ←── HSS + transport cost │
Pre-travel checklist (Gap #10) ←── Layers 3+4 │
Post-op manual (Gap #11) ←── transport panel │
Provider reports (Gap #8) ←── HSS + FMS + outcomes │
Consultation routing (Gap #7) ←── PFS + Layer 1 │
Channel preference (Gap #14) ←── FMS modifier │
Long-term engagement (Gap #13) ←── post-case data │
Part 7: Intent Capture Extraction Schema (Gap #3)¶
Extraction approach: infer first, ask explicitly for gaps¶
The Layer 1 extractor reads signals from whatever the patient says in the first 2-3 turns. If specific signals are missing after that, the agent asks targeted follow-up questions.
Extraction schema¶
{
"layer_1_intent": {
"case_type": {
"value": "selective",
"confidence": 0.85,
"source": "patient mentioned doctor recommendation + waitlist"
},
"urgency_score": 0.6,
"emotional_state": {
"readiness": "anxious_but_willing",
"primary_fear": "going_abroad",
"primary_hope": "pain_free_mobility",
"fear_intensity": 0.5,
"hope_intensity": 0.8
},
"decision_stage": {
"value": "comparing_options",
"confidence": 0.9
},
"trigger_event": {
"description": "NHS waitlist 18 months",
"category": "waitlist"
}
}
}
Enums¶
| Field | Values |
|---|---|
| case_type | elective, selective, urgent |
| readiness | ready_and_researched, anxious_but_willing, hesitant_exploring, desperate |
| primary_fear | complications, cost, distance_from_home, language_barrier, quality_of_care, unknown_outcome, travel_fitness, none |
| primary_hope | pain_free_mobility, improved_appearance, survival, quality_of_life, faster_treatment, cost_savings, better_care |
| decision_stage | just_exploring, comparing_options, ready_to_commit, decided_on_destination |
| trigger_category | waitlist, cost_prohibitive, doctor_recommendation, worsening_symptoms, insurance_denial, referral, self_research |
Enums will extend as patient data reveals new patterns.
Urgency score computation¶
| Factor | Weight |
|---|---|
| case_type: urgent = 1.0, selective = 0.6, elective = 0.3 | 0.40 |
| decision_stage: ready_to_commit = 1.0 → just_exploring = 0.25 | 0.25 |
| trigger_category: worsening_symptoms = 1.0, waitlist = 0.7, self_research = 0.3 | 0.25 |
| fear_intensity (inverse — desperate patients score higher urgency) | 0.10 |
How Layer 1 feeds PFS and HSS¶
- PFS: Intent is a modifier (0.15 weight). Urgent cases boost PFS even with lower medical/travel scores (fast-track).
- HSS:
primary_fearadjusts matching weights indirectly — fear ofquality_of_careincreases accreditation weight; fear oflanguage_barrierincreases language concordance weight. - FMS:
hesitant_exploring+just_exploringlowers conversion probability. Coordinator knows to nurture, not push.
Part 8: Financial Readiness Schema (Gap #6)¶
Patient Pricing Band (PV)¶
{
"layer_5_financial": {
"funding_source": "out_of_pocket",
"budget_range": {
"min_usd_cents": 500000,
"max_usd_cents": 1000000,
"flexibility": "soft_ceiling"
},
"insurance": null,
"financial_timeline_pressure": false,
"qualification": "qualified"
}
}
Funding source enums¶
out_of_pocket, insurance_domestic, insurance_international, employer_sponsored, government_program, medical_loan, family_sponsored
Qualification gate¶
| Status | Meaning | Platform behavior |
|---|---|---|
qualified |
Budget overlaps with ≥3 providers | Proceed to matching |
stretch |
Budget overlaps with 1-2 providers only | Agent informs: limited options, offer to adjust range |
mismatched |
No providers in range | Agent redirects: shows typical range for procedure+destination, suggests alternatives |
incomplete |
Insufficient data | Layer below threshold, matching blocked |
Agent conversation design¶
Financial questions come after Layers 1-4 (patient has invested in the process). Agent never asks "what's your budget?" directly. Instead:
"For knee replacement in Turkey, patients typically spend between $6,000 and $12,000 including travel and recovery. Does that range work for you, or should I focus on a different bracket?"
Anchors with market range, patient self-selects.
Conditional: Insurance details¶
If funding_source includes insurance, additional mandatory fields:
- Insurance provider name
- Policy type (domestic / international travel)
- Pre-authorization status (not started / in progress / approved / denied)
Some providers accept specific insurers — affects HSS cost_alignment scoring.
Part 9: Scoring Configuration (Gap #1 — Configurable)¶
All weights, thresholds, and parameters live in config/scoring.yaml with Flagsmith runtime override per key. Same pattern as config/model_registry.yaml.
config/scoring.yaml¶
pfs:
weights:
medical: 0.45
travel: 0.25
logistics: 0.15
intent_modifier: 0.15
medical_penalties:
blocking_factor: 25
high_severity: 10
moderate_severity: 5
missing_mandatory_doc: 5
max_penalty: 75
travel_tier_scores:
T1: 100
T2: 75
T3: 50
T4: 25
logistics_scores:
passport_valid: 40
visa_feasible: 30
timeline_realistic: 30
thresholds:
ready: 80
conditionally_ready: 60
needs_attention: 40
hss:
weights:
clinical_relevance: 0.25
outcome_score: 0.20
semantic_match: 0.10
cost_alignment: 0.15
travel_score: 0.10
accreditation: 0.10
preferences: 0.05
facility_readiness: 0.05
cost_alignment:
soft_ceiling_multiplier: 1.2
soft_ceiling_score: 0.5
outside_range_score: 0.0
facility_readiness:
critical_gap_penalty: 0.15
fms:
weights:
pfs: 0.30
hss: 0.35
preference_alignment: 0.15
historical_conversion: 0.20
bias: -0.5
default_historical_conversion: 0.5
thresholds:
high_conversion: 0.7
moderate: 0.4
low: 0.1
layer_completion:
matching_threshold: 0.6
summary_card_threshold: 0.8
financial_required_before: "provider_comparison"
Each top-level key (pfs, hss, fms, layer_completion) is also a Flagsmith JSON flag. Code loads YAML defaults, Flagsmith overrides at runtime. Enables A/B testing of scoring weights without deploys.
PFS formula¶
PFS = (medical_component × 0.45) + (travel_component × 0.25)
+ (logistics_component × 0.15) + (intent_modifier × 0.15)
medical_component (0-100):
base = 100
- (blocking factors × 25 each, capped at 75)
- (high severity × 10 each)
- (moderate severity × 5 each)
- (missing mandatory documents × 5 each)
travel_component (0-100):
T1 = 100, T2 = 75, T3 = 50, T4 = 25
logistics_component (0-100):
passport_valid = 40, visa_feasible = 30, timeline_realistic = 30
intent_modifier (0-100):
urgency_score × 100
Urgent cases boost PFS by up to 15 points even with lower medical/travel
HSS formula¶
Existing matching engine v2.1 reframed:
HSS = (clinical_relevance × 0.25) + (outcome_score × 0.20) + (semantic_match × 0.10)
+ (cost_alignment × 0.15) + (travel_score × 0.10) + (accreditation × 0.10)
+ (preferences × 0.05) + (facility_readiness × 0.05)
cost_alignment: gates against Patient Pricing Band
Within PV range = full score
Within 120% of PV max (soft_ceiling) = 0.5
Outside PV = 0 (filtered unless no alternatives)
facility_readiness: from ADR-0018
Critical gap penalty: -0.15 on total HSS + patient-facing note
FMS formula¶
FMS = sigmoid(w1 × PFS/100 + w2 × HSS/100 + w3 × preference_alignment
+ w4 × historical_conversion + bias)
Initial weights: w1=0.30, w2=0.35, w3=0.15, w4=0.20, bias=-0.5
Default historical_conversion: 0.5 (no data yet — becomes data moat as feedback accumulates)
Relationship with existing matching engine¶
The existing weighted scoring formula becomes the internal implementation of HSS. PFS and FMS are new. The existing engine is not replaced — it is reframed.
Relationship with risk_assessor¶
PFS consumes risk_assessor output as one input to the medical component. Risk_assessor remains authoritative for clinical risk items. PFS is a scorer, not a rule engine — rules live in dedicated modules. Future subsumption (~1 week effort) is enabled by keeping these as separate pure functions with a clean interface.
Part 10: Layer Completion Criteria (Gap #2)¶
Completion = mandatory signals captured / total mandatory signals.
Layer 1 — Intent Capture¶
| Signal | Mandatory | Weight |
|---|---|---|
| Case type (elective/selective/urgent) | Yes | 0.30 |
| At least one fear or concern | Yes | 0.25 |
| At least one hope or goal | Yes | 0.25 |
| Decision stage | No | 0.10 |
| Trigger event | No | 0.10 |
Complete at 0.80 (case_type + fear + hope).
Layer 2 — Medical Status¶
| Signal | Mandatory | Weight |
|---|---|---|
| Primary diagnosis identified | Yes | 0.20 |
| At least one document uploaded + analyzed | Yes | 0.20 |
| Medications confirmed (or "none") | Yes | 0.15 |
| Allergies confirmed (or "none") | Yes | 0.10 |
| Age captured | Yes | 0.10 |
| Comorbidities assessed | No | 0.10 |
| Risk assessment complete | No | 0.10 |
| Gender captured | No | 0.05 |
Complete at 0.75 (diagnosis + document + meds + allergies + age). Maps closely to existing intake_complete_v2 gate.
Layer 3 — Travel Readiness¶
| Signal | Mandatory | Weight |
|---|---|---|
| Mobility status | Yes | 0.30 |
| Oxygen dependency | Yes | 0.20 |
| Recent hospitalization (30 days) | Yes | 0.15 |
| Transport tier assigned | Auto-computed | 0.20 |
| Companion traveling | No | 0.15 |
Complete at 0.65 (mobility + oxygen + hospitalization → transport tier auto-computes). Most patients (T1) complete this in one turn.
Layer 4 — Logistics¶
| Signal | Mandatory | Weight |
|---|---|---|
| Country of residence | Yes | 0.25 |
| Passport status | Yes | 0.25 |
| Preferred travel timeline | Yes | 0.25 |
| Visa awareness | No — auto-derived from country pair | 0.15 |
| Companion arrangements | No | 0.10 |
Complete at 0.75 (country + passport + timeline). Country may already be captured in Layer 2 — if so, Layer 4 starts at 0.25.
Layer 5 — Financial Readiness¶
| Signal | Mandatory | Weight |
|---|---|---|
| Funding source | Yes | 0.35 |
| Budget range (min-max) | Yes | 0.35 |
| Budget flexibility | No | 0.15 |
| Insurance details | Conditional (if insurance) | 0.15 |
Complete at 0.70 (funding source + budget range). If funding_source includes insurance, insurance details become mandatory.
Part 11: PFS Remediation Behavior¶
PFS recalculates on every turn that adds layer data. Agent behavior adapts based on the current PFS band.
PFS 80-100: Ready¶
Proceed to matching immediately. No remediation needed.
PFS 60-79: Conditionally ready¶
Matching proceeds but agent flags gaps and coordinator is notified.
Agent behavior:
"I've found some strong matches for you. Before we look at them, I want to flag a couple of things that could affect your journey: • Your passport expires in 3 months — some visa processes take 20-25 days • You mentioned occasional breathing difficulty — confirming travel clearance with your doctor would be wise
Would you like to see the matches now, or address these first?"
Patient decides. Coordinator sees: "PFS 72 — passport timeline tight, travel fitness unconfirmed."
PFS 40-59: Needs attention¶
Matching is blocked. Agent enters focused remediation loop.
Agent behavior:
"There are a few things we need to sort out before I can find the right hospitals: 1. ⚠️ Your HbA1c is 9.2% — most hospitals require below 8% 2. ⚠️ No medical documents uploaded yet
Let's work through these. Would you like to start with uploading your records?"
Remediation loop: 1. Agent identifies blocking gaps, presents prioritized list 2. Asks patient to address one at a time 3. Suggests concrete actions per gap type: - High HbA1c → "Your local doctor can help. Upload updated results when ready." - Missing documents → "Most useful would be your latest X-ray or MRI." - Expired passport → "Renewal takes 2-6 weeks. We can continue in parallel." - Travel fitness concern → "Ask your doctor for a travel fitness certificate." 4. After each turn, PFS recalculates 5. If PFS crosses 60 → offer matching 6. If patient disengages → intake reminder notification (24h cooldown, existing system)
The agent never dead-ends — every blocking gap gets a concrete next step.
PFS 0-39: Not ready¶
Matching not available. Agent is honest but supportive.
Agent behavior:
"I want to be straightforward. Based on what we've discussed, traveling for surgery right now may not be the safest option: • Your INR is 1.8 — bleeding risk that needs resolution • You were hospitalized last week — surgeons want 4-6 weeks of stability
This doesn't mean surgery abroad isn't an option — the timing needs to be right. I'll save everything so you don't start over."
Key behaviors: - No matching at all - All layer data persists for return visits - Email summary option (patient takes to local doctor) - Coordinator notified for follow-up call in 4-6 weeks - No nagging reminders — patient needs medical stabilization, not nudges
Re-evaluation cycle¶
PFS is not computed once — it recalculates on every data-changing turn:
Turn 12: PFS 52 (HbA1c blocking)
Turn 15: Patient uploads new HbA1c of 7.8%
Turn 15: PFS recalculates → 68
Agent: "Great news — your updated HbA1c is within range.
I can now start finding matches. Ready?"
No manual intervention needed. Agent detects threshold crossings automatically.
Coordinator visibility across all bands¶
Coordinator case queue shows PFS band for every case:
CRW-2026-00247 Aisha M. TKR · Istanbul PFS: 78 ● Conditionally ready
Gaps: passport timeline tight
CRW-2026-00251 James R. CABG · Chennai PFS: 48 ● Needs attention
Blocking: HbA1c 9.2%, no documents
CRW-2026-00255 Wei L. Bariatric · Bangkok PFS: 32 ● Not ready
Blocking: INR 1.8, recent hospitalization
Next check-in: May 15 (6 weeks post-discharge)
Coordinator can intervene at any band — call patient, offer help, adjust timeline. Platform handles common path automatically; coordinator adds human touch when it matters.
Part 12: Travel Fitness Questionnaire & Scoring (Gap #4)¶
Two-track assessment¶
| Track | When | Questions |
|---|---|---|
| Quick screen (3 questions) | Always | Mobility, oxygen, recent hospitalization |
| Extended assessment (5+ questions) | If quick screen flags risk | Specific conditions, episode frequency, doctor's travel advice, escort preference |
Quick screen: "Can you walk unassisted or do you use a wheelchair? Any oxygen or breathing support? Have you been hospitalized in the last month?"
All clear → T1, Layer 3 complete in one turn.
Any flag → extended questions probe specifics.
Scoring algorithm¶
| Factor | Score range | T1 | T2 | T3 | T4 |
|---|---|---|---|---|---|
| Mobility | 0-30 | Walking unaided | Wheelchair for distance | Full wheelchair | Bedridden |
| Oxygen | 0-25 | None | — | Intermittent | Continuous |
| Hospitalization | 0-20 | None in 30 days | — | Within 30 days | Within 7 days |
| Comorbidity load | 0-15 | Low | — | High severity | Multiple blocking |
| Doctor travel advice | 0-10 | Cleared / not asked | — | Advised caution | Advised against |
Tier assignment¶
travel_fitness_score = sum of all factors (0-100)
0-20: T1 — Standard
21-45: T2 — Assisted
46-70: T3 — Medical
71-100: T4 — Critical
Auto-override rules (regardless of score)¶
- Continuous oxygen → minimum T3
- Bedridden → T4
- Doctor advised against travel → T4 + agent flags strongly
- Hospitalized within 7 days → T4
All configurable in config/scoring.yaml under travel_fitness key.
Part 13: Logistics Layer Schema (Gap #5)¶
Data schema¶
{
"layer_4_logistics": {
"country_of_residence": "GB",
"passport": {
"status": "valid",
"expiry_date": "2028-03-15",
"months_remaining": 23
},
"visa": {
"required": true,
"status": "not_started",
"estimated_processing_days": 15,
"auto_derived": true
},
"timeline": {
"preferred_start": "2026-06",
"preferred_end": "2026-07",
"flexibility": "flexible_within_month",
"feasibility": "feasible"
},
"companion": {
"traveling_with": true,
"relationship": "spouse",
"companion_visa_needed": true
},
"travel_risk_score": 0.2
}
}
Visa auto-derivation¶
Derived from country pair lookup, not patient questions:
Reference table covers all 8 destination countries. Agent informs rather than asks:
"Since you're traveling from the UK to Turkey, you'll need an e-Visa — it's online and takes about a day."
Timeline feasibility¶
Checks preferred timeline against lead times:
| Factor | Minimum lead time |
|---|---|
| Passport renewal (if expired) | 2-6 weeks |
| Visa processing | From lookup table |
| Provider quote turnaround | 5-7 days |
| Pre-op medical prep (if PFS flags) | 4-8 weeks |
| Coordinator booking | 1-2 weeks |
feasible: preferred_start > today + sum(lead_times)
tight: within 1 week of cutoff
infeasible: preferred_start < today + sum(lead_times)
If infeasible, agent suggests adjusted timeline.
Travel risk score¶
travel_risk = (passport_risk × 0.35) + (visa_risk × 0.30) + (timeline_risk × 0.35)
passport_risk: expired = 1.0, <3 months = 0.6, valid = 0.0
visa_risk: not_started + long processing = 0.8, in_progress = 0.4, obtained/not_needed = 0.0
timeline_risk: infeasible = 1.0, tight = 0.5, feasible = 0.0
Part 14: Consultation Routing (Gap #7)¶
Three consultation types¶
| Type | Purpose | Who delivers |
|---|---|---|
| MTC (Medical Travel Consultation) | Non-medical triage — is patient a good candidate? | Automatable (AI + coordinator) |
| Teleconsultation | First medical opinion for vague symptoms | Doctor via video |
| MSO (Medical Second Opinion) | Validates confirmed diagnosis | Specialist via video |
Routing logic¶
| Layer 1 signals | Route to |
|---|---|
just_exploring + no diagnosis |
MTC |
just_exploring + vague symptoms |
Teleconsultation |
comparing_options + confirmed diagnosis |
MSO (optional) |
ready_to_commit + confirmed diagnosis |
Skip — proceed to matching |
MTC is largely automated — the Layer 1-4 intake process IS the medical travel consultation. Patients completing layers with PFS ≥ 60 have effectively passed MTC.
Schema¶
{
"consultation_routing": {
"recommended_type": "mso",
"confidence": 0.8,
"reasoning": "Confirmed TKR diagnosis, comparing options",
"patient_accepted": null,
"scheduled": false
}
}
Routing is a recommendation, not a gate. Patient can skip.
Part 15: Cost Estimate Breakdown (Gap #9)¶
Estimate structure¶
Curaway produces the cost estimate (not the hospital). Full breakdown justifies service fee and prevents direct booking.
| Category | Line items | Source |
|---|---|---|
| Medical | Procedure, hospital stay, surgeon, anesthesia, implants, follow-ups | Provider quote |
| Travel | Flights, accommodation, ground transport, escort (if T2+), visa | Platform estimates + transport bookings |
| Recovery | Recovery facility, nursing, physiotherapy | Recovery provider quote |
| Curaway service | Coordination fee | Platform fee schedule |
| Contingency | Recommended buffer (configurable %) | Percentage of total |
Patient-facing display¶
COST ESTIMATE — TKR Bilateral · Acibadem Maslak, Istanbul
Medical $7,200 - $8,500
Procedure + hospital (5 nights) $6,500 - $7,500
Implants $500 - $700
Post-op follow-ups (2) $200 - $300
Travel $1,200 - $1,800
Flights (London → Istanbul return × 2) $600 - $900
Hotel (3 nights) $300 - $450
Ground transport (T1) $150 - $200
Visa (e-Visa) $50
Recovery (optional) $1,500 - $2,000
Curaway Coordination $XXX
Contingency (10%) $1,000 - $1,300
─────────────────
ESTIMATED TOTAL $10,900 - $13,600
Curaway fee model¶
Per-provider contract determines model:
fee_models:
percentage:
default_rate: 0.15
min_fee_usd_cents: 50000
max_fee_usd_cents: 500000
tiered:
brackets:
- max_medical_usd_cents: 500000 # Under $5K
fee_usd_cents: 75000 # $750
- max_medical_usd_cents: 1500000 # $5K-$15K
fee_usd_cents: 150000 # $1,500
- max_medical_usd_cents: null # $15K+
fee_usd_cents: 250000 # $2,500
When generated¶
After provider quotes arrive (Phase 1 quoting flow), before patient commits. The estimate is the decision-making artifact.
Budget comparison¶
Estimate includes comparison against Patient Pricing Band: - Within budget → green indicator - Slightly over → amber with options to adjust - Significantly over → flag with alternative destinations
Part 16: Post-Seed Features (Gaps #8, #10, #11, #13, #14)¶
Gap #8 — Provider Performance Reports¶
Weekly reports to hospitals building bilateral trust.
| Data point | Source |
|---|---|
| Leads sent | case_shares table |
| Response time (avg/min/max) | provider_quotes timestamps |
| Quote-to-selection conversion | cases selected / quoted |
| Common rejection reasons | feedback_records |
| Patient demographics (aggregated) | Layer 1-2 data |
| Comparison to platform average | Aggregated |
Format: PDF via QStash cron + email via Resend. Dashboard in provider-app.
Gap #10 — Pre-Travel Checklist¶
Auto-generated from Layer 3+4 + provider requirements.
Medical section: Records compilation, hospital invitation letter, consent forms, travel fitness certificate (T2+), medication list for customs.
Travel section: Passport check, visa application, flights, hotel, transport confirmation, travel insurance, companion arrangements.
Each item has status (done/pending/not needed), deadline, and action button. Rendered as rich card + persistent checklist in transport panel.
Gap #11 — Post-Op Manual¶
Per-procedure + per-patient, generated after surgery.
Sections: recovery timeline (day-by-day), medication schedule, warning signs, complication routing (which specialist for which complication), follow-up schedule, emergency contacts.
Generated by LLM using procedure template + patient EHR. Reviewed by coordinator before release.
Gap #13 — Long-Term Engagement¶
Deferred entirely. Subscription model (annual second opinions, priority teleconsultations, health monitoring) depends on post-procedure outcome data and business model validation.
Gap #14 — Channel Preference Detection¶
| Signal | Detection |
|---|---|
| Initiates via WhatsApp | Auto-set WhatsApp |
| Uses voice input | Flag voice preference |
| European patient | Default email |
| Middle East patient | Default WhatsApp |
| Explicit ask | "How would you prefer us to reach you?" |
Stored on patient profile. Notification system routes through preferred channel. FMS modifier: channel match improves conversion probability.
All Gaps — Resolution Status¶
| Gap | Status | Where documented |
|---|---|---|
| #1 — PFS/HSS/FMS | ✅ Complete | Part 3, Part 9 |
| #2 — 5-Layer Intake | ✅ Complete | Part 1, Part 10 |
| #3 — Intent/Emotional | ✅ Complete | Part 7 |
| #4 — Travel Readiness | ✅ Complete | Part 12 |
| #5 — Logistics | ✅ Complete | Part 13 |
| #6 — Financial Readiness | ✅ Complete | Part 8 |
| #7 — Consultation Routing | ✅ Complete | Part 14 |
| #8 — Provider Reports | ✅ Complete (light) | Part 16 |
| #9 — Cost Estimate | ✅ Complete | Part 15 |
| #10 — Pre-Travel Checklist | ✅ Complete (light) | Part 16 |
| #11 — Post-Op Manual | ✅ Complete (light) | Part 16 |
| #12 — On-Ground Support | ✅ Complete | Separate spec: coordinator-services-transport-spec.md |
| #13 — Long-Term Engagement | ✅ Deferred | Part 16 |
| #14 — Channel Preference | ✅ Complete (light) | Part 16 |
Edge Cases¶
| Scenario | Handling |
|---|---|
| Patient completes Layer 5 before Layer 1 | Layers tracked independently. Signal bookmarked. Agent circles back. No blocking. |
| Layer 2 data contradicts Layer 1 emotional state (patient calm but high-risk medical) | PFS weights medical over emotional. Agent flags the risk gently. |
| Patient refuses to answer Layer 1 questions | Layer 1 defaults to "neutral" emotional state. Does not block progression. Agent notes skip. |
| Travel fitness assessment changes after initial transport booking | Coordinator cancels future bookings at old tier, rebooks at new tier. Completed legs unaffected. |
| PFS drops below matching threshold mid-intake (new comorbidity discovered) | Matching blocked. Agent explains what's needed. Coordinator notified if case was already advanced. |
| Financial qualification gates out all matched providers | Agent explains budget mismatch. Offers options: adjust budget, different destination, different procedure timing. |
| Multiple layers complete on same turn | Multiple summary cards stacked in chat. Rare but handled. |
| Patient corrects data after layer summary card | Layer completion may drop temporarily. No re-fire of summary card. Summary panel updates live. |
| Coordinator views transcript without patient consent | Tier 1 (summary only) is default. Tier 2 requires explicit consent record. API enforces gate. |
| Layer extractor fails (LLM timeout) | Non-blocking. Layer completion stays at previous value. Retried on next turn. |
| Patient's visa auto-derivation is wrong (dual citizenship) | Agent asks to confirm: "I see you may need an e-Visa for Turkey. Is that correct, or do you hold another passport?" Patient corrects; visa status updated. |
| Timeline infeasible but patient insists | Agent explains risks. If patient proceeds, coordinator flagged. Case proceeds with timeline_risk: 1.0 feeding PFS. |
| Provider quote exceeds patient PV significantly | Cost estimate shows mismatch. Agent offers: adjust budget, different provider, different destination, or staged approach. |
| Patient is MTC candidate but asks for MSO directly | Respect patient choice. Route to MSO. Log the skip for analytics. |
| Consultation routing confidence low | Agent presents options to patient: "Based on what you've told me, a teleconsultation might help clarify your diagnosis. But if you'd prefer to go straight to comparing hospitals, we can do that too." |
| Cost estimate changes after initial generation (new quote, updated transport tier) | Re-generate estimate. Notify patient with diff: "Updated estimate: travel costs increased by $200 due to medical escort requirement." |
| Channel preference changes mid-journey | Update profile. All future notifications route through new channel. No retroactive changes. |
Implementation Phasing¶
This restructuring maps to ADR-0018's existing phase structure:
| ADR-0018 Phase | Restructuring scope | New effort |
|---|---|---|
| Phase 0: Foundation | Monorepo setup, shared component extraction, coordinator_audit_log | +1 week |
| Phase 1: Provider Flow | Provider app (clinical-app), cost estimate integration | +1 week |
| Phase 2: Risk + MSO | Consultation routing (Gap #7) | Included |
| Phase 3: Facilitators + Coordinators | Operations-app, coordinator tooling | +2 weeks |
| Phase 5: Coordination Lifecycle | Timeline manager, transport integration | +1 week |
| New: Intake Restructuring | 5-layer intake, triage agent, PFS/HSS/FMS, per-layer extractors | 3-4 weeks |
Total new effort: ~8-9 weeks on top of existing ADR-0018 phases.
Recommended sequence: Intake restructuring first (it's demo-critical), then Phase 0 monorepo setup, then remaining phases in ADR-0018 order.
Part 17: LangGraph Runtime Integration¶
Decision: Adopt LangGraph as runtime, not full Deep Agents harness¶
Deep Agents (LangChain's opinionated harness, July 2025) is built for coding-agent use cases (virtual filesystem, todo planning). Curaway's use case is conversational clinical triage — we need the graph infrastructure, not the coding-agent scaffolding.
Adopt:
- LangGraph compiled graph for Triage Agent
- LangGraph checkpointing (AsyncPostgresSaver → Railway PostgreSQL)
- LangGraph parallel sub-nodes (map-reduce for extractors)
- LangGraph interrupt() for coordinator handoff at PFS thresholds
- LangGraph native streaming (replaces custom SSE)
- LangGraph production middleware (retry with backoff, per-node timeouts)
Skip:
- Deep Agents virtual filesystem — not relevant
- Deep Agents write_todos planning tool — not relevant
- Deep Agents task tool for child agents — LangGraph sub-nodes are sufficient
A3 architecture expressed as LangGraph¶
Supervisor Node: Triage Agent (create_react_agent)
├── tools: choose_next_layer(), generate_response()
├── parallel sub-nodes (map-reduce):
│ ├── intent_extractor (structured output)
│ ├── clinical_context_agent (existing, refactored as node)
│ ├── travel_extractor (structured output)
│ ├── logistics_extractor (structured output)
│ └── financial_extractor (structured output)
├── code nodes:
│ ├── pfs_scorer (pure function — deterministic)
│ ├── hss_scorer (pure function — deterministic)
│ ├── fms_scorer (pure function — deterministic)
│ └── route_by_pfs (conditional edge — deterministic)
├── interrupt nodes:
│ ├── coordinator_handoff (PFS < 40)
│ └── matching_gate (PFS >= 60 + layers >= threshold)
└── state: patient_state TypedDict (layers, scores, transport_tier)
Deterministic behavior guarantees¶
LLMs are non-deterministic. The system around them is fully deterministic.
Deterministic (code — no LLM involved): - Graph topology (compile-time edges) - PFS/HSS/FMS scoring (pure functions, config/scoring.yaml) - Transport tier assignment (rule-based, auto-overrides) - Matching threshold gates (configurable thresholds) - Layer completion scoring (weighted sum) - Visa auto-derivation (lookup table) - Timeline feasibility (arithmetic) - Routing after PFS evaluation (conditional edges)
Non-deterministic (LLM — flexibility is a feature): - Triage Agent's conversational response (tone, wording) - Triage Agent's layer routing choice (which question next) - Extractor signal identification (did the patient express fear?) - Confidence scores on extracted signals
Key principle: LLMs handle conversation and extraction (where flexibility is a feature). Code handles scoring, routing, and gates (where predictability is mandatory).
Traceability¶
Every step of every patient's journey is reconstructable.
LangGraph checkpointing provides: - Full state snapshot after every node execution - Time-travel debugging (replay any turn) - Resume-from-failure (patient resumes from last successful node)
Integration with existing Langfuse: - LangGraph native Langfuse callback handler traces every LLM call - Langfuse shows: why the LLM said this (prompt, completion, model, tokens) - LangGraph checkpoint shows: what the system state was when it said this
Together: "At turn 14, patient state was X, PFS was 78, agent chose to ask about travel because Layer 3 was at 0.0, response generated by claude-sonnet-4-6 with this prompt."
Audit tables¶
Three new audit tables for healthcare compliance:
graph_node_audit_log — every graph node execution:
id, case_id, turn_number, node_name, node_type (llm/extractor/scorer/router),
input_hash (SHA-256), output_hash, state_before (JSONB), state_after (JSONB),
decision_made, decision_reason, model_used, duration_ms, created_at
scoring_audit_log — every PFS/HSS/FMS computation:
id, case_id, score_type (pfs/hss/fms), score_value, config_version (hash of scoring.yaml),
inputs (JSONB), component_breakdown (JSONB), threshold_crossed, threshold_direction,
previous_score, created_at
extraction_audit_log — every extractor output:
id, case_id, turn_number, layer (intent/medical/travel/logistics/financial),
extracted_signals (JSONB), confidence_scores (JSONB), completion_before,
completion_after, model_used, input_text, created_at
Tamper detection: input_hash and output_hash in graph_node_audit_log create a chain. Each turn's input_hash must match the previous turn's output_hash. If state is modified retroactively, the chain breaks.
Prompt abstraction compatibility¶
The existing prompt abstraction system (app/services/prompt_loader.py, config/prompts/) is fully compatible. Each LangGraph node consumes prompts via the same load_prompt() API.
Phase contexts → layer contexts:
config/prompts/
layer_contexts/ ← NEW (replaces phase_contexts for v3)
intent_capture.yaml
medical_status.yaml
travel_readiness.yaml
logistics.yaml
financial_readiness.yaml
remediation.yaml
multi_layer.yaml
phase_contexts/v2/ ← KEPT for v2 rollback
New function in prompt_loader.py (~50 lines):
Same pattern as load_phase_context() — same YAML structure, same caching, same locale fallback. Flagsmith prompt_version: v3 activates layer-aware prompts. v2 keeps working as fallback.
Caching improves: Layer contexts are more stable than phase contexts (patient stays in same layer for multiple turns). Higher cache hit rate.
New YAML files needed: 4 base extractors + 4 example files + 7 layer contexts = ~15 files.
Net new code in prompt_loader.py: ~50 lines for load_layer_context(). Existing load_prompt(), cached_system_message(), A/B variant support, locale fallback — all unchanged.
Implementation effort¶
| Component | Effort |
|---|---|
| Triage Agent as LangGraph graph | 1 week |
| Extractors as parallel sub-nodes | 1 week |
| LangGraph checkpointing → PostgreSQL | 2-3 days |
| Langfuse integration with LangGraph | 1 day |
| Audit tables (3 new) + Alembic migrations | 2-3 days |
| Hash chain integrity | 1 day |
interrupt() at PFS thresholds |
1 day |
| SSE streaming migration | 2-3 days |
| Prompt abstraction: layer contexts + loader | 2-3 days |
| Total | ~3-4 weeks |
This overlaps significantly with the "Intake Restructuring" phase — they are the same work.