The task came with its measurement: 23,188 mods_kg_entity rows with no mods_kg_entity_source row and no relation, five of them among the eight genes named JAK2, which is part of why gene name matching had become ambiguous. The brief named the likely creators: the two entity-merge scripts, or an aborted RTX-KG2 ingest. It was neither. The timestamps pointed elsewhere first. DRKG’s triples file was written on 2026-05-17 at 06:01:03, and the first orphan was created two seconds later. DRKG’s resume checkpoint was last written on 2026-05-28 at 16:04, line 2,565,171 of 5,874,261, thirteen minutes after the last orphan. Then the fingerprints: 4,247 synthetic drkg: CURIEs, ATC: drugs and NCBITaxon: “biomarkers” from DRKG’s own entity types, and compound namespaces no other source brings. To get a count rather than a likeness, I matched every orphan to DRKG’s entities under the connector’s own CURIE rules. All 23,188 matched, 21 of them only after case-folding (rhea: written by DRKG, RHEA: returned by Node Normalizer).
The commit record explained the rest. A session on 2026-05-29 says DRKG “was fully deleted from canonical”. It deleted the relations and the source rows. The entities stayed, because the delete was done by hand and skipped the orphan sweep that the repository’s own per-source wipe runs. Issue #736, opened this morning to ingest DRKG properly, says the connector “has never run on prod”. It ran for eleven days, and its checkpoint is still on disk: a plain re-run would trust it and silently skip the first 44% of the file.
Two corrections of my own. My first sweep for references hung on prod. A 23,188-element = ANY(...) against a 9.4-million-row backup table with no index kept three parallel backends busy for eight minutes before I noticed. I cancelled my own query and rewrote every large check as a hash semi-join; the whole sweep then took seconds. Then I wrote “mostly non-human” about the genes whose names resolve uniquely to an orphan, from an alphabetical sample of sixty that happened to open on frog and Arabidopsis symbols. Classifying all 2,326 by the species their stored cliques name gave 52 human, 964 non-human and 1,310 that name no species. That changed the issue, and it surfaced what deleting all of them would cost: 52 human non-coding genes exist in the graph only as these orphans.
The delete script plans read-only, refuses on any reference outside the three foreign keys, needs the count and id hash of a reviewed dry run, and checks the transaction’s own statistics so a cascade cannot take a relation with it. Two sabotage runs showed each guard catching what the other misses. Richard approved deleting all 23,188.
The run did not delete them all. Before applying I re-ran the dry run, and the set had shrunk. OncoKB’s re-annotation that evening had attached adagrasib, tepotinib and asciminib to three of the orphans, and attached them correctly. That contradicted what I had told Richard: that a hint-less record attaching to an orphan was the harm. For a gene of another species it can be. For a drug under the CHEBI or UNII id Node Normalizer chose, it is usually the right answer. Meanwhile #708’s species scoping had merged, and with its taxon backfill run, the gene orphans now blocked only two human-scoped names. I took the corrected picture back to Richard before deleting anything. A census split the orphans by what a name match can do with them. 15,132 can never be a candidate: ATC classes, drkg: synthetics, PUBCHEM and UMLS drugs, GO terms. The other 8,053 can be. Richard chose to delete only the first group. The script deleted exactly 15,132 rows, with a backup in the main checkout’s kg_backups. An independent check found the entity count down by exactly that, and source rows, relations, the retired-relation history and the curie cache unchanged. Every orphan left is a name-match anchor, and all eight JAK2s remain; #708’s species scoping, not this delete, is what keeps CIViC, OncoKB and PharmGKB off the five that belong to other species.