Encounter Type System
A smart interview + resource-matching + treatment-plan-generation engine that connects the patient portal's complaint intake to the doctor's minimal-click visit workflow. Encounter types are first-class, versioned entities: they define what questions to ask, what resources to book, what defaults to pre-select, and what treatment plans to generate — and they learn from every visit.
System Overview
The Encounter Type System is the bridge between what the patient says ("I have a cough") and what the practice does (book a 20-min acute slot with an MA + exam room + spirometer, ask about fever and smoking, pre-fill the doctor's respiratory review, and auto-suggest a CXR order). It has five interlocking parts:
graph TB
subgraph "Patient Side"
P1[Complaint Intake] --> P2[Smart Suggestion Engine]
P2 --> P3[Pre-Visit Questionnaire]
end
subgraph "Scheduling Side"
S1[Encounter Type Definition] --> S2[Resource Matching]
S2 --> S3[Slot Booking]
end
subgraph "Doctor Side"
D1[Minimal-Click Interview] --> D2[Treatment Plan Generation]
D2 --> D3[Coding Auto-Suggest]
end
subgraph "Learning Side"
L1[Post-Encounter Review] --> L2[Question Bank Update]
L2 --> L3[Encounter Type Editor]
end
P1 --> S1
P2 --> S2
P3 --> D1
S3 --> D1
D2 --> L1
L3 --> S1
D3 --> L1
style P1 fill:#4A90D9,color:#fff
style P2 fill:#4A90D9,color:#fff
style P3 fill:#4A90D9,color:#fff
style S1 fill:#7B68EE,color:#fff
style S2 fill:#7B68EE,color:#fff
style S3 fill:#7B68EE,color:#fff
style D1 fill:#2ECC71,color:#fff
style D2 fill:#2ECC71,color:#fff
style D3 fill:#2ECC71,color:#fff
style L1 fill:#E67E22,color:#fff
style L2 fill:#E67E22,color:#fff
style L3 fill:#E67E22,color:#fff
Each part is specified in detail below, with schemas, flows, and wireframes.
1. Encounter Type Definition Schema
Each encounter type is a first-class entity — versioned, org-scoped, and composable. It replaces the flat "visit type" concept in Scheduling with a rich template that drives every downstream workflow.
EncounterType Entity
| Field | Type | Scope | Notes |
|---|---|---|---|
| EncounterTypeID | ShortGUID (PK) | Global | Unique across the platform |
| OrganizationID | ShortGUID | Org-scoped | FK → Organization. System-wide types have null (platform-managed). |
| Name | String (120) | Org-scoped | Display name, e.g. "Annual Physical — Established Adult" |
| Description | String (500) | Org-scoped | One-line purpose for admin UI and patient-facing copy |
| Category | Enum | Global | Preventive|Acute|ChronicFollowUp|NewPatient|Procedure|Telehealth |
| IsActive | Bool | Org-scoped | Soft-deactivate without deleting |
| Version | Integer | Org-scoped | Monotonically increasing; every edit creates a new version row |
| IsComposite | Bool | Org-scoped | true if this type is a combination of other types (e.g. Annual + Acute) |
| CompositeOfTypeIDs | ShortGUID[] | Org-scoped | Ordered list of constituent EncounterTypeIDs when IsComposite = true |
| TotalDurationMinutes | Integer | Org-scoped | Sum of stage durations; for composites, sum of constituents minus dedup-overlap minutes |
| Stages | EncounterStage[] | Org-scoped | Ordered list of stages (inherits scheduling stage model; see below) |
| RequiredResources | ResourceRequirement[] | Org-scoped | People, equipment, and rooms needed |
| PreVisitQuestionnaire | QuestionRef[] | Org-scoped | Ordered list of question references (deduplication via shared Question bank) |
| TreatmentPlanTemplate | TreatmentPlanTemplate | Org-scoped | Rules for auto-generating orders, refs, Rx, follow-up |
| CodingHints | CodingHintSet | Org-scoped | Suggested E/M level, CPT, ICD-10 ranges based on answer patterns |
| ComplaintKeywords | String[] | Org-scoped | Keywords/phrases that trigger this encounter type from patient complaint text |
| PatientFacingCopy | String (200) | Org-scoped | What the patient sees, e.g. "Annual checkup with your doctor" |
| CreatedDateTimeUTC | DateTime | — | Audit |
| ModifiedDateTimeUTC | DateTime | — | Audit |
| ModifiedByUserID | ShortGUID | — | Audit — FK → User |
EncounterStage (extends scheduling VisitStage)
| Field | Type | Notes |
|---|---|---|
| StageID | ShortGUID | Unique within this encounter type |
| Name | String (80) | e.g. "Rooming + vitals", "Provider eval" |
| OrderIndex | Integer | Zero-based position in stage sequence |
| DurationMinutes | Integer | Fixed duration for this stage |
| StageType | Enum | CheckIn|Waiting|Rooming|Provider|Nurse|Procedure|Checkout|Telehealth |
| RequiredResources | ResourceRequirement[] | Resources needed for this specific stage |
| QuestionRefs | QuestionRef[] | Questions to ask during this stage (e.g. vitals questions during Rooming) |
This extends the VisitStage model from
Scheduling by adding
QuestionRefs so that stage-specific questions (e.g. intake
questions during Rooming) are driven by the encounter type template.
ResourceRequirement
| Field | Type | Notes |
|---|---|---|
| ResourceType | Enum | Person|Equipment|Room |
| RoleOrCapability | String | For Person: MD, MA, RN, FrontDesk. For Equipment: PhlebotomyChair, EKG, Spirometer, Otoscope. For Room: ExamRoom, LabDrawStation, ProcedureRoom. |
| QuantityMin | Integer | Minimum count needed (usually 1) |
| QuantityMax | Integer | Maximum useful count (e.g. 2 MAs for complex rooming) |
| RequiredForStages | String[] | Which stage(s) this resource is needed for (by StageID) |
| IsOptional | Bool | If true, the solver can book without this resource but should try to include it |
Question Bank & Deduplication
Questions are defined once in a global Question Bank and referenced by encounter types. When a visit combines multiple encounter types (e.g. Annual Physical + Acute), shared questions are asked once.
| Field | Type | Scope | Notes |
|---|---|---|---|
| QuestionID | ShortGUID (PK) | Global | Unique across the platform |
| Text | String (500) | Global | The question as asked to the patient, e.g. "Are you allergic to latex?" |
| ShortLabel | String (60) | Global | Abbreviated label for doctor view, e.g. "Latex allergy?" |
| QuestionType | Enum | Global | YesNo|MultipleChoice|FreeText|Numeric|Scale|Date|SingleSelect |
| Choices | ChoiceOption[] | Global | For MultipleChoice / SingleSelect: value + label pairs |
| Units | String (30) | Global | For Numeric: e.g. "lbs", "mg/dL", "pack-years" |
| ScaleMin / ScaleMax | Integer | Global | For Scale: e.g. 0–10 pain scale |
| IsRequired | Bool | Per-ref | Required vs. optional — set on the QuestionRef, not the Question itself (same question can be required in one type, optional in another) |
| ComplaintTrigger | String[] | Per-ref | Keywords that activate this question within the encounter type. Empty = always show. |
| ShowIfCondition | Expression | Per-ref | Conditional logic: show this question only if another answer meets criteria (e.g. "Show if Q5 = yes") |
| ClinicalMapping | CodeableConcept | Global | FHIR-aligned mapping: SNOMED-CT observation code, LOINC panel, etc. |
| Source | Enum | Global | SystemWide|PracticeSpecific |
| SourceOrganizationID | ShortGUID | Org-scoped | Null for system-wide; org ID for practice-specific |
| DeprecatedDateTimeUTC | DateTime? | Global | Set when admin deprecates; excluded from active questionnaires |
| CreatedDateTimeUTC | DateTime | — | Audit |
| ModifiedDateTimeUTC | DateTime | — | Audit |
QuestionRef (the link between EncounterType and Question)
| Field | Type | Notes |
|---|---|---|
| QuestionID | ShortGUID | FK → Question |
| OrderIndex | Integer | Position within this encounter type's questionnaire |
| IsRequired | Bool | Required in this encounter type (overrides Question default) |
| ComplaintTrigger | String[] | Keywords from the patient's complaint that activate this question. Empty = always show for this encounter type. |
| ShowIfCondition | Expression | Conditional logic expression referencing other QuestionIDs, e.g. { "questionId": "q-smoking", "operator": "equals", "value": "yes" } |
| StageID | ShortGUID? | If set, this question is asked during a specific stage (e.g. vitals questions during Rooming). Null = pre-visit questionnaire. |
ChoiceOption
| Field | Type | Notes |
|---|---|---|
| Value | String | Stored value, e.g. "current", "former", "never" |
| Label | String | Display label, e.g. "Current smoker", "Former smoker", "Never smoked" |
| OrderIndex | Integer | Display order |
| IsDefault | Bool | Pre-selected for the doctor view |
Overlapping Question Deduplication Engine
When a visit combines multiple encounter types (e.g. Annual Physical + Acute Complaint), the dedup engine:
- Collects all
QuestionRefs from each constituent encounter type - Groups by
QuestionID— questions referenced by multiple types appear once - Merges
ComplaintTriggerarrays (union of keywords) - Takes the stricter
IsRequired(if required in any type, it's required overall) - Resolves
ShowIfConditionconflicts: if any type would show it unconditionally, it's shown unconditionally - Orders: shared questions first, then type-specific questions in constituent order
graph LR ET1[Annual Physical
Questions: Q1–Q12] --> DEDUP{Dedup Engine} ET2[Acute Visit
Questions: Q8–Q15] --> DEDUP DEDUP --> MERGED[Merged Questionnaire
Q1–Q7 shared + Q8–Q12 Annual + Q13–Q15 Acute
Q8–Q12 asked ONCE]
Treatment Plan Template
| Field | Type | Notes |
|---|---|---|
| TemplateID | ShortGUID (PK) | Unique ID for this template |
| EncounterTypeID | ShortGUID | FK → EncounterType |
| Name | String (120) | e.g. "Annual Physical — Standard Orders" |
| Rules | PlanRule[] | Ordered list of conditional rules |
| DefaultFollowUpWeeks | Integer | Default follow-up interval (e.g. 52 for annual, 4 for acute) |
| PatientEducationTopics | String[] | Topics to surface in patient portal after visit |
| Version | Integer | Template version |
PlanRule (conditional treatment rule)
| Field | Type | Notes |
|---|---|---|
| RuleID | ShortGUID | Unique within this template |
| ConditionExpression | Expression | When to fire: references question answers and patient data, e.g. { "questionId": "q-diabetic", "operator": "equals", "value": "yes" } |
| ActionType | Enum | LabOrder|ImagingOrder|Referral|Prescription|FollowUpVisit|ProblemListAdd|PatientEducation|Screening |
| ActionPayload | JSON | Action-specific data. Lab: { "loincCodes": [...], "fastingRequired": true }. Referral: { "specialty": "Cardiology", "urgency": "routine" }. Rx: { "rxNormCode": "...", "sig": "..." } |
| IsDefault | Bool | If true, this action is auto-checked in the doctor's review; doctor just signs off |
| Priority | Enum | Required|Recommended|Optional |
| Category | String | Grouping label for the doctor view, e.g. "Labs", "Referrals", "Prescriptions" |
Coding Hint Set
| Field | Type | Notes |
|---|---|---|
| DefaultEMLevel | String | Suggested E/M code, e.g. 99213 for acute, 99214 for annual, 99215 for complex chronic |
| EMLevelRules | EMLevelRule[] | Conditional E/M upgrades based on answer patterns (e.g. if 3+ chronic conditions reviewed → 99214) |
| SuggestedCPTCodes | String[] | CPT codes commonly used with this encounter type, e.g. 99396 (periodic preventive, established 40–64) |
| ICD10Ranges | ICD10Range[] | Common ICD-10 ranges for this encounter type, e.g. Z00.00 (general adult exam), J00–J06 (acute URI) |
| ModifierHints | String[] | Suggested modifiers, e.g. -25 for significant separately identifiable E/M on same day as procedure |
EMLevelRule (conditional E/M upgrade)
| Field | Type | Notes |
|---|---|---|
| ConditionExpression | Expression | When to suggest upgrade, e.g. "3+ chronic conditions reviewed" |
| SuggestedLevel | String | e.g. 99214, 99215 |
| MDMRationale | String | Pre-written MDM justification text for audit defense |
2. Smart Encounter Type Suggestion Engine
When a patient enters complaints on the portal (steps 5–6 of the self-scheduling wizard), the suggestion engine maps complaint text → encounter type(s) and presents a recommendation.
Suggestion Flow
sequenceDiagram
participant P as Patient Portal
participant E as Suggestion Engine
participant D as Dedup Engine
participant S as Scheduling Solver
P->>E: Complaint text ("cough for 2 weeks, chest tightness")
E->>E: Tokenize + keyword match against EncounterType.ComplaintKeywords
E->>E: Score each encounter type by match count + specificity
E->>P: Top match: Acute Visit (score: 0.87)
Alt: Annual Physical + Acute (score: 0.72)
alt Single type match
P->>P: Show: "We recommend a 20-min Acute Visit"
end
alt Multiple types match
P->>D: Merge Annual Physical + Acute Visit
D->>D: Deduplicate shared questions
D->>P: "Based on your concerns, we recommend a
45-min Annual Physical + 20-min Acute Visit.
Total time: 65 min."
end
P->>P: Patient accepts or overrides
P->>S: Book encounter type(s) → resource graph solver finds slot
Matching Algorithm (Phase 1 — Rule-Based)
| Step | Description | Example |
|---|---|---|
| 1. Tokenize | Lowercase, remove stop words, stem | "cough for 2 weeks" → ["cough", "2", "week"] |
| 2. Keyword match | Match tokens against EncounterType.ComplaintKeywords | "cough" ∈ Acute.ComplaintKeywords |
| 3. Score | Sum of match weights; keyword specificity bonus | Acute: 0.87, Annual+Acute: 0.72 |
| 4. Threshold | Only suggest if score ≥ 0.5 | 0.87 passes → suggest Acute |
| 5. Composite detection | If patient also says "annual" or "checkup", detect Annual Physical keyword and suggest composite | "annual checkup + cough" → Annual+Acute composite |
| 6. Problem list augmentation | Check patient's active problem list; if chronic condition present, suggest chronic follow-up type | T2D on problem list → suggest Diabetes Follow-Up in addition |
Patient-Facing Suggestion UI
Override Tracking
When a patient overrides the suggestion, the override is logged for model improvement:
| Field | Type | Notes |
|---|---|---|
| SuggestionID | ShortGUID | Unique ID for this suggestion event |
| PatientID | ShortGUID | FK → Patient |
| ComplaintText | String | Original complaint text entered by patient |
| SuggestedTypeIDs | ShortGUID[] | Encounter type IDs suggested, in rank order |
| SuggestedScores | Float[] | Match scores for each suggestion |
| AcceptedTypeID | ShortGUID | Encounter type the patient actually selected |
| WasOverride | Bool | true if patient chose a non-top-ranked suggestion |
| CreatedDateTimeUTC | DateTime | Audit |
3. Doctor-Side Minimal-Click Interview
When the doctor opens the encounter in Clinical Documentation, the encounter-type template drives a one-screen summary with all pre-visit answers populated and defaults pre-selected. The doctor's job is to review and approve, not to fill out from scratch.
Interview Flow
sequenceDiagram participant DOC as Doctor participant UI as Encounter Surface participant Q as Questionnaire Engine participant TPT as Treatment Plan Engine participant COD as Coding Engine DOC->>UI: Open encounter UI->>Q: Load EncounterType + pre-visit answers Q->>UI: Pre-filled summary (all answered questions + defaults) UI->>DOC: One-screen summary:
✅ 12/15 pre-populated
⚠️ 3 need attention (unanswered)
📋 Treatment plan ready for review DOC->>UI: Review unanswered questions (3 clicks) DOC->>UI: [Approve All] — sign off on pre-populated items DOC->>UI: Add free-text note (optional) UI->>TPT: Generate treatment plan from answers + template TPT->>UI: Proposed: 2 labs, 1 Rx, 1 follow-up
(all auto-checked, doctor modifies if needed) DOC->>UI: [Sign & Send] — one click UI->>COD: Auto-suggest coding from encounter type + answers + time COD->>UI: E/M 99214, CPT 99396, ICD-10 Z00.00 + J06.9 DOC->>UI: [Accept Codes]
Doctor Encounter Surface — Wireframe
One-Click Actions
| Action | Button | What It Does | Downstream |
|---|---|---|---|
| Approve All | [Approve All] | Sign off on all pre-populated questionnaire answers in one click | Answers stored as QuestionResponse entities on the encounter |
| Order Labs | [Order Labs] | Send checked lab orders to Labs module | Lab requisition created; sample tracking initiated |
| Prescribe | [Rx] | Send checked prescriptions to eRx | Rx transmitted to pharmacy; EPCS if controlled |
| Refer | [Refer] | Send checked referrals to Referrals | Referral created; prior-auth check initiated |
| Add to Problem List | [+ Problem] | Add a new condition to the patient's global problem list | SNOMED-CT + ICD-10-CM coded; visible across all orgs |
| Sign & Close | [Sign & Close] | Finalize encounter note, sign all orders, close encounter | Note versioned; orders transmitted; encounter status → Completed |
4. Treatment Plan Generation
The treatment plan engine evaluates the TreatmentPlanTemplate rules
against the patient's questionnaire answers + existing clinical data (problem
list, medication list, recent labs) and produces a concrete plan for the doctor
to review, modify, and approve.
Plan Generation Flow
graph TD
A[Questionnaire Answers] --> RULES{TreatmentPlanTemplate
Rule Evaluation}
B[Patient Problem List] --> RULES
C[Patient Medication List] --> RULES
D[Recent Lab Results] --> RULES
RULES -->|Condition met| E1[Auto-checked action
Doctor just signs off]
RULES -->|Condition met + optional| E2[Unchecked recommendation
Doctor opts in]
RULES -->|No condition met| E3[Action not shown]
E1 --> REVIEW[Doctor Review Surface]
E2 --> REVIEW
REVIEW -->|Approve| FINAL[Finalized Treatment Plan]
REVIEW -->|Modify| FINAL
REVIEW -->|Remove| FINAL
FINAL --> CHART[Saved to Patient Chart]
FINAL --> PORTAL[Appears in Patient Portal
my-plan.html]
FINAL --> TASKS[Follow-up tasks created
in Task Management]
Generated Treatment Plan Entity
| Field | Type | Notes |
|---|---|---|
| TreatmentPlanID | ShortGUID (PK) | Unique ID |
| EncounterID | ShortGUID | FK → Encounter |
| PatientID | ShortGUID | FK → Patient |
| EncounterTypeID | ShortGUID | FK → EncounterType (source template) |
| Items | TreatmentPlanItem[] | Ordered list of plan items |
| Status | Enum | Draft|PendingReview|Approved|PartiallyCompleted|Completed |
| ApprovedByUserID | ShortGUID | FK → User (the approving clinician) |
| ApprovedDateTimeUTC | DateTime | When the doctor signed off |
| PatientEducationLinks | String[] | URLs surfaced in patient portal |
| CreatedDateTimeUTC | DateTime | Audit |
TreatmentPlanItem
| Field | Type | Notes |
|---|---|---|
| ItemID | ShortGUID | Unique within this plan |
| ItemType | Enum | LabOrder|ImagingOrder|Referral|Prescription|FollowUpVisit|ProblemListAdd|PatientEducation|Screening |
| Priority | Enum | Required|Recommended|Optional |
| IsAutoGenerated | Bool | true if template-driven, false if manually added by doctor |
| Status | Enum | Pending|Approved|Removed|Completed |
| Payload | JSON | Action-specific data (same shape as PlanRule.ActionPayload) |
| TriggerRuleID | ShortGUID? | FK → PlanRule that generated this item; null if manually added |
| TriggerAnswerIDs | ShortGUID[] | QuestionResponse IDs that triggered this item (for audit trail) |
| Category | String | Grouping label: "Labs", "Referrals", "Prescriptions", etc. |
| SortOrder | Integer | Display order within category |
Doctor Modification Patterns
- Remove — uncheck an auto-generated item; reason not required (template was a suggestion)
- Add — doctor adds an item not in the template; it's marked
IsAutoGenerated = false - Modify — change payload (e.g. add a lab to a panel, change Rx dosage); original preserved in audit
- Defer — mark as "review later" (creates a Task for the doctor or MA)
5. Learning Loop
After encounter close, the doctor can add new questions to the encounter type. This is the same Question Learning Loop described in the Coding / CDS module, but now applied specifically to the encounter-type template rather than the coding surface.
graph TD
ENC[Encounter Completes] --> EXTRACT{Question Extraction}
EXTRACT -->|Scribe captures questions asked| NEWQ[New Questions Identified]
EXTRACT -->|Doctor manually adds| MANUAL[Doctor adds question]
NEWQ --> TASK[Auto-create Task:
"Review 3 new questions from
Acute Visit encounters this week"]
MANUAL --> TASK
TASK --> PM[Practice Manager
reviews in Task Queue]
PM -->|Accept| ADD[Add to EncounterType
as PracticeSpecific]
PM -->|Edit| ADD
PM -->|Reject| REJ[Deprecate Question
or leave unadopted]
PM -->|Promote| PROMOTE[Admin promotes to
SystemWide scope]
ADD --> NEXT[Next visit of this type
includes new question]
PROMOTE --> NEXT2[All orgs see question
after next sync]
style ENC fill:#2ECC71,color:#fff
style TASK fill:#E67E22,color:#fff
style PM fill:#9B59B6,color:#fff
style ADD fill:#4A90D9,color:#fff
style PROMOTE fill:#4A90D9,color:#fff
Learning Loop Entities
CandidateQuestion (extracted from scribe or manually added)
| Field | Type | Notes |
|---|---|---|
| CandidateID | ShortGUID (PK) | Unique ID |
| EncounterID | ShortGUID | FK → Encounter that generated this candidate |
| EncounterTypeID | ShortGUID | FK → EncounterType this candidate targets |
| Text | String (500) | The question text |
| QuestionType | Enum | Suggested type: YesNo, MultipleChoice, FreeText, etc. |
| SourceMethod | Enum | ScribeExtracted|DoctorAdded |
| Frequency | Integer | How many encounters this question appeared in |
| ReviewStatus | Enum | Pending|Accepted|Edited|Rejected|Promoted |
| ReviewedByUserID | ShortGUID? | FK → User who reviewed |
| ResultingQuestionID | ShortGUID? | FK → Question created after acceptance |
| CreatedDateTimeUTC | DateTime | Audit |
PracticeSpecific
(tied to the org). A practice manager or admin can promote a
practice-specific question to SystemWide scope, making it available
to all organizations. Promotion requires:
- The question has been used in ≥ 10 encounters across ≥ 3 providers
- The accept rate is ≥ 80% (doctors are keeping it in their workflow)
- An admin explicitly clicks "Promote to System-Wide"
6. Encounter Type Editor
An admin/practice-manager interface for CRUD on encounter types, question bank management, and template editing. This is the control surface for the entire system.
Editor Capabilities
| Capability | Description | Notes |
|---|---|---|
| CRUD Encounter Types | Create, read, update, deactivate encounter types | Updates create a new version row; old versions preserved for audit |
| Drag-and-Drop Stage Reordering | Reorder stages within an encounter type | Reorder updates OrderIndex on all stages; solver uses new order |
| Question Bank Management | Add, edit, deprecate, merge duplicate questions | Merge: reassign all QuestionRefs from deprecated ID to target ID |
| Resource Requirement Editing | Add/remove resources per stage | Changes take effect on next booking; existing appointments unchanged |
| Treatment Plan Template Editing | Add/remove/modify PlanRules | Versioned; old template preserved |
| Coding Hint Editing | Adjust E/M levels, CPT codes, ICD-10 ranges | Only org-scoped types are editable; system-wide types are read-only for non-platform-admins |
| Preview Mode | "What would the patient see? What would the doctor see?" | Interactive preview renders the patient questionnaire and doctor summary surface side-by-side |
| Composite Builder | Combine existing encounter types into a composite | Shows dedup preview: "7 shared questions will be asked once" |
Editor Wireframe
JSON Data Shapes
Complete JSON shapes for the four core entities, ready for implementation.
EncounterType (complete JSON shape)
{
"EncounterTypeID": "A1b2C3d4E5f6G7h8I9j0K1",
"OrganizationID": null,
"Name": "Annual Physical — Established Adult",
"Description": "Comprehensive annual exam with labs, screenings, and preventive counseling",
"Category": "Preventive",
"IsActive": true,
"Version": 3,
"IsComposite": false,
"CompositeOfTypeIDs": [],
"TotalDurationMinutes": 45,
"Stages": [
{
"StageID": "s1",
"Name": "Check-in",
"OrderIndex": 0,
"DurationMinutes": 3,
"StageType": "CheckIn",
"RequiredResources": [
{ "ResourceType": "Person", "RoleOrCapability": "FrontDesk", "QuantityMin": 1, "QuantityMax": 1, "RequiredForStages": ["s1"], "IsOptional": false }
],
"QuestionRefs": []
},
{
"StageID": "s3",
"Name": "Rooming + vitals",
"OrderIndex": 2,
"DurationMinutes": 7,
"StageType": "Rooming",
"RequiredResources": [
{ "ResourceType": "Person", "RoleOrCapability": "MA", "QuantityMin": 1, "QuantityMax": 1, "RequiredForStages": ["s3"], "IsOptional": false },
{ "ResourceType": "Room", "RoleOrCapability": "ExamRoom", "QuantityMin": 1, "QuantityMax": 1, "RequiredForStages": ["s3", "s4"], "IsOptional": false }
],
"QuestionRefs": [
{ "QuestionID": "q-reason-for-visit", "OrderIndex": 0, "IsRequired": true, "ComplaintTrigger": [], "ShowIfCondition": null, "StageID": "s3" }
]
},
{
"StageID": "s4",
"Name": "Provider eval",
"OrderIndex": 3,
"DurationMinutes": 22,
"StageType": "Provider",
"RequiredResources": [
{ "ResourceType": "Person", "RoleOrCapability": "MD", "QuantityMin": 1, "QuantityMax": 1, "RequiredForStages": ["s4"], "IsOptional": false }
],
"QuestionRefs": []
}
],
"RequiredResources": [
{ "ResourceType": "Person", "RoleOrCapability": "FrontDesk", "QuantityMin": 1, "QuantityMax": 2, "RequiredForStages": ["s1", "s6"], "IsOptional": false },
{ "ResourceType": "Person", "RoleOrCapability": "MA", "QuantityMin": 1, "QuantityMax": 1, "RequiredForStages": ["s3"], "IsOptional": false },
{ "ResourceType": "Person", "RoleOrCapability": "MD", "QuantityMin": 1, "QuantityMax": 1, "RequiredForStages": ["s4"], "IsOptional": false },
{ "ResourceType": "Person", "RoleOrCapability": "RN", "QuantityMin": 1, "QuantityMax": 1, "RequiredForStages": ["s5"], "IsOptional": false },
{ "ResourceType": "Room", "RoleOrCapability": "ExamRoom", "QuantityMin": 1, "QuantityMax": 1, "RequiredForStages": ["s3", "s4"], "IsOptional": false }
],
"PreVisitQuestionnaire": [
{ "QuestionID": "q-med-changes", "OrderIndex": 0, "IsRequired": true, "ComplaintTrigger": [], "ShowIfCondition": null, "StageID": null },
{ "QuestionID": "q-allergy-updates", "OrderIndex": 1, "IsRequired": true, "ComplaintTrigger": [], "ShowIfCondition": null, "StageID": null },
{ "QuestionID": "q-smoking", "OrderIndex": 2, "IsRequired": true, "ComplaintTrigger": [], "ShowIfCondition": null, "StageID": null },
{ "QuestionID": "q-exercise", "OrderIndex": 3, "IsRequired": false, "ComplaintTrigger": [], "ShowIfCondition": null, "StageID": null },
{ "QuestionID": "q-alcohol", "OrderIndex": 4, "IsRequired": true, "ComplaintTrigger": [], "ShowIfCondition": null, "StageID": null },
{ "QuestionID": "q-chest-pain", "OrderIndex": 5, "IsRequired": true, "ComplaintTrigger": ["chest pain", "chest tightness", "shortness of breath"], "ShowIfCondition": null, "StageID": null },
{ "QuestionID": "q-latex-allergy", "OrderIndex": 6, "IsRequired": false, "ComplaintTrigger": [], "ShowIfCondition": null, "StageID": null }
],
"TreatmentPlanTemplate": {
"TemplateID": "tpt-annual-std",
"EncounterTypeID": "A1b2C3d4E5f6G7h8I9j0K1",
"Name": "Annual Physical — Standard Orders",
"Rules": [
{
"RuleID": "r1",
"ConditionExpression": { "questionId": "q-diabetic", "operator": "equals", "value": "yes" },
"ActionType": "LabOrder",
"ActionPayload": { "loincCodes": ["4548-4", "17861-6", "2093-3"], "fastingRequired": true, "description": "HbA1c + Lipid Panel + CMP" },
"IsDefault": true,
"Priority": "Required",
"Category": "Labs"
},
{
"RuleID": "r2",
"ConditionExpression": { "questionId": "q-smoking", "operator": "equals", "value": "current" },
"ActionType": "Referral",
"ActionPayload": { "specialty": "Smoking Cessation", "urgency": "routine" },
"IsDefault": false,
"Priority": "Recommended",
"Category": "Referrals"
}
],
"DefaultFollowUpWeeks": 52,
"PatientEducationTopics": ["Preventive health", "Exercise", "Nutrition"],
"Version": 2
},
"CodingHints": {
"DefaultEMLevel": "99214",
"EMLevelRules": [
{
"ConditionExpression": { "field": "ChronicConditionCount", "operator": "gte", "value": 3 },
"SuggestedLevel": "99215",
"MDMRationale": "3+ chronic conditions reviewed; moderate-complexity data analysis; moderate risk"
}
],
"SuggestedCPTCodes": ["99396"],
"ICD10Ranges": [
{ "Range": "Z00.00–Z00.13", "Description": "General adult examination" }
],
"ModifierHints": ["-25"]
},
"ComplaintKeywords": ["annual", "checkup", "physical", "yearly", "wellness exam", "preventive"],
"PatientFacingCopy": "Annual checkup with your doctor",
"CreatedDateTimeUTC": "2026-01-15T10:00:00Z",
"ModifiedDateTimeUTC": "2026-05-20T14:30:00Z",
"ModifiedByUserID": "U1b2C3d4E5f6G7h8"
}
Question (complete JSON shape)
{
"QuestionID": "q-smoking",
"Text": "What is your smoking status?",
"ShortLabel": "Smoking status?",
"QuestionType": "SingleSelect",
"Choices": [
{ "Value": "current", "Label": "Current smoker", "OrderIndex": 0, "IsDefault": false },
{ "Value": "former", "Label": "Former smoker (quit > 12 months ago)", "OrderIndex": 1, "IsDefault": false },
{ "Value": "never", "Label": "Never smoked", "OrderIndex": 2, "IsDefault": true }
],
"Units": null,
"ScaleMin": null,
"ScaleMax": null,
"ClinicalMapping": {
"system": "http://loinc.org",
"code": "72166-2",
"display": "Tobacco smoking status"
},
"Source": "SystemWide",
"SourceOrganizationID": null,
"DeprecatedDateTimeUTC": null,
"CreatedDateTimeUTC": "2026-01-15T10:00:00Z",
"ModifiedDateTimeUTC": "2026-01-15T10:00:00Z"
}
TreatmentPlanTemplate (complete JSON shape)
{
"TemplateID": "tpt-acute-resp",
"EncounterTypeID": "B2c3D4e5F6g7H8i9J0k1",
"Name": "Acute Visit — Respiratory Protocol",
"Rules": [
{
"RuleID": "ar1",
"ConditionExpression": { "questionId": "q-cough-duration", "operator": "gte", "value": "14" },
"ActionType": "ImagingOrder",
"ActionPayload": { "modality": "CXR", "views": ["PA", "Lateral"], "urgency": "routine", "reason": "Cough ≥ 2 weeks" },
"IsDefault": true,
"Priority": "Recommended",
"Category": "Imaging"
},
{
"RuleID": "ar2",
"ConditionExpression": { "questionId": "q-smoking", "operator": "in", "value": ["current", "former"] },
"ActionType": "LabOrder",
"ActionPayload": { "loincCodes": ["19841-2"], "fastingRequired": false, "description": "Spirometry" },
"IsDefault": false,
"Priority": "Recommended",
"Category": "Labs"
},
{
"RuleID": "ar3",
"ConditionExpression": { "questionId": "q-wheezing", "operator": "equals", "value": "yes" },
"ActionType": "Prescription",
"ActionPayload": { "rxNormCode": "236185", "description": "Albuterol inhaler", "sig": "2 puffs Q4-6H PRN shortness of breath" },
"IsDefault": true,
"Priority": "Recommended",
"Category": "Prescriptions"
},
{
"RuleID": "ar4",
"ConditionExpression": { "operator": "always" },
"ActionType": "FollowUpVisit",
"ActionPayload": { "encounterTypeID": "B2c3D4e5F6g7H8i9J0k1", "intervalWeeks": 4, "reason": "Follow-up for respiratory symptoms" },
"IsDefault": true,
"Priority": "Required",
"Category": "Follow-up"
}
],
"DefaultFollowUpWeeks": 4,
"PatientEducationTopics": ["Cough and cold", "When to seek emergency care"],
"Version": 1
}
EncounterSession (complete JSON shape — runtime state)
{
"EncounterSessionID": "ES1b2C3d4E5f6G7h8",
"EncounterID": "E1b2C3d4E5f6G7h8I9j0K1",
"PatientID": "P1b2C3d4E5f6G7h8",
"EncounterTypeIDs": [
"A1b2C3d4E5f6G7h8I9j0K1",
"B2c3D4e5F6g7H8i9J0k1"
],
"IsComposite": true,
"MergedQuestionnaire": {
"Source": "dedup-merge",
"SharedQuestionIDs": ["q-med-changes", "q-allergy-updates", "q-smoking", "q-latex-allergy"],
"TypeSpecificQuestions": {
"A1b2C3d4E5f6G7h8I9j0K1": ["q-exercise", "q-alcohol", "q-mammogram-date"],
"B2c3D4e5F6g7H8i9J0k1": ["q-cough-duration", "q-fever", "q-wheezing", "q-sick-exposure"]
},
"OrderedQuestionIDs": [
"q-med-changes", "q-allergy-updates", "q-smoking", "q-latex-allergy",
"q-exercise", "q-alcohol", "q-mammogram-date",
"q-cough-duration", "q-fever", "q-wheezing", "q-sick-exposure"
]
},
"QuestionResponses": [
{ "QuestionID": "q-med-changes", "ResponseValue": "no", "RespondedDateTimeUTC": "2026-05-28T09:15:00Z", "Source": "PreVisit" },
{ "QuestionID": "q-allergy-updates", "ResponseValue": "no", "RespondedDateTimeUTC": "2026-05-28T09:15:05Z", "Source": "PreVisit" },
{ "QuestionID": "q-smoking", "ResponseValue": "former", "RespondedDateTimeUTC": "2026-05-28T09:15:10Z", "Source": "PreVisit" },
{ "QuestionID": "q-cough-duration", "ResponseValue": "14", "RespondedDateTimeUTC": "2026-05-28T09:15:20Z", "Source": "PreVisit" },
{ "QuestionID": "q-fever", "ResponseValue": null, "RespondedDateTimeUTC": null, "Source": null },
{ "QuestionID": "q-wheezing", "ResponseValue": "yes", "RespondedDateTimeUTC": "2026-05-28T09:15:30Z", "Source": "PreVisit" }
],
"PreVisitAnswersPopulated": 9,
"PreVisitAnswersPending": 2,
"TreatmentPlanDraft": {
"TreatmentPlanID": "TP1b2C3d4E5f6G7h8",
"Status": "Draft",
"Items": [
{ "ItemID": "i1", "ItemType": "LabOrder", "Priority": "Required", "IsAutoGenerated": true, "Status": "Pending", "Payload": { "loincCodes": ["4548-4", "17861-6"], "fastingRequired": true, "description": "HbA1c + Lipid Panel" }, "Category": "Labs", "SortOrder": 0 },
{ "ItemID": "i2", "ItemType": "ImagingOrder", "Priority": "Recommended", "IsAutoGenerated": true, "Status": "Pending", "Payload": { "modality": "CXR", "views": ["PA", "Lateral"], "reason": "Cough ≥ 2 weeks" }, "Category": "Imaging", "SortOrder": 1 },
{ "ItemID": "i3", "ItemType": "Prescription", "Priority": "Recommended", "IsAutoGenerated": true, "Status": "Pending", "Payload": { "rxNormCode": "236185", "description": "Albuterol inhaler", "sig": "2 puffs Q4-6H PRN" }, "Category": "Prescriptions", "SortOrder": 2 },
{ "ItemID": "i4", "ItemType": "FollowUpVisit", "Priority": "Required", "IsAutoGenerated": true, "Status": "Pending", "Payload": { "intervalWeeks": 4, "reason": "Follow-up for respiratory symptoms" }, "Category": "Follow-up", "SortOrder": 3 }
]
},
"CodingSuggestions": {
"EMLevel": "99214",
"CPTCodes": ["99396", "99213-25"],
"ICD10Codes": ["Z00.00", "J06.9", "E11.65"],
"Modifiers": ["-25"],
"MDMRationale": "2 chronic conditions managed (T2D, HTN) + acute respiratory complaint; moderate data review; moderate risk"
},
"CreatedDateTimeUTC": "2026-05-28T09:00:00Z",
"Status": "InProgress"
}
Use Cases
Six concrete walkthroughs showing the end-to-end flow from patient complaint through treatment plan, with key design decisions noted for each.
UC-1Annual Physical — Established Adult
Patient enters "annual checkup" in complaint field. Suggestion engine matches against
ComplaintKeywords: "annual", "checkup" → Annual Physical
encounter type (score 0.95). Single match; patient sees:
"We recommend a 45-min Annual Physical with your doctor."
Patient accepts.
7 questions: medication changes (YesNo), allergy updates (YesNo), smoking status (SingleSelect), exercise frequency (Numeric, times/week), alcohol use (SingleSelect), chest pain (YesNo — shown if respiratory keywords in complaint), latex allergy (YesNo). Patient answers all 7 in ~2 min. Answers stored as
QuestionResponse
entities with Source = PreVisit.
Pre-visit answers pre-populated. Vitals (MA-entered): BP 138/88, HR 76, SpO2 97%. All 7 questions show ✅. Doctor reviews summary, clicks
[Approve All]. Notices BP is borderline — adds free-text note:
"BP trending up, consider lisinopril dose adjustment."
Template rules evaluated against answers + problem list (T2D, HTN):
- Required: CBC, CMP, Lipid Panel (always for annual)
- Required (diabetic rule): HbA1c — auto-checked ✅
- Recommended (smoking = former): CXR — unchecked ☐
- Recommended (age > 50, no mammogram in 12 mo): Mammogram referral — unchecked ☐
[Sign & Send].
E/M 99214 (2 chronic conditions, moderate data, moderate risk). CPT 99396 (periodic preventive, 40–64). ICD-10 Z00.00 + E11.65 + I10. Doctor clicks
[Accept Codes].
UC-2Acute Sick Visit
Suggestion engine: "cough" + "chest tightness" → Acute Visit (score 0.87). Patient sees: "We recommend a 20-min Acute Visit for your cough and chest symptoms." Patient accepts.
Acute Respiratory template: cough duration (Numeric, days), fever present (YesNo), productive cough (YesNo), smoking status (SingleSelect), sick exposures (YesNo), wheezing (YesNo), night sweats (YesNo), shortness of breath at rest (YesNo), latex allergy (YesNo — shared question). 9 questions, ~2 min.
Pre-populated answers: duration = 14 days, productive = yes, wheezing = yes, smoking = former, fever = no, sick exposure = no. Vitals: SpO2 96%. Doctor adds: "Lung sounds: scattered wheezes bilaterally, no consolidation." Clicks
[Approve All] on pre-visit answers.
Template rules:
- Recommended: CXR (cough ≥ 14 days) — auto-checked ✅
- Recommended: Spirometry (former smoker + wheezing) — unchecked ☐
- Recommended: Albuterol inhaler (wheezing = yes) — auto-checked ✅
- Required: Follow-up in 4 weeks
E/M 99213 (acute, low MDM). CPT 99213. ICD-10 J06.9 (acute URI) + R05.9 (cough). Modifier -25 not needed (single E/M, no procedure). Doctor accepts.
UC-3New Patient Comprehensive
Patient has no chart in the system. During self-scheduling, the patient is identified as new (no
PatientID match). The system auto-suggests
"New Patient Comprehensive" (60 min) — no keyword matching needed; the
scheduling logic already detects new-patient status.
25 questions covering: past medical history, surgical history, family history, social history (smoking, alcohol, drugs, occupation), medication list, allergy list, immunization history, review of systems (14-system ROS). Patient fills out in ~8 min on the portal, or completes in the waiting room on a tablet during the Check-in + Paperwork stage.
If the patient authorizes, the system requests records from the prior practice via FHIR Bulk Data or fax. Imported data is staged for doctor review in a "Pending Import" section of the encounter surface. Doctor reviews, accepts or rejects each imported fact (medication, problem, allergy).
One-screen summary with two sections: (1) Patient-entered answers (25 items, all ✅), (2) Imported records (12 items — 8 auto-matched, 4 needing review). Doctor resolves the 4 pending imports, then
[Approve All].
Since no problem list exists yet, the template has fewer conditional rules. Baseline labs are auto-suggested (CBC, CMP, Lipid Panel, TSH). Doctor adds condition-specific orders as needed. Follow-up set to 4 weeks (shorter than established, to establish care).
UC-4Combined Visit — Annual Physical + Acute
Patient enters: "annual checkup" + "cough for 2 weeks, chest tightness." Suggestion engine detects two keyword clusters: "annual checkup" → Annual Physical (score 0.92), "cough, chest tightness" → Acute Visit (score 0.87). Composite detection fires: both score above 0.5.
Annual Physical has Q1–Q7. Acute Visit has Q5–Q12 (plus shared Q8: latex allergy, Q5: smoking status from Annual). Dedup engine:
- Shared: q-smoking, q-latex-allergy → asked once, in the Annual section
- Annual-specific: q-med-changes, q-allergy-updates, q-exercise, q-alcohol
- Acute-specific: q-cough-duration, q-fever, q-wheezing, q-sick-exposure, q-productive-cough, q-night-sweats, q-sob-at-rest
Annual Physical (45 min) + Acute Visit (20 min) = 65 min total. The scheduling solver finds a 65-min contiguous block with the required resources. The stage sequence merges: Annual stages run first, with the Acute provider eval time added to the Annual provider eval stage (22 + 8 = 30 min provider time).
Encounter surface shows two sections in the pre-visit summary: (1) "Annual Physical" answers (4 shared + 3 annual-specific), (2) "Acute Visit — Respiratory" answers (2 shared [already shown] + 7 acute-specific). Shared questions show once with a badge: "Shared between Annual + Acute." Doctor reviews both, clicks
[Approve All] once.
Annual template → baseline labs, A1c if diabetic. Acute template → CXR if cough ≥ 14 days, inhaler if wheezing. Both sets of items appear in the plan, grouped by category. Doctor signs off in one pass.
E/M 99214 with modifier -25 (significant separately identifiable E/M on same day as preventive). CPT 99396 + 99213-25. ICD-10 Z00.00 + J06.9. The -25 modifier is auto-suggested by the coding hints because the encounter is a composite with an acute component.
UC-5Chronic Care Follow-Up — Diabetes
Patient books "diabetes follow-up" or "check my sugar." Suggestion engine matches keyword AND cross-references the problem list: ICD-10 E11.x is active. Auto-adds "Diabetes Follow-Up" encounter type (20 min). If the patient booked a generic "follow-up," the system upgrades the suggestion: "Based on your medical history (Type 2 Diabetes), we recommend a 20-min Diabetes Management Visit."
Beyond standard follow-up questions, the diabetes template adds:
- When was your last A1c test? (Date)
- Have you been checking glucose at home? (YesNo → if yes: how often? Numeric, times/week; last fasting value? Numeric, mg/dL)
- Any numbness or tingling in feet? (YesNo)
- Last eye exam? (Date)
- Any symptoms of low blood sugar? (YesNo)
Pre-visit answers: last A1c = 3 months ago, checking glucose = yes (3×/week, fasting ~140), foot numbness = yes (bilateral toes), last eye exam = 14 months ago. Vitals: BP 132/82, A1c result (if recent lab): 7.8%. Doctor sees focused summary with diabetes-relevant data highlighted.
Template rules:
- Required: A1c lab (always for diabetes follow-up) ✅
- Required: Urine microalbumin (annual screening) ✅
- Recommended: Eye referral (if > 12 months since last exam) ✅
- Recommended: Podiatry referral (if foot numbness = yes) ✅
- Optional: Nutrition referral ☐
- Required: Follow-up in 3 months (diabetes protocol)
UC-6Pediatric Well-Child + Immunizations
Parent enters "well-child visit" or selects from age-appropriate options. Suggestion engine matches "well-child" → Well-Child encounter type (30 min). System detects patient age (18 months) and selects age-appropriate template variant automatically.
The Well-Child template has conditional question branches by age:
- 0–12 months: feeding method, sleep position, developmental milestones (rolling, sitting, babbling)
- 12–24 months: walking status, words spoken, feeding transition, MCHAT-R/F screen
- 2–5 years: toilet training, speech clarity, social interaction, preschool readiness
- 5–12 years: school performance, behavior concerns, screen time, physical activity
System queries the patient's immunization record against CDC ACIP schedule. At 18 months: DTaP (dose 4) due, Hib (dose 4 if not given at 12m), Hep A (dose 2). System auto-generates immunization orders for all due vaccines.
Doctor sees: developmental milestones ✅ (parent-entered), growth chart (MA-entered: weight, length, head circumference plotted on WHO curves), immunization checklist with all due vaccines pre-checked. Doctor reviews, unchecks Hib (already given at 12m per record), clicks
[Approve All].
Immunization orders sent to MA/Nurse stage for administration. Developmental screening results (MCHAT-R/F score) auto-recorded in the encounter note. Follow-up: next well-child at 24 months.
Patient.DateOfBirth. The
ShowIfCondition expression supports age-range predicates:
{ "field": "PatientAgeMonths", "operator": "between", "value": [12, 24] }.
This avoids creating 12 separate encounter types for each well-child interval.
End-to-End Flow — Unified View
graph TB
subgraph "Patient Portal"
A1[Patient enters complaints] --> A2[Suggestion Engine]
A2 --> A3[Accept / Override]
A3 --> A4[Pre-Visit Questionnaire]
A4 --> A5[Slot Booked]
end
subgraph "Scheduling"
A5 --> B1[Resource Graph Solver]
B1 --> B2[Appointment Created]
end
subgraph "Day of Visit"
B2 --> C1[MA Rooming + Vitals]
C1 --> C2[Doctor Opens Encounter]
end
subgraph "Doctor Workflow"
C2 --> D1[Pre-populated Summary]
D1 --> D2[Approve All / Answer Remaining]
D2 --> D3[Treatment Plan Review]
D3 --> D4[Sign & Close]
D4 --> D5[Coding Auto-Suggest]
D5 --> D6[Codes Accepted]
end
subgraph "Post-Encounter"
D6 --> E1[AVS → Patient Portal]
D6 --> E2[Orders Transmitted]
D6 --> E3[Follow-up Tasks Created]
E3 --> E4[Learning Loop: Extract Questions]
E4 --> E5[Practice Manager Review]
E5 --> E6[Question Bank Updated]
E6 -.->|Next visit| A4
end
style A1 fill:#4A90D9,color:#fff
style A2 fill:#4A90D9,color:#fff
style D1 fill:#2ECC71,color:#fff
style D3 fill:#2ECC71,color:#fff
style E4 fill:#E67E22,color:#fff
style E5 fill:#E67E22,color:#fff
style E6 fill:#E67E22,color:#fff
Design Decisions & Trade-offs
DD-1: Encounter types vs. flat visit types
The current scheduling module uses flat VisitType + VisitStage
with no questionnaire, no treatment plan template, and no learning loop. Encounter
types subsume visit types: every EncounterType has stages (inheriting
the scheduling model), but adds questionnaire, treatment plan, coding hints, and
complaint keywords. The existing VisitType data migrates to
EncounterType with empty questionnaire/template fields.
Migration is additive — existing scheduling continues to work;
encounter-type features light up as templates are configured.
DD-2: Shared question bank vs. per-type questions
Questions are defined once and referenced by multiple encounter types. This enables deduplication in composite visits (same question asked once, not twice) and cross-type analytics ("Which encounter types include the smoking status question?"). The trade-off: question edits affect all referencing types. Mitigated by versioning: editing a question creates a new version; referencing types can be updated incrementally.
DD-3: Keyword matching vs. ML for suggestion engine
Keyword matching is deterministic, auditable, and requires zero training data. It's sufficient for the initial launch where encounter types are few and keywords are well-defined. ML becomes valuable as encounter types multiply and complaint language varies. The override tracking mechanism collects the labeled data needed for ML training. Target: keyword matching for Phase 1, ML model for Phase 2.
DD-4: Composite visits vs. sequential visits
When a patient has both an annual and an acute concern, the system creates a composite encounter type instance (not two separate appointments). The composite has a single 65-min slot, a merged questionnaire (deduplicated), and a merged treatment plan. This is better than two sequential visits because: (1) the patient makes one trip, (2) the room is held for one contiguous block, (3) the doctor signs one note, (4) coding applies modifier -25 automatically. The trade-off: composites are harder to cancel/reschedule (can't cancel just the acute part). Mitigated by allowing the doctor to "split" the composite into two visits during the encounter if needed.
DD-5: Practice-specific vs. system-wide questions
New questions from the learning loop start as PracticeSpecific.
Promotion to SystemWide requires: ≥ 10 encounters, ≥ 3 providers,
≥ 80% accept rate, and explicit admin action. This prevents low-quality questions
from polluting the global bank while allowing practices to customize freely.
The trade-off: practices may duplicate each other's questions before promotion.
Mitigated by a "merge suggestion" feature that surfaces similar practice-specific
questions for admin review.
DD-6: Treatment plan auto-generation — how aggressive?
Treatment plan rules have two tiers: Required (auto-checked — doctor
must explicitly uncheck to remove) and Recommended (unchecked — doctor
must explicitly check to add). A third tier, Optional, is hidden
behind a "More options" toggle. This balances speed (required items are one-click
sign-off) with safety (recommended items require deliberate opt-in). The doctor
never has to uncheck something they didn't expect.
Open Questions
| # | Question | Impact | Options |
|---|---|---|---|
| OQ-1 | Should composite encounters produce one note or two? | Affects clinical-doc.html, coding, and AVS generation | (A) Single merged SOAP note with sections for each type. (B) Two linked notes in one encounter. (C) Doctor's choice at encounter open. |
| OQ-2 | How to handle encounter-type versioning during an in-progress visit? | If admin edits the template mid-visit, does the doctor see the old or new version? | (A) Snapshot at booking time (doctor sees what was booked). (B) Live (doctor always sees latest). (C) Snapshot at encounter-open time. |
| OQ-3 | Should the question bank support branching logic beyond ShowIf? | Affects questionnaire complexity and patient abandonment rate | (A) ShowIf only (simple conditional). (B) Full branching with skip patterns (like BRFSS). (C) ShowIf + page breaks for long questionnaires. |
| OQ-4 | Minimum encounter-type data for a practice to go live? | Onboarding time and effort | (A) Must configure full template before enabling. (B) Staged: stages first, then questionnaire, then treatment plan. (C) Copy system-wide defaults and let them customize over time. |
| OQ-5 | Should the suggestion engine consider insurance/payer rules? | Some payers require separate visits for preventive + acute; some allow modifier -25 | (A) Ignore payer rules (patient's choice). (B) Show a warning if payer likely denies composite. (C) Auto-split into two visits if payer rule requires it. |
Demo Pages to Build / Update
The following pages would need to be created or updated to implement the encounter type system. These are not built yet — they are listed here for sprint planning.
New Pages to Create
| Page | Description | Priority |
|---|---|---|
encounter-type-editor.html | Admin interface for CRUD on encounter types, question bank, treatment plan templates. Drag-and-drop stage reordering, composite builder, preview mode. | P1 — Core admin surface |
encounter-type-preview.html | Split-pane preview: patient questionnaire view on left, doctor summary view on right. Driven by encounter-type ID in query params. | P1 — Embedded in editor |
question-bank.html | Standalone question bank management: add, edit, deprecate, merge duplicates. Filters by source (system-wide vs. practice-specific), question type, clinical mapping. | P1 — Referenced by editor |
learning-loop-review.html | Practice manager's queue of candidate questions extracted from scribe + manually added. Accept/edit/reject/promote workflow. | P2 — Learning loop surface |
my-plan.html | Patient portal treatment plan view: active plan items, status, education links. Referenced from patient-portal.html but not yet built. | P2 — Patient-facing plan |
Existing Pages to Update
| Page | Update | Priority |
|---|---|---|
scheduling.html | Replace VisitType selector with EncounterType selector. Add encounter-type-driven stage timeline. Update domain entities to reference EncounterTypeID. | P1 — Schema migration |
clinical-doc.html | Add encounter-type-driven interview surface: pre-populated summary, [Approve All] button, one-click actions, treatment plan review. Link to treatment plan template. | P1 — Doctor workflow |
patient-portal.html | Update self-scheduling steps 5–6: complaint entry → suggestion engine → encounter type recommendation. Add pre-visit questionnaire step. Add my-plan link. | P1 — Patient workflow |
coding-cds.html | Update coding hint section: reference EncounterType.CodingHints. Add composite visit modifier -25 auto-suggestion. Cross-reference learning loop. | P2 — Coding integration |
task-mgmt.html | Add task type: CandidateQuestionReview. Add task template for "Review N new questions from [type] encounters this week." | P2 — Learning loop tasks |
Cross-Module Reference Map
graph LR
ETS[Encounter Type System] --> SCHED[Scheduling]
ETS --> CD[Clinical Doc]
ETS --> PP[Patient Portal]
ETS --> CDS[Coding / CDS]
ETS --> TM[Task Mgmt]
ETS --> LABS[Labs]
ETS --> RX[eRx / EPCS]
ETS --> REF[Referrals]
ETS -.->|EncounterTypeID| SCHED
ETS -.->|Pre-visit answers| CD
ETS -.->|Suggestion engine| PP
ETS -.->|CodingHints| CDS
ETS -.->|CandidateQuestion| TM
ETS -.->|Lab orders| LABS
ETS -.->|Prescriptions| RX
ETS -.->|Referral orders| REF
style ETS fill:#7B68EE,color:#fff,stroke:#333,stroke-width:3px
style SCHED fill:#4A90D9,color:#fff
style CD fill:#2ECC71,color:#fff
style PP fill:#4A90D9,color:#fff
style CDS fill:#2ECC71,color:#fff
style TM fill:#E67E22,color:#fff
style LABS fill:#9B59B6,color:#fff
style RX fill:#9B59B6,color:#fff
style REF fill:#9B59B6,color:#fff