| name | decision-synthesizer |
| description | Use when synthesizing per-trial gating + risk + efficacy outputs into a Top-N decision report with diversity bucketing, Goals-of-Care trigger, and vs-SoC head-to-head. Triggers as the final synthesis step in clinical-trial-matching after trial-gater + trial-risk-annotator + trial-efficacy-contextualizer have run. Replaces v1.7.x synthesis/decision_paths.py + goals_of_care.py + consistency_check.py. |
| license | MIT |
| metadata | {"author":"CancerDAO","version":"2.0.0","parent_skill":"clinical-trial-matching"} |
decision-synthesizer
You produce the final decision_report.json that drives the patient-facing HTML report. You read the aggregated per-trial analysis (gating + risk + efficacy) plus the patient profile, and emit a structured report with Top-N decision paths, Goals-of-Care section (when triggered), and patient consistency flags.
The bugs this subskill exists to fix
v1.7.x had three Python modules that all had quality issues:
decision_paths.py — produced empty patient_summary={}, feasibility_score=None for paths despite the synthesizer printing correct values to stdout. JSON serialization broke. Also picked a KRAS G12D drug class trial as #3 path for a KRAS G12C patient because the diversity bucket forced "alternative mechanism" without checking class compatibility.
goals_of_care.py — used treatment_lines_completed (which excludes ongoing line) to compare against ontology thresholds. A patient on L3 with treatment_lines_completed=2 never triggered GoC even when ontology said CRC L3+ is GoC-relevant.
consistency_check.py — emitted empty consistency_flags for patients with severe comorbidity loads, conflicting treatment timelines, or unusual responses (e.g. PR after multiple progressions).
Inputs
{
"patient": { },
"analyzed_trials": [
{
"trial_id": "NCT...",
"title": "...",
"phases": [...],
"sponsor": "...",
"interventions": [...],
"china_sites": [...],
"feasibility_score": 0.961,
"feasibility_dims": {...},
"gating": { ...trial-gater output },
"risks": [ ...trial-risk-annotator output ],
"efficacy_context": { ...trial-efficacy-contextualizer output }
}
]
}
Output
{
"report_version": "v2.0.0",
"generated_at": "2026-05-07T12:34:56Z",
"patient_summary": {
"summary_text": "string",
"cancer_type": "CRC",
"mutations": ["KRAS G12C"],
"treatment_lines_completed": 2,
"current_therapy_ongoing": true,
"key_comorbidities": [...]
},
"consistency_flags": [
{
"flag": "string description",
"severity": "info | warn | alert",
"evidence": "what in the patient profile triggered this"
}
],
"goals_of_care": {
"triggered": true,
"reasons": [
"CRC L3 progression on prior FOLFOX/KELOX+IO+Apatinib; entering L4",
"Median OS at L3+ mCRC per ontology: ~6 months",
"Severe CV comorbidity (HTN3 + CAD + post-stenting) constrains future regimen tolerability"
],
"discussion_recommendation": "Recommend formal Goals-of-Care discussion before initiating next line. Frame trial enrollment as one option among several (palliative care, hospice, comfort-focused care, continuation of cytotoxic SoC). Patient and family should hear realistic prognosis at L4 mCRC (median OS ~6mo) before committing to trial logistics (cross-city travel, screening burden, possible Phase 1 sub-therapeutic dosing)."
},
"decision_paths": [
{
"rank": 1,
"role": "primary | secondary | secondary_overseas | secondary_cell_therapy | alternative_mechanism",
"trial_id": "NCT...",
"trial_title": "...",
"sponsor": "...",
"phase": "PHASE2",
"china_sites_count": 11,
"feasibility_score": 0.961,
"feasibility_dims": {...},
"rationale": "string",
"efficacy_snapshot": {...from contextualizer},
"vs_soc": {...from contextualizer},
"risks": [...from annotator],
"blockers_satisfied": [...],
"blockers_pending": [...],
"alternatives_comparison": [
{"trial_id": "NCT...", "reason_not_chosen": "..."}
],
"consequences_of_skipping": "string — what happens if patient doesn't pursue this path",
"estimated_timeline": {
"screening_window": "2026-05-07 to 2026-05-21",
"earliest_first_dose": "2026-05-28",
"critical_path_steps": ["string", ...]
}
}
],
"soc_benchmarks": [
{
"regimen": "string",
"expected_orr": 0.26,
"expected_pfs_months": 5.6,
"evidence": "trial name"
}
],
"match_inventory_size": {"match": 30, "conditional": 15, "exclude": 49},
"v2_summary": {
"total_trials_analyzed": 45,
"verified_real_nct_ids": 45,
"decision_paths_emitted": 3,
"goc_triggered": true,
"consistency_flags_count": 2,
"redundancy_flags_count": 0
}
}
Process
Step 1 — Patient summary
Echo the patient summary from patient.json plus 1-paragraph synthesis.
Step 2 — Consistency check
Look for internal inconsistencies in the patient profile:
- Treatment timeline gaps (e.g. "L1 ended 2023-01, L2 started 2023-08" — gap of 7 months unexplained?)
- Response classification mismatches (e.g. "L1 PR" but baseline cancer was metastatic at diagnosis — was it really PR or just stable?)
- Comorbidity vs treatment compatibility (e.g. severe CV disease + recent anti-angiogenic without mention of cardiac monitoring)
- Lab value anomalies vs treatment context (e.g. TSH up + on PD-1 drug — irAE? was it managed?)
- Missing standard workup (e.g. CRC patient without recent CEA, or without HER2/MMR results)
Emit consistency_flags as an array. Severity: info (note for completeness), warn (clarify before proceeding), alert (must resolve before any treatment decision).
Step 3 — Goals-of-Care trigger
Trigger GoC discussion if ANY of:
- Patient is on or progressed past Nth line where ontology median OS < threshold months. Use
clinical-trial-matching/data/clinical_ontology.json:cancers.{X}.median_os_months_at_line for thresholds; default threshold 6 months.
- Critical fix from v1.7.x: count current ongoing line in this calculation. If
patient.current_therapy_ongoing == true, evaluate as if patient is at treatment_lines_completed + 1 for ontology lookup.
- Patient has rapid progression (≤4 cycles) on most recent regimen
- Patient ECOG ≥2 OR KPS ≤60
- Patient has significant cumulative comorbidity burden (≥3 serious comorbidities, or any single life-limiting one)
- Patient is in Phase 1 dose-escalation only options with no Phase 2/3 alternatives
If any trigger fires, emit goals_of_care.triggered = true with reasons and a discussion_recommendation paragraph.
Step 4 — Top-N decision paths (diversity bucketing)
Select Top-N (default N=3) from the matched trials, prioritizing both quality and diversity:
Step 4a — Filter
- Drop verdict=exclude
- Keep verdict=match and verdict=conditional
Step 4b — Sort by composite score
composite = 0.5 * feasibility_score + 0.3 * (1 - confidence_penalty) + 0.2 * evidence_tier_weight
where evidence_tier_weight: trial_specific=1.0, mutation_class=0.7, drug_class=0.5, no_data=0.2
Step 4c — Diversity bucketing (avoid 3 same-mechanism paths)
Allocate slots:
- 1 slot: highest composite score (the "primary path")
- 1 slot: best alternative mechanism (different drug class)
- 1 slot: best cell therapy OR best different-region path (overseas if patient willing)
If a slot has no qualifying candidate, leave the slot empty (don't fill with a worse-fit path just for diversity).
Step 4d — Per-path narrative
For each chosen path:
- role
- rationale
- efficacy_snapshot (from contextualizer)
- vs_soc (from contextualizer)
- risks (from annotator) — REQUIRED to be cancer-context-grounded
- blockers_satisfied / blockers_pending (from gater)
- alternatives_comparison: 1-2 similar trials with reason for non-selection
- consequences_of_skipping: 1-2 sentence narrative
- estimated_timeline
Step 5 — SoC benchmarks (cross-cutting, not per-path)
Pull the patient's relevant SoC options from any of the path's vs_soc data, dedupe, list as a top-level soc_benchmarks array. This drives the report's "标准治疗对照" section.
Step 6 — Cross-validation guardrails
Before emitting, verify:
- Every path's risks pass the cancer-context grounding check (no PDAC narrative on CRC paths, etc.)
- Every path's efficacy_snapshot.applies_because actually applies to this patient's mutation
- No path with R2-hard, R3-hard, or hard exclusion criteria slipped through
- If
goc_triggered=true and Top 3 paths are all Phase 1 dose escalation, add a flag: "All recommended paths are early-phase; review GoC discussion carefully"
- If
redundancy_flags_count > 0, ensure each redundant trial's path narrative mentions the off-trial alternative (e.g. "Sotorasib + panitumumab is FDA-approved for this indication and may be accessible without trial enrollment")
Output schema
See rules/output-decision-report-schema.md for full JSON contract.
Reference