OpenOnco
UA EN

Capabilities

A declarative rule engine for oncology recommendations. JSON profile in — Plan with two alternative tracks (standard + aggressive) out, every claim shipping with a citation to its source.

STUB status across all clinical content. Dual sign-off: 15/806 (CHARTER §6.1 requires two Clinical Co-Lead approvals). This is a proposed plan: structured data + algorithm + sources are in place, but without dual sign-off. Decision-support tool, not a medical device. State as of 2026-06-11 11:51 UTC.
92
diseases in KB
664
indications (230 1L · 172 2L+)
384
treatment regimens
298
drugs (ATC/RxNorm)
594
red flags
444
cited sources
16
clinician skills (MDT)
15/806
with dual sign-off
01Not a black box
Every algorithm step in the trace. LLM doesn't make clinical decisions (CHARTER §8.3).
02Every claim with a citation
source_id + position + paraphrased quote + page/section. Render-time guard.
03Privacy by design
CLI / Pyodide / Python import. No server. Patient JSON never leaves the machine.
04Plan stays alive
revise_plan() refreshes the recommendation as new biomarkers or findings arrive.

Coverage matrix

/diseases.html — per-disease table: counts of biomarkers / drugs / indications / red flags, 1L+2L checkmarks, fill% and verified%. Grouped by lymphoid + myeloid hematology and solid tumors. Canonical UI for /disease_coverage.json. → View matrix

/gallery.html — 586 cases (159 hand-curated + 362 verified variant profiles + 65 auto-base). Each — a full Plan or Diagnostic Brief with all citations. Disease-grouped drill-down. → View examples

6-stage request processing

The clinician feeds the engine a JSON profile. The engine runs 6 sequential stages and returns a Plan with ≥2 tracks (CHARTER §15.2 C6 — alternative never hidden).

Stage 1
Disease + Algorithm resolve
disease.id + line_of_therapy + disease_state → Algorithm entity.
Stage 2
Findings flatten
Merges demographics + biomarkers + findings into one flat dict.
Stage 3
RedFlag eval
594 RFs against findings (any_of/all_of/none_of with thresholds).
Stage 4
Algorithm walk
Decision tree step by step. Trace records fired_red_flags at each node.
Stage 5
Tracks materialize
Indication → tracks (standard / aggressive / surveillance) with biomarker filter.
Stage 6
Per-track resolve
Indication → Regimen (with phases) + Monitoring + SupportiveCare + AccessMatrix.

CIViC actionability

Actionability data used to come from OncoKB — but their ToS blocked non-commercial public derivatives (conflict with CHARTER §2). We migrated to CIViC (CC0) (WashU). The engine reads a local nightly YAML snapshot (knowledge_base/hosted/civic/<date>/) — deterministic + offline. The fusion-aware matcher handles both point mutations (BRAF V600E) and fusions (BCR::ABL1). Render: ESCAT tier — primary, CIViC evidence rating — in details. Monthly refresh CI opens a PR with the diff.

Multi-phase regimens

Regimen.phases is an ordered list of named blocks (induction → consolidation → maintenance), each with its own cycle schedule and transition trigger. Real-world protocols (R-CHOP × 6 → maintenance, AML 7+3 → HiDAC consolidation, axi-cel bridging → infusion). bridging_options — bridging regimens between phases (for CAR-T). Legacy single-phase YAMLs auto-wrap into one-phase form via auto_wrap_legacy_components().

Citation guard — 3 layers

A three-layer verification system — three places where we catch unsourced claims:

LayerWhereWhat
L1 · Loader YAML load (Pydantic) SRC-* referential integrity. Unknown SRC-ID → load fail.
L2 · Verifier Contributor PR (CI) Three-layer grounding: source exists, paraphrase grounded, anchor in section.
L3 · Render HTML output No citation → warn-badge (lenient) or skip cell (strict_citation_guard=True).

Three ways to run

CLI
Locally

python -m knowledge_base.engine.cli --patient profile.json --render plan.html. Offline.

Pyodide
In the browser (try.html)

Python WASM + micropip + engine bundle (~2.4 MB). First load 8-15 s, then like a local CLI. Service worker for offline.

Library
Python import

from knowledge_base.engine import generate_plan, revise_plan — EHR / CSV / batch testing. Stateless, deterministic.

What the engine reads from a profile

Only structured fields with explicit semantics. Unknown fields are ignored — no hidden effects.

CategoryFieldsHow we use it
Disease (entry point) disease.id · icd_o_3_morphology · line_of_therapy · disease_state determines which Algorithm to run
Diagnostic mode suspicion.lineage_hint · tissue_locations · presentation activates DiagnosticPlan instead of Plan
Demographics age · ecog · fit_for_transplant · decompensated_cirrhosis · pregnancy_status filter on Indication.applicable_to.demographic_constraints
Biomarkers any BIO-X from KB: BIO-CLL-HIGH-RISK-GENETICS, BIO-HCV-RNA, … trigger RedFlags, filter Indications, map to CIViC
Findings hundreds of structured fields — dominant_nodal_mass_cm, ldh_ratio_to_uln, tp53_mutation, … thresholds in RedFlag triggers
Prior tests prior_tests_completed: [TEST-IDs] excludes already-completed tests from workup_steps

What the engine returns — Plan

FieldContents
tracks[]≥2 alternative tracks (default first): indication + regimen (+ phases) + monitoring + supportive_care + contraindications
access_matrixper-track aggregate: registrations, reimbursement, cost ranges, AccessPathway. Stale-cost warning > 180 days.
experimental_optionsthird track — enumerate_experimental_options() queries ClinicalTrials.gov v2. 7-day TTL cache.
actionability_hitsCIViC matches with ESCAT-primary + variant, evidence rating, clinical significance, source citations
fda_complianceFDA Criterion 4 fields: intended_use, patient_population_match, algorithm_summary, automation_bias_warning
tracestep-by-step walk_algorithm history: step / outcome / branch / fired_red_flags
warningsschema/ref errors, time_critical disqualifications, missing data hints, citation-guard warnings
supersedes / superseded_byversion chain between plans for the same patient

Optionally enabled: MDT brieforchestrate_mdt() adds required/recommended/optional roles from 16 virtual specialists + open questions + provenance graph.

Plan updates — revise_plan()

Three legal transitions + one forbidden. The previous plan is not mutated — a deep copy is returned with superseded_by set. Per CHARTER §10.2, old versions persist indefinitely.

FromChangeTransitionResult
DiagnosticPlan vNsuspicion onlydiagnostic → diagnosticDiagnosticPlan v(N+1)
DiagnosticPlan vNhistology confirmeddiagnostic → treatment (promotion)Plan v1
Plan vNupdate with histologytreatment → treatmentPlan v(N+1)
Plan vNhistology removedILLEGAL — ValueError, CHARTER §15.2 C7
Privacy. Patient JSON never leaves the user's machine. No logs, no DB. Reproducibility: Plan.knowledge_base_state.algorithm_version records the KB version → same input + same KB = same output.

Open Questions — engine refuses to decide without data

Instead of a silent default, the engine explicitly flags which fields are missing and which test or report is needed (MDT_ORCHESTRATOR_SPEC §3). Rendered into the Plan as a separate section, never hidden.

CodeTriggerWhat the engine emits
Q1Histology not confirmed«Treatment Plan generated against ICD-O-3 code only; confirm primary histology before therapy»
Q2Stage missing«Lugano/Ann Arbor stage required for confident risk-stratification»
Q3RF clause incomplete«Cytogenetic panel incomplete; high-risk status assessed with partial data»
Q4Biomarker missing«IGHV mutation status + FISH del(17p) required to confirm 1L recommendation»
Q5Performance status missing«ECOG required for transplant-eligibility assessment»; falls back to conservative default
Q6Drug not reimbursed«D-VRd: daratumumab not currently reimbursed; verify funding pathway»
DQ1-4Diagnostic-mode: tissue / lineage / presentation / hypotheses missinglowers workup match confidence; lineage_hint + tissue dominate
Why no silent default: CHARTER §15.2 C6 (anti automation-bias) — the engine cannot pretend to know when it doesn't.

Personalization gaps — deliberate

«Personalization» in OpenOnco is rule-based selection from a fixed catalog, not AI-generation. Deliberate architectural choice (CHARTER §8.3).

Gap 1

No per-patient dose calculation

Regimen stores the standard dose (bortezomib 1.3 mg/m²), not multiplied by patient BSA, not adjusted automatically for CrCl 30. By design — to avoid FDA device classification.

Gap 2

No response-adapted cycles

Regimen pins total_cycles: 6 + 2 maintenance. Not adapted automatically by response (PR vs CR after PET2). Re-staging via a separate revise_plan.

Gap 3

Genomic matching limited to CIViC

Outside CIViC (rare, novel variants) emits a warning «no actionability evidence», without creative interpretations.

Gap 4

SupportiveCare identical across cohort

PJP prophylaxis attached to D-VRd for everyone — the engine doesn't know alternatives (dapsone instead of bactrim). The clinician substitutes.

Gap 5

No cumulative-toxicity tracking

2L plan for a patient who got bortezomib in 1L with grade 2 neuropathy — the profile doesn't carry prior_treatment_history as a structured field; the clinician interprets manually.

CHARTER constraints — will not change

Principled architectural decisions that gate FDA / clinical safety.

§8.3

LLM doesn't decide clinically

LLM only: boilerplate, doc drafts, extraction (with human verification), translation with clinical review. Not: regimen choice, doses, biomarker interpretation.

§15.2 C7

No histology — no Plan

Treatment Plan only if disease.id is confirmed. Otherwise DiagnosticPlan mode. revise_plan treatment → diagnostic is forbidden.

§15.2 C5

No time-critical

Not intended for emergency oncology (oncologic emergencies). Indication with time_critical: true → disqualification warning.

§6.1

Two-reviewer merge

Any change to clinical content needs 2 of 3 Clinical Co-Lead approvals. Without that — STUB.

§15.2 C6

Anti automation-bias

Always ≥2 tracks side-by-side. Alternative is never buried, never «click to expand». The clinician sees a choice, not a directive.

§9.3

Patient data never in repo

patient_plans/ gitignored. Site shows only synthetic examples. Telemetry forbidden without explicit consent.

Never list — what the engine never does

Never

Hide the alternative track

Both recommendations are always shown. The UI has no «expand to see alternative» pattern.

Never

Generate Indication via LLM

Everything from the curated KB. No matching Indication → warning, not «creative invention».

Never

Modify doses

Doses come from the standard NCCN/ESMO. Adjustments only via explicit dose_modification_rules.

Never

Judge «which is better»

The algorithm picks a default but doesn't claim it's superior. The clinician has full autonomy — automation_bias_warning.

Never

Interpret imaging

«Bulky disease» arrives as a structured field, not from image analysis. Image analysis = device classification.

Never

Cohort matching

«N patients chose X in M% of cases» — requires a persisted patient registry + privacy review. Not yet.

Current coverage — STUB status and gaps

CategoryStateMeaning
Diseases with full chain77 / 92The rest are partially modeled
Indications 1L230First line for all 92 diseases
Indications 2L+17234 heme + 21 solid. Other solid 2L+ partial.
Pediatric oncology0Out of MVP scope — separate track
Radiation therapypartialRT in multimodal Indications; not modeled as a standalone entity
Surgerynot modeledSurgical oncology indications absent
Formulary live-feedstatic flagHard-coded on regimens; not auto-refreshed
Reviewer dual sign-off15/806Primary bottleneck metric — capacity plan: 806 → ≥85% verified
Live gap dashboard→ linkBuild-generated audit (sign-off, solid 2L+, surgery, RT, supportive care)
What STUB does NOT mean: structured data + algorithm + sources are already in place. What STUB means: didn't pass Clinical Co-Lead dual sign-off. «Proposed plan», not «approved plan».

Clinician workflow

The engine prepares for a tumor board, it does not replace one. The clinician: 1) verifies sources (every claim cited, guard already dropped uncited cells) → 2) closes Open Questions (orders tests, calls revise_plan) → 3) adapts to the patient (doses, supportive care, regional availability) → 4) discusses at the tumor board (MDT brief — structured agenda). Engine: draft. Clinician: final.

TaskTorrent — verify algorithms with your AI's tokens

The biggest gap — 15/806 dual-reviewer sign-off. The bottleneck doesn't dissolve with new code — it dissolves through contributors with AI tools who pick up structured chunks of work.

1
What it is

A maintainer publishes a «chunk» — one self-contained task (~100k–300k tokens): «reverify BMA evidence for DLBCL × 17 entities» or «backfill source-license for 8 sources». A contributor claims the chunk, AI executes, PR opens.

2
What you need

An AI tool with a token budget (Claude Code Pro+, Codex, Cursor, ChatGPT with web). GitHub + gh CLI. Python 3.10+. ~1-3 hours of your time. No clinical expertise required — you trigger structured drafting; the clinical co-leads sign off.

3
8-line bootstrap

Copy the 8-line prompt from CONTRIBUTOR_QUICKSTART.md into your AI agent. It finds an available chunk, claims it, runs the work, runs the validator, opens a PR.

4
What happens to the PR

The maintainer checks the mechanical part (validator, schema). A Clinical Co-Lead does a sample review of the semantic part (CHARTER §6.1). Merge → sidecar landing → upsert into hosted KB → render. Attribution recorded in _contribution_meta.yaml.

Impact. Every verified BMA is one actionability claim we can render as «approved» instead of «STUB». One contributor with Pro+ tokens in an evening can push 10-20 BMAs through signoff prep — about a week of work for one person under any other model.

Recent activity

Over the last 4 days TaskTorrent saw 7 waves, dozens of chunks, ~73 BMA candidates, 23 BMA drafts ready for clinical signoff, 53 source stubs, 1,251 UA-language fields drafted. Recent structural updates:

  • CIViC pivot — engine + 29 BIO + 399 BMA YAMLs migrated off OncoKB schema; monthly snapshot refresh CI.
  • Multi-phase regimens (PR1-3)Regimen.phases, bridging_options, phases-aware render, back-compat auto-wrap.
  • Citation guard L3 — render-time check on every BMA cell.
  • Coverage matrix/diseases.html per-disease drill-down.
  • 586 cases in gallery — Phase 2 chunked feat: ~60 new hand-curated in 4 days.