diff --git a/ivr routing system.txt b/ivr routing system.txt index 11414a1..e2d8b82 100644 --- a/ivr routing system.txt +++ b/ivr routing system.txt @@ -6,6 +6,28 @@ VetCan Studio is an AI operations layer and control surface for clinic workflows Current client: Marijuana Express MD. +## Implementation-Truth Route Matrix + +This matrix reflects the current `api/src/routes/voice.ts` behavior and the focused voice regression tests. It is evidence for Studio/demo packaging, not a request to alter runtime behavior. + +| Route | Entry trigger | Runtime behavior | Must not do | Staff fallback | Payment/Acuity behavior | Evidence | +| --- | --- | --- | --- | --- | --- | --- | +| Main menu | Inbound `/api/voice/inbound` or IVR replay via `*`/`#` | Plays the RingCentral-parity Marijuana Express MD menu: Press 1 booking, Press 2 annual state-card help, Press 3 other questions. | Must not advertise Press 4 or public reschedule. Must not present itself as medical advice. | No selection replays menu, then callback/staff paths handle low signal. | No payment capture or Acuity mutation at menu. | `voiceInboundReceptionist.test.ts`: exact menu test asserts no Press 4 and no reschedule. | +| Press 1 | DTMF 1 or supported booking speech | Starts booking lane for seven-month Renewal TELE or new-patient card scheduling; can offer live openings, collect name/phone/email, confirm booking details, and create booking drafts if live booking cannot complete. | Must not collapse annual state/MMU card renewal into Press 1. Must not replay the main IVR inside the booking flow. | Booking draft callback is created when availability/provider/payment path cannot complete safely; staff finalizes. | Renewal TELE and new-patient booking can create Acuity appointments when provider/runtime supports it. Payment prompts are limited to proven payment paths; otherwise staff or secure-link follow-up handles payment. | `voiceInboundReceptionist.test.ts`, `voiceBookingFlow.smoke.test.ts`, `voiceNewPatientScript.smoke.test.ts`, `voicePaymentCapture.test.ts`. | +| Press 2 | DTMF 2 or annual/state/MMU card language | Explains the annual Florida MMU/state card is separate from the seven-month doctor recommendation, then collects full name and callback phone for staff follow-up. Ambiguous renewal language gets one clarification; explicit seven-month doctor renewal redirects to Renewal TELE. | Must not quote new-patient/veteran pricing, start payment capture, or treat annual state card help as Renewal TELE unless the caller explicitly says seven-month doctor recommendation. | Creates a pending voice callback with `source_flow=annual_state_card_ivr`, `renewal_type=annual_state_card`, and `press_lane=2`; medical questions go to staff/doctor guardrail. | No payment capture. No Acuity booking or mutation. | `voiceInboundReceptionist.test.ts`: Press 2 separation, clarification, redirect, and medical-guardrail tests. `voicePaymentCapture.test.ts`: no payment capture for Press 2. | +| Press 3 business-hours | DTMF 3 while business hours and staff handoff is configured | Announces transfer and dials the configured staff line for general questions. Explicit reschedule/cancellation speech is intercepted before generic handoff. | Must not run after-hours deterministic triage while open. Must not collect payment details. | If staff phone/config is missing or transfer unavailable, moves into callback capture with `businessHoursStatus=open`. | No payment capture. No Acuity mutation. | `voiceInboundReceptionist.test.ts`: digit 3 to live staff handoff and general non-reschedule handoff. `voiceStaffHandoff.test.ts`: open-hours fallback metadata. | +| Press 3 after-hours | DTMF 3 while outside business hours, then submenu DTMF or speech | Offers bounded deterministic triage only: scheduling/new patient to Press 1, hours/location operational answer, callback capture, seven-month renewal to Renewal TELE, annual state card to Press 2, veteran questions to staff callback, medical questions to staff/doctor callback, explicit reschedule/cancellation to hidden staff-controlled lanes. | Must not claim live GPT/RAG, provide medical advice, collect payment through Press 3, or mutate Acuity. | Unknown, medical, veteran, max-attempt, and callback intents route to callback capture with `businessHoursStatus=closed`. | No payment capture through Press 3. No Acuity mutation through Press 3. | `voiceInboundReceptionist.test.ts`: after-hours classifier coverage for renewal, state card, new patient, veteran, what-to-bring, pricing, medical, reschedule, cancellation, and mixed cancel/reschedule. `voiceStaffHandoff.test.ts`: after-hours callback metadata. | +| Hidden reschedule | Explicit reschedule intent from Press 3/general speech, symptom-backed appointment-change speech, or unadvertised DTMF 4 | Starts `/api/voice/reschedule`, looks up the caller by caller ID or provided phone/name/email, captures current appointment context where found, asks for preferred new day/time, records staff action required, and discloses the 24-hour/$50 office-confirmed policy. | Must not advertise as public menu option. Must not say the appointment moved unless the disabled self-service flag is explicitly enabled and succeeds. Must not treat a medical symptom reason as medical advice when the caller is asking to move an appointment. | Default path creates a pending reschedule callback and tells caller staff will confirm the change. | Default public behavior does not mutate Acuity. Self-service reschedule code exists only behind `ENABLE_PUBLIC_SELF_SERVICE_RESCHEDULE=true`; leave disabled unless owner-approved. No payment capture. | `voiceInboundReceptionist.test.ts`: hidden lane and symptom-backed reschedule tests. `voiceRescheduleLane.test.ts`: lookup/fallback/request capture behavior. | +| Cancellation | Explicit cancellation intent without reschedule intent from Press 3/general speech or after-hours classifier | Starts hidden cancellation intake at `/api/voice/reschedule?stage=cancel_lookup`, captures cancellation request and phone, creates callback with cancellation request type/scenario, and tells caller the appointment is not canceled yet. | Must not ask for a preferred new day/time. Must not say cancellation is complete. Must not mutate Acuity. Mixed "cancel and reschedule" stays on reschedule priority. | Creates pending cancellation callback with `staff_action_required=confirm_cancellation`; staff confirms before anything is canceled. | No payment capture. No Acuity cancellation or mutation. | `voiceInboundReceptionist.test.ts`: pure cancellation, symptom-backed cancellation, and mixed cancel/reschedule priority tests. | +| Veteran branch | New-patient paid path after full-pay decline and deposit decline, then veteran yes/prior-card/price/medical responses | Clean veteran yes reads the Veterans Cannabis Care callback script, including Casselberry, qualifying Florida resident Veterans, first-time-patient-only limitation, in-person initial appointment, limited availability, callback order, and full name/phone/best callback time collection. Prior/lapsed/existing-card, price, and medical uncertainty go to staff callback wording. | Must not guarantee eligibility, event date, appointment availability, funding, or a paid veteran alternative price. Must not reuse Renewal TELE veteran pricing as new-patient veteran-event pricing. | Veteran callback request is captured for staff to confirm correct option, eligibility, and timing. | No payment capture in the veteran callback branch. No Acuity veteran event booking is promised by this branch. | `voicePaymentCapture.test.ts`: veteran yes script, callback contact parsing/fallback, prior-card uncertainty, price question, and no payment assertions. `voiceNewPatientScript.smoke.test.ts`: deposit rescue before veteran fallback. | + +## Evidence Audit Notes + +- Cancellation and reschedule are intentionally separate. Pure cancellation routes to the hidden cancellation callback lane; mixed cancel/reschedule routes to reschedule because explicit reschedule is checked first. +- Symptom-backed appointment changes are treated as appointment-change routing when the caller explicitly asks to reschedule or cancel. True medical questions still route to staff/doctor callback without advice. +- The current route matrix does not prove HIPAA readiness, live GPT/RAG, public self-service reschedule, guaranteed veteran eligibility, guaranteed appointment availability, or untested payment-provider behavior. +- High-value next regression coverage: a direct DTMF 4 hidden-lane smoke test, a business-hours Press 3 cancellation interception test, and a default-disabled assertion that the reschedule route never calls `rescheduleAppointment` unless `ENABLE_PUBLIC_SELF_SERVICE_RESCHEDULE=true`. + ## Current IVR Menu Truth The public top-level IVR remains: