Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions ivr routing system.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading