Curating a GO interpretation of a gene set
You are adding (or reviewing) one curation/genesets/<SET>.yaml — a curator's
GO-term interpretation of a non-GO gene set — to a hand-curated gold standard
that doubles as a precision/recall benchmark for genesets-rs. One YAML per set.
Read first: curation/README.md (the categories, recovery_status, insight,
sources, series, evidence — the authority) and the schema
curation/schema/genesets_interpretation.yaml (slots + enums). Match the house
style of an existing file, e.g. curation/genesets/TRAVAGLINI_LUNG_CILIATED_CELL.yaml.
The one rule that governs everything: ground in the actual membership
Before asserting any biology, read the set's real gene list. Do not curate
from the cell type's textbook markers — curate from what is actually in the set.
This is what makes recovery_status honest and is the most common way agents go
wrong (e.g. a fetal "photoreceptor" set that lacks RHO/PDE6; a "chromaffin" set
that lacks TH/DBH; a "pro-B" set dominated by cell-cycle genes).
How to get the membership:
- MSigDB sets (
MSIGDB:<NAME>, collections C8/C2/H/…):_idon mygeneset.info equals the MSigDB set name. Fetch withscripts/fetch_mygeneset_query.py(or query_id:"<NAME>"directly). The full list is also what gets folded into the eval. - Literature sets (
LIT:ids): the defining paper is the identity, membership, and evidence. For short, explicit lists (GWAS loci, CRISPR hits, causal-gene panels) capture the genes verbatim from the primary source, HGNC-normalize, and append tocuration/genesets/lit_members.gmt(tab-sep:<gene_set_name>\tcurated_literature_membership\tGENE1\tGENE2…). The GMTset_idMUST equal the YAMLgene_set_name.
Per-term: the three orthogonal axes
For each association set category, confidence, specificity, seed_source,
recovery_status, and (on core/supporting terms) insight, plus a curator_note
and optional evidence. Aim for ~5–7 associations: the cell/state's defining
core terms (a process + a component), 1–2 supporting, at most one nonspecific
only if the membership clearly carries it (don't invent a housekeeping hit).
category— the biology (authoritative; NOT driven by annotation state).core_process/core_component/supporting_process/marker_driven_plausible/nonspecific/false_association. A term that is biologically core stays core even if no annotation supports it.recovery_status— grounded in the actual membership (orthogonal to category). Name the specific present/absent genes in thecurator_note:annotation_supported— carrier genes are in the set; enrichment recovers it.annotation_gap— relevant genes ARE in the set but GO annotation is too shallow. The gap is GO's (a GO-annotation curation target).seed_source: curator_added.membership_gap— the carrier genes are NOT in the set (legacy/incomplete set, or a fetal signature lacking its mature effectors). The term still belongs in a complete description.seed_source: curator_added.
insight— interpretive value (only on core/supporting). The tightened rule:confirmatory— entailed by the set's construction/identity (the default for a marker signature; ALL generic hallmarks — proliferation, apoptosis, generic PI3K/MAPK, known disease OXPHOS, expected immune terms).mechanistic— a SPECIFIC, non-obvious process not entailed by construction; a genuine enrichment insight. Use sparingly (~10% of terms corpus-wide). When in doubt, it's confirmatory.
Anti-hallucination discipline (non-negotiable)
- OLS-verify every ontology id+label (GO/CL/UBERON/MONDO/…) before writing it.
Use the OLS MCP (
mcp__claude_ai_OLS__search/fetch). Confirm the id resolves to the exact label and is not obsolete. Never invent ids; if unsure, search by label and use the returned id. - Reject obsolete terms. The validator's 4th gate sweeps OAK
obsoletes()and fails the build. Thesqlite:obobuilds retain labels for obsolete classes, so an obsolete id paired with its old label passes id+label validation but fails here (e.g.GO:0062023collagen-containing ECM →GO:0031012;GO:0050663cytokine secretion →GO:0032635). - Evidence snippets are verbatim or absent. Include an
evidenceitem with asnippetONLY if you retrieved the exact text from the cited paper (PubMed MCP) and copied it character-for-character — the reference-validator substring-checks it and fails on any mismatch. Otherwise usecurator_noteonly. Never fabricate. Any item with asnippetmust also carry areference. - Cite the right paper. Verify PMIDs. (The Descartes fetal atlas is
PMID:33184181, not32848094— a recurring trap.)
Pairs / series
Link contrasting poles of one axis with series (a shared SERIES:<NAME> id) and
series_role (this set's pole, free text). Add the field to both/all poles
(edit the partner files too). The eval checks that opposite poles resolve to
contrasting GO interpretations — e.g. SERIES:PANCREATIC_ISLET alpha/beta/delta,
SERIES:MYELINATING_GLIA central/peripheral.
Validate, then regenerate the manifest
# 4 gates: linkml structural, term id+label, reference snippet, obsolescence
uv run --project python/genesets-workflows --extra curation \
genesets-workflows curate validate curation/genesets/<SET>.yaml # exit 0 = pass
Iterate until exit 0. Validate the whole corpus before a PR with just curate-validate.
Regenerate curation/genesets/manifest.tsv after a batch (columns:
gene_set_id, collection, context_term, context_type, context_label, series, series_role) by looping every YAML through model.load_interpretation. Run
just curate-test (29 unit + 5 doctest).
Fold the set into the eval (so it becomes scoreable)
A set is only evaluable if its membership is in the eval's queries.gmt. MSigDB
sets come from the mygeneset base; LIT: sets come from lit_members.gmt. After
adding sets, rebuild queries.gmt and re-run the evaluate-enrichment skill.
The guardrail (read evals/iba_vs_benchmark/README.md)
The eval measures the gold; it must never refit it. category is the scored
truth. recovery_status/insight are curator judgments adjudicated against GOA
facts during curation — never auto-updated to match whatever a tool happened to
recover (that would make recall-vs-gold circular). When the eval surfaces a
disagreement (a gap_recovered term), it is a review item, decided on the merits,
not an automatic relabel.