Radiation Plan Cockpit
Event-sourced, plan-centric RT system: the Treatment Plan is the unit of work, UX, and audit.
Design Principles
-
Plan-centric, not encounter-centric. The Treatment Plan is the unit of work, unit of UX, unit of audit. Every screen is a view onto the plan; every action is an event on the plan. Encounters, orders, fractions are children – they don’t compete for primacy.
-
Decisions over data. RT generates enormous data exhaust (DICOM, contours, DVHs, plan parameters, daily setup, cone-beam CT, OTV notes). 95% of clinician cognition during a 3-minute chair check is spent on a handful of decisions: Is this patient on track? Is anything trending wrong? Do I need to replan? The UX surfaces those decisions; the data is one click away.
-
Genomic facts as ambient signal. Genomic data appears inline at the moment it changes a decision – never on a separate tab nobody visits.
-
Minimize cognitive load. A patient on RT is in a difficult situation. A chair check is a moment of focused attention – don’t bury it in modal dialogs. Clear, calm, purposeful UX.
System Architecture (The Spine)
flowchart LR
DB[did:bio wallet] -.attestations.-> Plan
SR[ServiceRequest] --> Plan[Treatment Plan v1..n]
TC[Tumor Conference] -.M:N.- Plan
Plan --> P1[Phase 1: Initial]
Plan --> P2[Phase 2: Boost]
P1 --> RX1[Prescription]
RX1 --> APT[Appointments auto-generated]
APT --> FX[Fraction Delivery]
FX --> OTV[On-Treatment Visit]
Plan --> Sum[End-of-Treatment Summary]
Sum --> SV[Survivorship Plan]
Sum -.signed attestation.-> DB
AI[AI Suggestions] --> Gate[Safety Gate]
Gate --> Plan
Event-Sourced Plan
Every state change – order created, MDT decision logged, prescription approved, fraction delivered, OTV noted, plan amended – is an immutable event. Current plan state is a fold over events.
Benefits:
- Free audit trail
- Free time-travel for retrospective review
- Free continuous history (3.12.1.3 is literally one query)
- Clean amendment semantics (replan = new event, not destructive update)
Versioned Plan Documents
Each plan event yields a new plan version. Versions are diffable. The OTV “what changed since last week” view is a diff render, not custom code.
Multi-Modal Payload Per Plan
Structured (FHIR CarePlan + ServiceRequest), DICOM-RT objects (RTSTRUCT, RTPLAN, RTDOSE, RTIMAGE) referenced via DICOMweb, genomic attestations (did:bio JWT proofs), photos (skin toxicity), free text, voice memos transcribed. The plan owns references; heavy data lives in modality-appropriate stores.
AI Safety Gate
Dose recommendations, replan triggers, toxicity predictions – all pass through the gate before becoming plan events. Suggestions that lack clinical grounding or show bias are flagged and never auto-execute.
Schema – The Four Core Tables
-- The spine
treatment_plan (
id uuid PK,
patient_id text NOT NULL,
status text NOT NULL, -- draft | active | completed | amended | cancelled
intent text, -- curative-definitive | curative-adjuvant | palliative | prophylactic
modality text, -- IMRT | VMAT | 3D-CRT | SBRT | Brachy | Electron | Proton
created_at timestamptz,
updated_at timestamptz
)
-- Immutable event log (source of truth)
plan_event (
id uuid PK,
plan_id uuid FK -> treatment_plan,
type text NOT NULL, -- order_created | mdt_decision | prescription_approved |
-- fraction_delivered | otv_noted | plan_amended | ...
payload jsonb NOT NULL,
actor_id text NOT NULL,
ts timestamptz NOT NULL DEFAULT now()
)
-- Materialized plan state at each version
plan_version (
id uuid PK,
plan_id uuid FK -> treatment_plan,
version_no integer NOT NULL,
snapshot jsonb NOT NULL,
derived_from_event_id uuid FK -> plan_event
)
-- Portable genomic claims (no raw data)
genomic_attestation (
id uuid PK,
did text NOT NULL, -- did:bio identifier
claim_type text NOT NULL, -- hpv_status | atm_variant | dpyd_status | radiosensitivity_class | ...
claim_value text NOT NULL, -- positive | heterozygous | wild_type | high | ...
verifier_did text,
signature text,
plan_id uuid FK -> treatment_plan
)
Everything else (phases, prescriptions, appointments, fractions, OTVs, codes) is derived from the event stream and projected into query-friendly tables. plan_event is the source of truth – the rest are views you can rebuild.
Genomic Integration – Five Clinical Entry Points
These are the five real hooks where genomic data changes RT decisions:
1. Hereditary Cancer Syndromes
Li-Fraumeni (TP53), Ataxia-telangiectasia (ATM homozygous), Fanconi anemia, NF1. These contraindicate or modify RT. ATM heterozygotes show meaningful radiosensitivity and warrant dose modification. Missing this is a serious adverse event.
2. Tumor Predictive Markers
HPV+ vs HPV- oropharyngeal cancer: same anatomy, same stage, but HPV+ gets de-escalated dose because response is better. MGMT methylation in glioblastoma. EGFR/ALK in NSCLC changes whether RT is even the right modality.
3. Radiosensitivity / Radioresistance Signatures
RSI, GARD-style genomic-adjusted radiation dose. Research-grade now, production-grade soon.
4. Pharmacogenomics for Concurrent Chemo
DPYD for 5-FU (head/neck, rectal chemo-RT), UGT1A1, TPMT. Wrong dose of concurrent chemotherapy can be lethal.
5. Second Malignancy Risk
Survivors who got RT young carry lifetime risk modulated by germline variants. Survivorship-clinic territory, but the data must travel with them.
did:bio Integration
The EMR doesn’t store the genome. The patient does, sovereign, in their did:bio wallet. The EMR stores attestations: “this DID has verified ATM heterozygous status, attested by [lab], bound to this biological identity.” When the radiation oncologist opens the plan, they see flags relevant to RT decisions plus verifiable proof – never raw VCF. ZK selective disclosure means facilities across countries can consume radiosensitivity_class: high without either holding the genome.
genomic_attestation is a list of (claim, verifier, signature) tuples, not embedded data – which dissolves cross-border regulatory issues (PDPA, APPI, HIPAA all relax when the regulated entity holds attestations rather than raw genomic data).
The UX Flow – Six Moments
Each described as a single moment of attention rather than a feature list:
1. Referral Inbox
New patient arrives. One card per referral, sorted by urgency. Auto-assembled snapshot: diagnosis, stage, prior treatment, imaging thumbnails, genomic flags if present. Clinician decides: accept / decline / request info. One tap.
2. MDT Cockpit
Pre-MDT: case packet auto-builds (imaging, path, prior treatments, genomic panel). During MDT: shared screen, contouring viewer, genomic facts inline (HPV, mutation status, hereditary flags), structured decision-capture that emits a TumorConferenceNote linked M:N to plan. Post-MDT: decision becomes a plan-skeleton with one tap.
3. Plan Designer
Visual phase builder (drag to create initial + boost). Prescription form with clinical decision support inline: protocol selector (RTOG/EORTC/local), constraint suggestions, genomic adjustments surfaced as cards (“ATM heterozygous – consider 10% dose reduction”). Physicist co-signs; plan locks; appointments bulk-generate.
4. Daily Delivery Console (RTT)
One screen per patient, full-screen kiosk mode in the treatment vault. Big patient photo + biometric ID match. Setup checklist. IGRT compare. Single “Deliver” button after all gates pass. Posts a FractionDelivery event; counter advances “Fraction 12 of 30.”
5. On-Treatment Visit (Weekly)
Diff view: what changed since last week. Toxicity grading (CTCAE) with photo capture. Dose-to-date as a horizontal gauge, not a number. Decision point: continue / pause / amend / consult.
6. End-of-Treatment Summary
Auto-generated from the event log, editable, signed. Becomes the survivorship document and a signed attestation back to the patient’s did:bio wallet. Portable, verifiable RT history.
Plan Cockpit – The Central Screen
The screen the radiation oncologist opens 50 times a day:
+---------------------------------------------------------------------+
| P. R., F 54 HN 12345678 * active |
| Oropharyngeal SCC . T2N1M0 . Curative . IMRT + concurrent cisplatin|
| -- Genome (verified did:bio) -- |
| HPV-16+ ATM het [!] radiosensitive DPYD wt |
+---------------------------------------------------------------------+
+-- Treatment Lane ---------------------------------------------------+
| Referral--MDT--Sim--Plan[ok]-- PHASE 1 (50 Gy / 25 fx) -----------|
| 3/05 3/15 3/22 3/28 ############________ 12/25 |
| ^ TODAY |
| ---- PHASE 2 (Boost 10 Gy / 5 fx) -- |
| ---- EOT Summary -- Survivorship -- |
+---------------------------------------------------------------------+
+-- Dose to Date --------+-- Toxicity -----------+-- Pending ---------+
| | | |
| Target 60 Gy | Skin ##__ G2 | [!] Weekly OTV |
| Given 24 Gy | Mucositis ##__ G2 | due tomorrow |
| ########_________ 40% | Fatigue #___ G1 | |
| | [ok] tracking to ATM | Prescription on |
| Parotid R: 18.2 Gy | predicted curve | track. No replan. |
| (cap 26 Gy) ####___ | | |
+--------------------------+-----------------------+--------------------+
+-- Recent Events --------------------------------------------------------+
| Today 09:14 Fraction 12 delivered . IGRT match good . RTT: NW |
| Yest. 09:08 Fraction 11 delivered . no setup issues |
| 2d ago 14:30 Nurse visit . prophylactic mouthwash protocol started |
| 4d ago 11:00 Fraction 10 . IGRT 2mm shift, corrected |
+-------------------------------------------------------------------------+
Read top-down: who is this (header) -> where are we (treatment lane) -> how is it going (three gauges) -> what just happened (event feed). Three seconds to orient, one click to drill anywhere.
The genome row is small, ambient, always visible. The [!] on ATM het ties to the toxicity reading further down (“tracking to ATM predicted curve”).
Every element is a projection of the event stream. The lane is plan_event filtered by type. The dose-to-date is a fold over FractionDelivery events. There is no separate “history” data structure – 3.12.1.3 is satisfied by the architecture, not by a feature.
Mini-App Registry (Complete)
| DynamicCoreApp Enum | Mini-App | Requirement | Cockpit Role |
|---|---|---|---|
RT_PLAN_COCKPIT |
RadiationPlanCockpit | Central hub | The hub – links to all below |
RADIATION_SERVICE_REQUEST |
RadiationServiceRequest | 3.12.1.1 | Order entry -> creates plan |
TUMOR_CONFERENCE |
TumorConference | 3.12.1.2 | MDT review (M:N with plan) |
RADIATION_THERAPY_CYCLE_TRACKER |
RadiationTherapyCycleTracker | 3.12.1.3 + 3.12.1.6 | History + scheduling spine |
RADIATION_PROCEDURE_CODING |
RadiationProcedureCoding | 3.12.1.4 | Code management |
RADIATION_ONCOLOGY_INTAKE_PLANNING |
(existing) | – | Intake forms |
RADIATION_ONCOLOGY_TREATMENT_DAILY_CARE |
(existing) | – | Daily care forms |
RADIATION_ONCOLOGY_QUALITY_ASSURANCE |
(existing) | – | QA forms |
RADIATION_ONCOLOGY_POST_TREATMENT_FOLLOWUP |
(existing) | – | Follow-up forms |
Clinical Walk-Through
A 54-year-old Thai woman, oropharyngeal SCC, T2N1M0.
-
Pre-MDT – cockpit auto-pulls her did:bio attestations: HPV-16 positive (tumor), ATM heterozygous (germline), DPYD wild-type. Three facts that shape every downstream decision.
-
MDT – definitive chemoRT, de-escalated dose because HPV+, further trimmed because ATM het. Concurrent cisplatin (DPYD wt = standard dosing safe). One tap commits plan-skeleton.
-
Plan designer – 60 Gy in 30 fx (de-escalated from 70 Gy because HPV+, trimmed 5% for ATM het). Constraints auto-loaded for parotid sparing. Physicist optimizes, co-signs.
-
Bulk appointments – 30 fractions, Mon-Fri, all carrying
treatment_plan_idandphase_id. -
Week 3 OTV – skin reaction G2, mucositis G2, tracking to ATM predicted curve. Continue.
-
End of treatment – summary auto-built from event log, signed attestation to her did:bio wallet. She owns her radiation dose history forever, portable across institutions.
The genome doesn’t sit in a tab. It is woven into MDT, the prescription, toxicity expectations, and the survivorship handoff. Five touchpoints, one identity, zero raw genomic data leaving the wallet.