Make #369's one-off drift audit a standing invariant - #456
Conversation
#369 audited all 366 grounded ids against the tool and found two blocks that disagreed - one resolving to a different rank, one to nothing. Re-auditing now, both are gone: the Chryseobacterium species/genus disagreement no longer occurs, and the Chlorobium block that grounds to nothing carries curated: true, which is a curator saying so rather than an unnoticed gap. So there is nothing to fix in the KB. What that audit was really testing is an invariant worth keeping: a stored grounding either matches what the tool produces today, or is marked curated: true. There is no third category - a block in it would be a claim nobody is accountable for, which is the state #294's status enum and #384's pin exist to prevent. Measured: 378 distinct grounded taxa, 11 blocks disagreeing with the tool, all 11 curated - nine demotion or nomenclature pins (#445, #451), two the Allobosea rename the crosswalk predates (#365). Three tests: the invariant, a guard on the fixture so an empty read cannot make it vacuous, and that every pin carries its reason. Verified the invariant fails when a pin loses its curated flag. Needs the crosswalk and so skips where that is absent, CI included - the same limitation as its neighbours. It earns its place anyway: the audit it replaces was run by hand once, and the KB has changed under it twice since. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
test_every_curated_block_says_why took the crosswalk-backed `audit` fixture and never used it - it calls _grounded_taxa() and re-reads the files itself. Its assertion is pure YAML, so the vestigial argument was the only thing making it skip where kg-microbe is absent, CI included. It is the one check here that can actually gate, and now does: verified it passes with KG_MICROBE_DIR pointed at nothing. Dropping the fixture also removed the file filter built from _grounded_taxa(), which required term.id while the inner loop did not - so a curated block with no term.id, in a file with no other curated block, would have escaped the note check. Zero such blocks today; the filter was only a parse-time optimisation and it was the thing introducing the gap. The failure message told the reader to run `--refresh --apply`, which is a guaranteed no-op when the tool reports None because it resolved the taxon as ambiguous - apply_to_community skips those. It now names --withdraw-ambiguous and the pin instead. Also record what the audit deliberately does not replicate: apply_to_community skips blocks in the legacy CURATED_GROUNDINGS list even without the flag, and per #384 the flag is primary - so a grounding protected only by the list is exactly what this test should complain about. The review reproduced the audit independently with its own walk and got the same numbers: 727 blocks, 378 distinct taxa, 11 disagreements, all curated, all with a note. It also confirmed both vacuity traps close - a resolver returning always None fails the invariant, always-the-stored-value fails the guard. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review round 1 — verdict: ship, one fix appliedThe reviewer reproduced the audit independently — its own positional walk mirroring Fixed — the one thing worth fixing
That also removed the file filter derived from Two smaller ones: the failure message told the reader to run Verified clean by the reviewWant-set construction matches
|
The push of 9cb6a4f produced no workflow run - the diff is test-only and tests/**/*.py is in the trigger paths, so it should have fired. Closing and reopening the PR did not start one either. An empty commit to get CI onto the final tree state rather than merging on a green run for the previous commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Blocked: CI has not run on the final commit
It is not this PR: GitHub Actions has produced no run on this repository since 14:50 UTC, roughly four hours. All eight workflows report Local state, on the exact tree (
|
Cause identified: a GitHub Actions platform outageNot this repo, not this PR. GitHub's own status API: Repo and org Actions settings are both Nothing to do here but wait. This PR is ready: |
Pushes during the outage (Actions was in major_outage from ~14:50 to ~22:00 UTC) produced no workflow run. Empty commit to queue one now that events are being accepted again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Closes #369.
Re-audit: both cases are gone
#369 audited all 366 grounded ids against the tool and found two disagreements. Re-running that audit today:
NCBITaxon:59732→s__Chryseobacterium_indologenes, tool saidg__ChryseobacteriumNCBITaxon:340177→g__Chlorobium, tool said nothingcurated: true— a curator saying so, not an unnoticed gapSo there is nothing to fix in the KB, and this PR changes none of it.
What the audit was really testing
An invariant worth keeping: a stored grounding either matches what the tool produces today, or is marked
curated: true. There is no third category. A block in it would be a claim nobody is accountable for — the tool didn't make it and no curator signed it — which is exactly the state #294's status enum and #384's pin exist to prevent.Current measurement: 378 distinct grounded taxa, 11 blocks disagreeing with the tool, all 11 curated. Nine are demotion or nomenclature pins (#445, #451); two are the Allobosea rename the crosswalk predates (#365).
Three tests
curated: trueblock carries acuration_note, since a pin is only accountable if it says why.Verified by mutation: stripping
curated: truefrom one pin makes the invariant fail.Limitation, stated plainly
Needs the kg-microbe crosswalk, so it skips where that is absent — CI included, the same limitation as its neighbours (
test_gtdb_support_countsand friends). It earns its place anyway: the audit it replaces was run by hand once, and the KB has changed under it twice since.just qcgreen.🤖 Generated with Claude Code