Zero of fifteen, again: the same worklist, the same wrong intermediate answer of thirteen, and the third recurrence of a gap list that cannot see a decision
also called 0 of 15 were gaps, third time · the unwritten dispatch targets are not gaps · ledger-staleness-audit regenerated a resolved worklist · an id-only resolver always returns 13
An old audit file listed fifteen genes as promised-but-never-written. None of them is actually a gap: the project had already written, or explicitly decided against, every one. This is the third time that same list has been mistaken for real work.
The same thing, for a scientist
`analyses/ledger-staleness-audit` holds `unwritten_dispatch_targets`, **15 gene ids** past dispatch plans named and no beat delivered. **0 of the 15 is a gap** [E1]. | symbol | `is-symbol-covered.py` verdict | where the decision actually lives | |---|---|---| | `H3F3A` | COVERED | `variant-h3-3` / `protein-histone-h3-3` carry it as an alias; the latter is titled "the reason this graph should not file it as `gene-h3f3a`" | | `H3F3B` | COVERED | same two entries | | `TNFRSF1A` | DECLINED | `mechanism-il1-irak-axis-in-leukaemia-stem-cells`: *"which is why it gets an entry and TNFRSF1A, MYD88 and TRAF6 do not"* | | `MYD88` | DECLINED | same sentence | | `TRAF6` | DECLINED | same sentence, plus a bounded-rejection grade in `ana-nfkb-upstream-enumeration-and-bounded-absences` | | `MAP3K7` | DECLINED | `ana-nfkb-upstream-enumeration-and-bounded-absences`, as a table row: "MAP3K7 (TAK1) | O43318 | 606 | 3 | **0** | bounded absence" | | `KAT6B` | DECLINED | `ana-no-hdac-inhibitor-result-in-this-disease-attributes-to-an-enzyme` | | `SIRT6` | DECLINED | same entry | | `HDAC6` | no match | but named in that same entry under the heading **"Enumerated and dropped as targets"**, with its query and 0 records | | `IL1R1` | no match | named in `ana-nfkb-upstream-enumeration-and-bounded-absences`, `mechanism-il1-irak-axis-in-leukaemia-stem-cells` and `gene-tnf` | | `IRAK1` | no match | named in both NF-kB/IL1 entries | | `IRAK4` | no match | named in both NF-kB/IL1 entries | | `NFKBIB` | no match | a table row in the enumeration entry | | `NFKBIE` | no match | a table row in the enumeration entry | | `NAP1L1` | no match | **not an interactor** - its only substantive mention is as a one-patient MLLT10 fusion partner in `breakpoint-kmt2a-partner-frequency-by-age-lineage` | 🔴 **The failure reproduced its own history step for step.** Cycles 65-66 worked this identical list and reached 0 of 15. The intermediate wrong answer recorded from cycle 65 was **"13 survive, re-checked with a resolver I built - the resolver only checks ids"**. In cycle 142 I built an id-and-alias resolver by hand, got **13**, wrote an entry titled *"...are thirteen..."*, and committed it. **The same list, the same instrument defect, the same number.** That entry is now superseded. 🔵 **The project already ships the right instrument and I did not run it.** `scripts/is-symbol-covered.py` scans corpus **prose**, not ids, and returns a verdict my matcher could not express: **`DECLINED ON PURPOSE - the corpus says so in prose`**. It exists because of the cycle-65 failure. Running it on 15 symbols is one loop and it printed the refusal sentences verbatim. 🟠 **And the corpus had written the guard against this exact error.** The HDAC entry says, in the sentence before its dropped-target list: *"recorded so a future cycle can tell a considered dismissal from an unasked question."* A past cycle anticipated a future cycle mistaking its refusals for gaps, wrote the warning, and the warning did not reach me because **I never opened the entry** - the id-existence check told me there was nothing there to open. **The consequence for the standing priority.** The PI's instruction is to map every interactor, one entry per thing. This worklist offered 15 and supplies **none**: nine are an NF-kB/IL1 axis a past beat enumerated with queries and counts before declining most of it, four are chromatin enzymes declined on DepMap and literature grounds, two are H3.3 filed correctly as a protein and a variant, and one was never an interactor. **Re-opening a reasoned rejection costs a beat to re-derive a conclusion already written down.**
Why four rounds of mechanical checking converge on the wrong answer
Every check I ran was sound and answered the wrong question:
- Do the 15 ids exist? No. (True, and uninformative.)
- Do the mention counts reproduce? Exactly - 2, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 5, 10, 12, every one identical to the stored value. Perfect agreement, because both derivations asked the same question. Reproducibility measured consistency, never validity.
- Do aliases cover them? Caught 2, missed 12, and produced a false positive -
TNFRSF1Areported as covered bygene-erg, because I put the generic aliasp55in the lookup and ERG carries it. - Prose scan (
is-symbol-covered.py) - caught 8 outright and pointed at the entries holding the other 6.
🔴 A gap list is built from absence, and absence is precisely the wrong signal for finding what was decided. This corpus records refusals inside entries - in prose, in table cells, in other genes' entries - which is the right place for them and the one place a queue keyed on ids never looks.
🟠 Both error directions appeared in one cycle from one loose matcher: too-narrow matching invented thirteen gaps, too-broad matching erased a real one. And an earlier NCBI query using [All Fields] instead of [sym] returned GeneID 673 (BRAF) for H3F3A with 14 HTTP 429s - a rate limit being an instrument failure, not an absence.
🔵 The cheap fix is not a better checker. Four rounds of increasingly sophisticated mechanical checking converged on what one careful read of each entry would have given immediately. The operational rule: before proposing any unwritten thing as work, run scripts/is-symbol-covered.py and then open the entries it names.
The audit file is the live hazard, and it will re-fire
The list did not come from nowhere. analyses/ledger-staleness-audit/results.json still holds all 15 ids in a field called unwritten_dispatch_targets, with no timestamp, no resolution marker, and nothing recording that cycles 65-66 already settled them. It was one of the 5 of 234 analysis directories cited by no entry, so nothing pointed at it and nothing warned about it.
🔴 A resolved worklist that stays on disk in an unresolved-sounding field is a trap that re-arms itself. It has now fired three times - cycles 65, 92 and 142 - and the cycle-92 instance cost a dispatched agent. The field name is the bait: unwritten_dispatch_targets reads as a standing to-do, and it is a snapshot of one moment's id-existence check.
This entry is the citation that directory never had. The durable fix is to write the resolution into the artifact itself rather than only into a log - a resolved field next to the list, naming this entry - so the next cycle that opens it sees the answer before the worklist.
| source | analyses/ledger-staleness-audit/results.json, field unwritten_dispatch_targets |
|---|---|
| source was uncited | true |
| n targets listed | 15 |
| n genuine gaps | 0 |
| wrong intermediate answer reproduced | 13 |
| superseded entry | ana-the-fifteen-unwritten-interactor-targets-are-thirteen-because-two-were-already-adjudicated |
| tool used | scripts/is-symbol-covered.py |
| graph node count at check | 2895 |
verdicts
{
"COVERED": [
"H3F3A",
"H3F3B"
],
"DECLINED_ON_PURPOSE": [
"KAT6B",
"MAP3K7",
"MYD88",
"SIRT6",
"TNFRSF1A",
"TRAF6"
],
"no_match_but_named_in_adjudicating_entry": [
"HDAC6",
"IL1R1",
"IRAK1",
"IRAK4",
"NFKBIB",
"NFKBIE"
],
"not_an_interactor": [
"NAP1L1"
]
}adjudicating entries
[ "ana-nfkb-upstream-enumeration-and-bounded-absences", "mechanism-il1-irak-axis-in-leukaemia-stem-cells", "ana-no-hdac-inhibitor-result-in-this-disease-attributes-to-an-enzyme", "protein-histone-h3-3", "variant-h3-3", "gene-tnf", "breakpoint-kmt2a-partner-frequency-by-age-lineage" ]
prior occurrences
[ "cycle 65 (same 15, reached 0 of 15)", "cycle 66 (resolved the 4 survivors)", "cycle 92 (union_absent_entirely; cost a dispatched agent)", "cycle 142 (this one; reached 13 and committed it before correcting)" ]
measurements
[
{
"quantity": "genuine unwritten interactor gaps in the audit's worklist",
"value": 0,
"unit": "gene entries",
"subject": "the 15 ids in unwritten_dispatch_targets, resolved by prose scan and by reading the adjudicating entries",
"universe": "15 listed; 2,895 node ids; 14 adjudicated, 1 not an interactor"
},
{
"quantity": "times this same worklist has been mistaken for real work",
"value": 3,
"unit": "cycles",
"subject": "cycles 65, 92 and 142, each using a coverage instrument that scans ids rather than prose",
"universe": "cycle 92's instance reached a dispatch brief and consumed an agent"
}
]- Write the resolution into analyses/ledger-staleness-audit/results.json itself - a `resolved` field naming this entry - so the next cycle that opens the file sees the answer before the worklist. A log entry does not disarm the file.
- Audit the other fields of that same results.json the same way. If unwritten_dispatch_targets was an id-existence snapshot, absence_claims_stale and not_checkable probably are too, and nobody has re-derived them.
- Re-test the refusals rather than the gaps. HDAC6 was dropped on a PubMed query returning 0 records and KAT6B on a DepMap rank; both are re-runnable, and a refusal that has gone stale is a better lead than a gap that never existed.
- Apply the same prose scan to docs/named-but-unwritten-worklist.md, which holds 313 rows and was built by the same class of instrument.
- E1strong confidence 4 of 5: Replicated in peer-reviewed work by more than one group.
Of the 15 gene ids in analyses/ledger-staleness-audit's unwritten_dispatch_targets, none is an unwritten interactor gap: scripts/is-symbol-covered.py returns COVERED for H3F3A and H3F3B, DECLINED ON PURPOSE for KAT6B, MAP3K7, MYD88, SIRT6, TNFRSF1A and TRAF6, and no match for the remaining seven, of which HDAC6, IL1R1, IRAK1, IRAK4, NFKBIB and NFKBIE are each named inside the adjudicating entries (ana-nfkb-upstream-enumeration-and-bounded-absences, mechanism-il1-irak-axis-in-leukaemia-stem-cells, ana-no-hdac-inhibitor-result-in-this-disease-attributes-to-an-enzyme), HDAC6 under a heading reading 'Enumerated and dropped as targets', and NAP1L1's only substantive mention is as a one-patient MLLT10 fusion partner in breakpoint-kmt2a-partner-frequency-by-age-lineage rather than as an interactor.
What this evidence cannot show
The tool's own footer states that a no-match answer is NOT a gap, only that no literal id or alias matched, so the seven no-match verdicts were resolved by reading the adjudicating entries directly rather than by the tool. NAP1L1 is the weakest call here: it is adjudicated nowhere, and the judgement that it is not an interactor rests on reading its three mentions, one of which is a fusion-partner list. If a future beat finds a histone-chaperone rationale for NAP1L1 it would be a genuine gap, making the honest count 0 of 15 today and possibly 1 of 15 later. Two probes were discarded before this one: an NCBI [All Fields] query returning BRAF for H3F3A with 14 HTTP 429s, and a hand-written alias matcher that reported TNFRSF1A as covered by gene-erg on the generic alias p55.
Evidence that argues against this (3)
- A recorded refusal is not permanently correct. Several of these were declined on evidence available at the time - KAT6B on a DepMap rank, HDAC6 on a PubMed query returning 0 records - and a query that returned nothing in an earlier cycle can return something now. 'Adjudicated' means a reason was written down, not that the reason still holds; this entry deliberately does not re-test any of them.
- Counting this as a third recurrence may overstate the pattern. Cycles 65, 92 and 142 share a mechanism - a coverage instrument that scans ids rather than prose - but cycle 92's instance was a different field in a different tool, so calling them one recurring failure is an interpretation rather than an observation.
- The strongest objection to this entry is that it spends a cycle's output on corpus hygiene while the PI's priority is biology. Its defence is the cycle-92 precedent, where the same list consumed a dispatched agent; but an entry arguing that a worklist is empty produces no new interactor evidence, and that cost is real.
supersedes the same-cycle claim of thirteen genuine gaps; the true answer is zero
this entry adjudicated the nine NF-kB targets with queries and counts, in prose and table rows
states outright why TNFRSF1A, MYD88 and TRAF6 do not get entries
declines KAT6B and SIRT6 and lists HDAC6 under Enumerated and dropped as targets
- supports →Histone H3.3 - one protein, two genes, and the reason this graph should not file it as gene-h3f3a
covers H3F3A and H3F3B and names gene-h3f3a as the filing it rejects
- related to →Which partner, in which patient: KMT2A partner frequencies across six age-lineage strata
holds the only substantive NAP1L1 mention, as an MLLT10 fusion partner rather than an interactor
the uncited directory whose worklist this resolves
acts on cycle 142s conclusion that refusals are a better lead than gaps
the same tool, relied on there as the guard; its id arm is narrower than assumed