The absence-class checker globbed a filename instead of the field, so it walked 40 of 243 entries and reported them as the whole population - and the 40 it called invalid turn out to be two independently re-invented vocabularies
also called absence_class vocabulary · check-absence-class defect · literature-absence-bounded · absence_class_note
A tool that checks how we label the gaps in our own knowledge was only looking at the files whose names began with the word 'absence', which was one in six of them. Fixing it showed that where authors had written something the tool called invalid, they were usually describing a distinction the official label list had no word for.
The same thing, for a scientist
`scripts/check-absence-class.py` globbed `data/graph/nodes/*/absence-*.json` and so walked entries by FILENAME. It reported **40 absence entries, 36 classified, 0 missing** - a clean-looking result. Walking the FIELD instead: **243 node files carry a real `data.absence_class`**, of which only 40 are named `absence-*`. **The checker was seeing 16.5% of its own population and nothing in its output revealed it.** After the fix: 243 entries, **222 classified, 21 invalid**. The 40 that were out of vocabulary decompose into **two independently re-invented vocabularies plus a handful of one-offs**, not into careless authors: 14 entries begin `literature - bounded with counts, querytranslations and controls`, and ~17 from the ISR beat use a **two-axis** scheme - `MEASURED-AND-NULL`, `MEASURED-AND-FLAT`, `MEASURED-AND-LARGE`, `BOUNDED-UNPUBLISHED` - encoding a measured result's DIRECTION alongside its literature-bound status. Both express things the six-token vocabulary cannot. One token was added, 19 entries were migrated mechanically, and 21 were left flagged rather than forced.
Why a new token rather than forcing the 14 into an existing one
Every pre-existing token is about whether data exists:
| token | meaning |
|---|---|
never-measured | no instrument was ever pointed at it |
measured-not-reported | the assay ran, the number was never written down |
measured-not-analysed | deposited and public, this analysis never run |
measured-not-searched | in an archive, unfindable because the search excluded it |
measured-not-curated | published, absent from the database we join against |
A bounded literature absence asserts something different and weaker: no published report says it, bounded with counts, querytranslations and controls. It says nothing about whether the data exists.
The cycle immediately before this one is the proof that the distinction is real rather than a shade of never-measured. absence-no-h3k9-writer-or-reader-localised-at-the-kmt2a-locus was carried as never-measured. Its literature half is genuinely bounded and empty. Its archive half held two deposited SUV39H1 datasets, which a beat then read at the locus for the first time. Had the two halves shared one token, nobody would have gone looking for the archive half - and that lookup is where the result came from. So literature-absence-bounded was added, with the explicit caution that it must NOT be used where an archive was also checked.
What was migrated, and what was deliberately not
Migrated mechanically, never by judgement (19). Two rules only: a class string beginning literature became literature-absence-bounded; a class string whose own first word was already a valid token became that token. In every case the original string is preserved verbatim in the new absence_class_note field, because it says more than the token can - one of them carries a 1,000 bp resolution bound against a 147 bp question, which no token could hold.
Left flagged (21), and this is the more interesting half. Sixteen or seventeen come from the ISR/ATF4 beat and use a genuinely richer scheme than the official one: MEASURED-AND-NULL, MEASURED-AND-MODEST, MEASURED-AND-FLAT, MEASURED-AND-LARGE, MEASURED-BUT-PLATFORM-DISCORDANT, MEASURED-AND-LINE-DEPENDENT, each usually paired with BOUNDED-UNPUBLISHED for the prose half. That is two axes - what the measurement showed, and whether the literature was searched - and forcing it into one token would delete the direction of a measured result. gene-ppp1r15a even reads FALSE ABSENCE, NOW CLOSED, which is a state the vocabulary has no word for at all.
Two are bare one-offs (not-applicable, meta) and one is honest about not belonging: not-an-absence -- this is an instrument characterisation.
The checker's own report was the thing that hid the defect
It printed 40 absence entries, 36 classified, 0 missing. Zero missing is the reassuring number, and it was true of the population the tool had chosen. This is the same shape as three earlier instrument failures in this corpus - a clean headline over a denominator nobody checked - and the fix is the same one: the checker now prints both populations on its first line, so 40 files named absence-*, 243 files carrying a real data.absence_class field, 40 in both is the first thing a reader sees and the gap between them cannot be read past.
| node files walked | 2243 |
|---|---|
| files named absence star | 40 |
| files carrying absence class field | 243 |
| fraction the checker walked PCT | 16.5 |
| vocabulary token added | literature-absence-bounded |
| token added because | no published report says it, bounded with counts, querytranslations and controls, saying NOTHING about whether the data exists - the distinction that produced the cycle-66 SUV39H1 archive result |
| field added | absence_class_note, for prose the token cannot carry |
| migrated mechanically | 19 |
| left flagged not assigned | 21 |
| measured | 2026-09-23, king, cycle 67 |
| CORRECTION 2026 09 23 the field was not mine to add | This entry says a field was added: 'Plus `absence_class_note`, for prose no token can hold.' **I did not add it. It already existed in 60 entries before my commit**, and a SECOND scoping field, `absence_class_basis`, existed in 58 more - measured with git grep against the parent of my own commit 88aa45f. Zero entries carry both, so the corpus had TWO independent scoping conventions and I adopted one of them while believing I was creating it. My migration raised absence_class_note from 60 to 86 and touched no basis field. The irony is exact and worth leaving in place: this is the entry in which I diagnosed 31 entries for independently re-inventing a convention, and I re-invented one in the same commit, by asserting a property of the corpus without checking it. |
before fix — the numbers behind the chart
{
"entries": 40,
"classified": 36,
"missing": 0,
"invalid": 4
}after fix — the numbers behind the chart
{
"entries": 243,
"classified": 222,
"missing": 0,
"invalid": 21
}out of vocabulary decomposition
{
"begins_with_literature": 14,
"isr_beat_two_axis_scheme": "about 17 (MEASURED-AND-NULL / -FLAT / -LARGE / -MODEST / -LINE-DEPENDENT / BOUNDED-UNPUBLISHED)",
"bare_one_offs": [
"not-applicable",
"meta"
],
"self_declared_non_absence": "not-an-absence -- this is an instrument characterisation"
}- Should the ISR beat's two-axis scheme become the schema? It carries what the official vocabulary cannot - the DIRECTION of a measured result alongside the literature-bound status - and about 17 entries already use it. The choice is between two fields (measurement outcome, literature bound) and a longer single vocabulary, and it should be made deliberately rather than by whichever beat writes next.
- Nothing checks whether a valid token is the RIGHT token. Every check here is on membership. An audit would mean re-deriving a sample of absences from their own stated evidence and asking whether the class follows - the cycle-66 beat did this by hand for one entry and found it wrong while its token was valid.
- How many of the 243 are not absences at all? One flagged value says so explicitly. If the field has been used as a general annotation slot, the population that any absence statistic should quote is smaller than 243 and nobody has separated them.
- E1established confidence 5 of 5: Multiple independent lines of evidence; treated as settled in the field.computation_on_this_corpus
scripts/check-absence-class.py selected entries with the glob data/graph/nodes/*/absence-*.json, matching filenames rather than the field it validates. Across 2,243 node files, 243 carry a real data.absence_class and only 40 are named absence-*, so the checker walked 16.5% of its population while reporting 0 missing. After walking the field: 243 entries, 222 classified, 21 invalid. Of the 40 originally out-of-vocabulary values, 14 begin with the word 'literature' and about 17 use the ISR beat's MEASURED-AND-* / BOUNDED-UNPUBLISHED two-axis scheme.
Field-versus-filename population audit of the absence-class checker over the Oncofusion corpus · king, Oncofusion knowledge graph, cycle 67 · scripts/check-absence-class.py 2026What this evidence cannot show
The 243 figure counts any entry with a non-empty `data.absence_class`, which includes entries whose principal subject is not an absence - one flagged value is literally `not-an-absence -- this is an instrument characterisation`. So 243 is the population the CHECKER should walk, not a count of bounded absences in the corpus; a separate cycle-66 estimate put the latter near 221. The 14/17 split of the out-of-vocabulary values was assigned by a regex on the leading word and by reading the flagged list, and two or three sit on the boundary. The migration rules are deliberately narrow, so some of the 21 could probably be assigned by a careful reader - that was left undone rather than guessed. AND ONE CLAIM IN THIS ENTRY IS WRONG: it presents `absence_class_note` as a field this cycle added. It existed in 60 entries beforehand, alongside `absence_class_basis` in 58 others. See CORRECTION_2026_09_23_the_field_was_not_mine_to_add.
Evidence that argues against this (2)
- The opposite reading of this finding is that a controlled vocabulary re-invented twice is not under-specified but UNENFORCED, and that adding a seventh token rewards the drift. That case has force: the ISR beat's scheme is the richer one and it was never proposed as a schema change, so the corpus now has three conventions in a field whose whole purpose is to be machine-readable. The reason this entry sides with extension over enforcement is narrow and specific - the literature/archive distinction has already paid, once, in the cycle that preceded it. No such demonstration exists for the MEASURED-AND-* axis, which is exactly why those 17 were left flagged rather than blessed.
- And the checker fix does not make this field trustworthy. 222 of 243 now hold a vocabulary token, but nothing verifies that the token is CORRECT - a `measured-not-analysed` that should read `never-measured` passes every check here. The cycle-66 beat found exactly that error class by hand, in an entry whose token had been valid all along.
the entry whose literature half was bounded and empty while its archive half held two deposited datasets - the case that justifies separating a literature absence from never-measured
that census classified 39 absence- entries; this shows the checker behind the field was walking 40 of 243, so the population both rest on was six times larger
the cycle-66 beat estimated the unwalked population and reported the glob defect; this fixes it and measures the result
that found the checker walking 40 of 243; this asks what the 243 are and finds them to be rich entries carrying 7-11 gaps each under one token
that entry claims cycle 67 ADDED absence_class_note; it existed in 60 entries beforehand and a second convention, absence_class_basis, in 58 more, with zero overlap
same defect family: an id-keyed census under-walks the absence population