|
| 1 | +# BioSymphony: campaign preflight runbook |
| 2 | + |
| 3 | +**Date:** 2026-05-12 |
| 4 | +**Status:** authoritative for all new campaigns |
| 5 | +**Scope:** the mandatory Stage 0 step that every BioSymphony campaign must complete before any compute is spent. |
| 6 | + |
| 7 | +This runbook tells you (a) why Stage 0 exists, (b) how to run it, (c) what to do when it complains, and (d) how to feed the catalog after the campaign so the next campaign starts richer. |
| 8 | + |
| 9 | +## Why Stage 0 exists |
| 10 | + |
| 11 | +Before Stage 0 was wired in, every campaign re-derived "what do we know about this target species + what related species share the pathway?" by hand. Prior campaigns each spent meaningful operator time on this question. The answers were good but lived only in campaign-local docs, so the next campaign re-derived them from scratch. The public catalog at `data/pathway-species-catalog.tsv` now persists those answers across campaigns. |
| 12 | + |
| 13 | +Stage 0 fixes this. It: |
| 14 | + |
| 15 | +1. **Forces** every campaign to start with a structured 5-pillar evaluation (Data / Inputs / Relevance / Novelty / Importance) before any pipeline launch is allowed. |
| 16 | +2. Pulls known producers of the target pathway from `data/pathway-species-catalog.tsv` instead of re-deriving them. |
| 17 | +3. Auto-discovers additional candidates via NCBI taxonomy walk + NCBI Datasets v2 + SRA esearch + NGDC GWH fallback. |
| 18 | +4. Produces a downstream contract (`campaign-launch-readiness.json`) that every other `genecluster_*` stage must honor. |
| 19 | + |
| 20 | +If the operator forgets to provide a comparator list, the system asks NCBI + the catalog itself rather than launching against the target in isolation. |
| 21 | + |
| 22 | +## Stage 0 contract (what downstream stages depend on) |
| 23 | + |
| 24 | +After a successful preflight, the campaign directory MUST contain these artifacts: |
| 25 | + |
| 26 | +| File | Purpose | |
| 27 | +|---|---| |
| 28 | +| `campaign-launch-readiness.json` | Downstream contract. `preflight_status == "ready"` is required for any L0→L1 stage to proceed. | |
| 29 | +| `campaign-preflight-summary.md` | Top-level Markdown report of the 5 pillars. | |
| 30 | +| `species_scout.tsv` | One row per candidate species, with assembly, SRA, scoring. | |
| 31 | +| `species_scout.json` | Full structured findings. | |
| 32 | +| `relevance-novelty-summary.md` | Human-friendly 5-section narrative. | |
| 33 | +| `seed-query-candidates.tsv` | KEGG-derived placeholder enzymes (when pathway resolves) or operator-supplied set. | |
| 34 | + |
| 35 | +If `preflight_status` is `blocked` or `needs_audit`, every `genecluster_*` script will refuse to advance the maturity ladder past `L0_control_plane_ready`. |
| 36 | + |
| 37 | +## How to run it |
| 38 | + |
| 39 | +### Quick start: operator does NOT know the comparator list |
| 40 | + |
| 41 | +```bash |
| 42 | +python3 skills/biosymphony/scripts/genecluster_campaign_preflight.py \ |
| 43 | + --target "Coptis chinensis" \ |
| 44 | + --pathway BIA \ |
| 45 | + --campaign-id coptis-bia-example \ |
| 46 | + --out-dir .runtime/coptis-bia-example-preflight \ |
| 47 | + --max-candidates 10 \ |
| 48 | + --ncbi-api-key "$NCBI_API_KEY" |
| 49 | +``` |
| 50 | + |
| 51 | +The preflight invokes the species scout, which: |
| 52 | + |
| 53 | +1. Pulls every catalog row tagged with `pathway_id=BIA` (or pathway-name match). |
| 54 | +2. Resolves *Coptis chinensis* taxonomy via NCBI E-utilities, gets `genus=Coptis, family=Ranunculaceae, order=Ranunculales`. |
| 55 | +3. Walks the genus, family, and order for related species (e.g., *Coptis teeta*, *Hydrastis canadensis*, *Berberis vulgaris*). |
| 56 | +4. For each candidate (target + ≤9 relatives), queries NCBI Datasets v2 for best assembly, esearch SRA for tissue breadth, and probes NGDC GWH plants for fallback assemblies when NCBI is empty. |
| 57 | +5. Resolves `BIA` → KEGG `map00950` and pulls the enzyme list as seed-query placeholders. |
| 58 | +6. Composes the 5-section relevance/novelty summary. |
| 59 | + |
| 60 | +### Quick start: operator KNOWS comparators (skip auto-discover) |
| 61 | + |
| 62 | +```bash |
| 63 | +python3 skills/biosymphony/scripts/genecluster_campaign_preflight.py \ |
| 64 | + --target "Coptis chinensis" \ |
| 65 | + --pathway BIA \ |
| 66 | + --campaign-id coptis-bia-example \ |
| 67 | + --out-dir .runtime/coptis-bia-example-preflight \ |
| 68 | + --comparative-species "Berberis vulgaris,Eschscholzia californica,Argemone mexicana" \ |
| 69 | + --seed-queries-tsv .runtime/coptis-bia-example-preflight/operator-seeds.tsv |
| 70 | +``` |
| 71 | + |
| 72 | +The preflight validates the comparator list against the catalog (flagging unknown / cross-pathway species) and validates the seed-queries TSV shape (required columns, controls, duplicate `query_id`, missing UniProt anchors). |
| 73 | + |
| 74 | +### Dry run (no NCBI fetches) |
| 75 | + |
| 76 | +```bash |
| 77 | +python3 skills/biosymphony/scripts/genecluster_campaign_preflight.py \ |
| 78 | + --target "Coptis chinensis" \ |
| 79 | + --pathway BIA \ |
| 80 | + --campaign-id coptis-bia-example \ |
| 81 | + --out-dir .runtime/coptis-bia-example-preflight \ |
| 82 | + --dry-run |
| 83 | +``` |
| 84 | + |
| 85 | +Dry run produces the catalog-derived report without hitting any REST endpoint. Useful for offline scaffolding. |
| 86 | + |
| 87 | +## The five-pillar report: what each section tells you |
| 88 | + |
| 89 | +### 1. Data |
| 90 | + |
| 91 | +Per candidate species: |
| 92 | + |
| 93 | +- Best NCBI assembly (accession, level chromosome/scaffold/contig, year) |
| 94 | +- NGDC GWH fallback accession when NCBI is empty |
| 95 | +- Annotation presence flag (yes / partial / unknown / no) |
| 96 | +- SRA RNA-Seq breadth: total run count + per-tissue counts (root / leaf / stem / flower / fruit / rhizome / latex / etc.) |
| 97 | +- Top 1, 3 BioProjects |
| 98 | +- Most recent submission year |
| 99 | + |
| 100 | +This is the answer to "is there anything to run on?" before you launch. |
| 101 | + |
| 102 | +### 2. Inputs |
| 103 | + |
| 104 | +If the pathway resolves to a KEGG map (`BIA→map00950`, `MIA→map00901`, etc.), the scout emits a placeholder query set (`PROPQ001…PROPQNN`) from KEGG enzymes. **These are placeholders.** Each row's `uniprot` column shows `(needs_anchor_resolution)`; the operator (or a Codex dispatch agent) must replace these with canonical SwissProt accessions before launch. |
| 105 | + |
| 106 | +Standard controls are always appended: |
| 107 | +- `POSCTRL_ACTIN` (ACT2, Arabidopsis P0CJ47) |
| 108 | +- `POSCTRL_GAPDH` (Arabidopsis P25856) |
| 109 | +- `NEGCTRL_RANDOM` (shuffled 150 aa) |
| 110 | + |
| 111 | +When the operator passes `--seed-queries-tsv path/to/seeds.tsv`, the scout uses that file directly and validates: required columns (`query_id`, `enzyme_name`, `uniprot`), presence of all three control types, no duplicate `query_id`, no missing anchors. |
| 112 | + |
| 113 | +### 3. Relevance |
| 114 | + |
| 115 | +Candidates are bucketed by taxonomy relationship to the target: |
| 116 | + |
| 117 | +- **Same family**, direct sister species (highest synteny; near-1:1 ortholog mapping expected) |
| 118 | +- **Same order, different family**, broader convergence baseline |
| 119 | +- **Different order (convergent producers)**, independent-origin signal |
| 120 | + |
| 121 | +This is the answer to "how much pathway overlap is the candidate likely to give us?" |
| 122 | + |
| 123 | +### 4. Novelty |
| 124 | + |
| 125 | +Candidates with a tracked `key_publication_pmid` in `data/pathway-species-catalog.tsv` are listed with their existing publication and the `novelty_window` field. Candidates without a tracked publication are flagged for a multi-pass literature audit. |
| 126 | + |
| 127 | +**Operator action when novelty is unclear:** trigger the lit-audit agent fan-out before committing the campaign. The audit writes back into the catalog's `key_publication_pmid` + `novelty_window` columns so the next campaign benefits. |
| 128 | + |
| 129 | +### 5. Importance |
| 130 | + |
| 131 | +Composite ranking via deterministic score: |
| 132 | + |
| 133 | +| Signal | Weight | |
| 134 | +|---|---| |
| 135 | +| Chromosome-scale assembly | +30 | |
| 136 | +| Scaffold assembly | +15 | |
| 137 | +| NGDC-GWH fallback assembly | +18 | |
| 138 | +| Annotation present | +20 | |
| 139 | +| ≥3 tissues in SRA | +15 | |
| 140 | +| 1, 2 tissues in SRA | +7 | |
| 141 | +| Year ≥ 2024 | +10 | |
| 142 | +| Year ≥ 2020 | +5 | |
| 143 | +| Catalog `comparative_value=HIGH` | +15 | |
| 144 | +| Catalog `comparative_value=BASELINE` (canonical target) | +12 | |
| 145 | +| Catalog `comparative_value=MED` | +7 | |
| 146 | + |
| 147 | +Top 3 by score are reported as "recommended comparators" plus a sequencing-priority order (NCBI fastest path first, then NGDC GWH, then de novo RNA-Seq). |
| 148 | + |
| 149 | +## What blocks a preflight |
| 150 | + |
| 151 | +| Status | Trigger | Operator action | |
| 152 | +|---|---|---| |
| 153 | +| `ready` | All checks pass | Proceed to L1 | |
| 154 | +| `blocked` | Scout produced 0 candidates OR seed-queries TSV failed validation | Inspect `status_reasons` in the readiness JSON; fix and re-run | |
| 155 | +| `needs_audit` | `--require-novelty-audit` set and `novelty-audit.md` not present | Run the literature audit, save output as `<out-dir>/novelty-audit.md`, re-run preflight | |
| 156 | + |
| 157 | +The `genecluster_*` downstream scripts grep `preflight_status` from the readiness JSON before doing anything else. If `ready` is missing, they exit non-zero with a pointer back to this runbook. |
| 158 | + |
| 159 | +## Adding to the catalog (post-campaign) |
| 160 | + |
| 161 | +After a campaign ships, enrich `data/pathway-species-catalog.tsv` with what you learned. Edit the TSV directly (it is tab-separated, 21 columns; trailing empty cells are fine): |
| 162 | + |
| 163 | +``` |
| 164 | +pathway_id pathway_name species common_name genus family plant_order |
| 165 | + best_genome_accession genome_source genome_level annotation_present |
| 166 | + rna_seq_bioprojects tissues_covered year_latest key_publication_pmid |
| 167 | + key_publication_doi comparative_value novelty_window campaign_used_in |
| 168 | + last_audit_date notes |
| 169 | +``` |
| 170 | + |
| 171 | +Recommended per-campaign updates: |
| 172 | + |
| 173 | +1. **Update `last_audit_date`** for every catalog row you touched. |
| 174 | +2. **Set `comparative_value`** from MEDIUM (predicted) to HIGH (proven) when the campaign confirmed strong synteny / cluster signal. or down to LOW when it disappointed. |
| 175 | +3. **Fill in `key_publication_pmid` / `novelty_window`** if the literature audit produced new citations. |
| 176 | +4. **Add new species rows** for any tax-walk candidate the scout surfaced that wasn't already there. |
| 177 | +5. **Reference the campaign in `campaign_used_in`** (e.g., `campaign-sp2`). |
| 178 | + |
| 179 | +## Operator quality bar |
| 180 | + |
| 181 | +- **Never bypass Stage 0.** If `preflight_status` is anything but `ready`, the campaign is not ready. The 5-pillar report is not optional paperwork. It is the difference between "we ran a campaign" and "we ran a defensible campaign." |
| 182 | +- **Catalog rows are evidence, not opinion.** When you update `comparative_value`, cite the specific cluster/anchor evidence. When you fill `key_publication_pmid`, the publication must actually mention the species + pathway pair. |
| 183 | +- **Treat KEGG placeholder queries as TODOs.** They never go to a launch bundle as-is. Either an operator or a Codex agent fan-out resolves UniProt anchors first. |
| 184 | +- **Always include controls.** Positive (ACTIN, GAPDH) and negative (shuffled). Stage 0 enforces this on user-supplied TSVs but does not enforce it on the placeholder set. You do. |
| 185 | + |
| 186 | +## Cross-references |
| 187 | + |
| 188 | +- `skills/biosymphony/SKILL.md`, Stage 0 section, mandatory contract |
| 189 | +- `skills/biosymphony/scripts/genecluster_campaign_preflight.py`, wrapper script |
| 190 | +- `skills/biosymphony/scripts/genecluster_species_scout.py`, fan-out scout |
| 191 | +- `data/pathway-species-catalog.tsv`, public pathway × species catalog used as institutional memory |
0 commit comments