Repository navigation
Tell the validation oracle how the graph was actually built - #14
Merged
Merged
Conversation
A conversion run with --info-representation raw could not pass validation. The
oracle reported the entire structured layer missing -- the allele layer,
value items, InfoFieldValue/InfoFieldDefinition, and all 256 buckets of the
INFO value digest -- and the run exited 1.
The oracle was right and already handled this: expected_census only adds that
layer when info_representation == "structured". It just never learned which
mode produced the graph. attach_census_expectations was called as
attach_census_expectations(parser, args.representation)
and both info_representation and header_representation are keyword-only with
default "structured", so every run was scored against a structured oracle. The
validation runner's CLI had no flag for either, so the wrapper had no way to
say otherwise across the container boundary.
- validation_runner.py gains --info-representation and --header-representation
and passes them at the call site.
- run_validation_mode takes both as required keyword arguments and forwards
them to the runner. Full mode already had them and simply never passed them
on; validate mode reads them from args like sample_representation does.
- expected_census and attach_census_expectations lose their defaults. The
default was the bug: it let a caller omit the parameter and silently get
wrong expectations instead of a TypeError.
The oracle's raw/structured branch was already exercised -- validation_fixtures
passes both values explicitly -- so the logic was covered while the wiring
between wrapper and runner was not. Added tests for the wiring itself: that the
flags reach the runner's argv, that the runner's CLI accepts what the wrapper
sends, and that the census helpers refuse to guess.
Found by 11_covering_set, whose row 2 is the only row pairing raw INFO with
single-strategy HDT. That row failing also aborted rows 3-6, so the sweep
recorded 2 of 6 rows.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
With the representation threaded through, q09_predicate_census and q10_class_census came back clean but q12_info_value_digest still reported all 256 buckets missing against zero extra rows -- the graph produced nothing and the oracle expected a full digest. q12 hashes the decomposed INFO value items, which only the structured representation emits; under raw INFO the column stays one opaque literal and the query matches nothing. But the digest is computed from the VCF in parse_vcf, where the emitter's representation is not in scope, so it survived unconditionally. Gate it in attach_census_expectations, next to the existing q13 gate on sample representation. validation_fixtures already encodes this -- parser_summary(include_info=False) yields an empty digest -- so the fixture and the production oracle disagreed. The new test pins them together. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Every job began with `pip install --upgrade pip`, so each run resolved dependencies with a different, unannounced resolver. CI was non-reproducible by construction: the same commit could pass or fail depending on what pip shipped that morning, with nothing in this repository to show for it. Pin it once per workflow as PIP_VERSION and reference that from all six install steps, so a resolver change lands as its own reviewable commit. What this does not do is prevent transient index failures, and it should not be read as a fix for one. The case that prompted it: the pull_request run for PR #14 failed with no matching distributions available for your environment: mdurl while the identical commit had passed 15 minutes earlier on push, passed on ubuntu-22.04 and macos-latest in that same run, and passed again on re-run with no code change. mdurl is a pure-Python py3-none-any wheel and the job pins Python 3.11, so nothing about the environment made it uninstallable -- that was the index, not the resolver, and the answer to it is a re-run. Pinning was worth doing on its own merits, not because it would have prevented that failure. Note that build, twine and coverage are still unpinned in the publish and coverage jobs. Same argument applies to them; left alone here so this commit stays about the toolchain that resolves everything else. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ecrum19
added a commit
that referenced
this pull request
Sep 22, 2026
…items Brings in #14-#17. The overlap that matters is CottasEngine: dev still had the pycottas subprocess form, main replaced it with the comunica-backed endpoint. Git merges the two cleanly because they touch different regions, and the comunica implementation wins -- verified here that no COTTASStore or COTTAS_QUERY_RUNNER remnant survives, so the merged engine is coherent rather than merely conflict-free.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
A conversion run with
--info-representation rawcould not pass validation. The oracle reported the entire structured layer missing — the allele layer, value items,InfoFieldValue/InfoFieldDefinition, and all 256 buckets of the INFO value digest — and the run exited 1.Root cause
The oracle was right, and already handled this.
expected_censusonly adds that layer wheninfo_representation == "structured", and the code even says so:It just never learned which mode produced the graph. The single call site was:
info_representationandheader_representationare keyword-only with default"structured", so every run was scored against a structured oracle. The validation runner's CLI had no flag for either, so the wrapper had no way to say otherwise across the container boundary —run_validation_modedid not even accept the values, thoughrun_full_modehad them all along.A second, independent gate was missing:
q12_info_value_digestis computed inparse_vcf, where the emitter's representation is not in scope, so it survived unconditionally even once the flags were threaded.Changes
validation_runner.pygains--info-representationand--header-representation, and passes them at the call site.run_validation_modetakes both as required keyword arguments and forwards them. Full mode had them and never passed them on; validate mode reads them fromargslikesample_representationdoes.expected_censusandattach_census_expectationslose their defaults. The default was the bug: it let a caller omit the parameter and silently get wrong expectations instead of aTypeError.q12_info_value_digestis gated inattach_census_expectations, beside the existingq13gate on sample representation.Why no test caught it
The oracle's raw/structured branch was already exercised —
validation_fixturespasses both values explicitly, andparser_summary(include_info=False)already yields an empty digest. So the logic was covered while the wiring between wrapper and runner was not, and the fixture and the production oracle quietly disagreed aboutq12.Added tests for the wiring itself: that the flags reach the runner's argv, that the runner's CLI accepts what the wrapper sends, that the census helpers refuse to guess, and that raw INFO expects no value digest.
Verification
Unit suites: 378 tests across
test_validation_{engines,oracle,logic,results,benchmark}_unitandtest_vcf_rdfizer_unit, all passing.End to end on a benchmark VM with an image built from this branch, running the full
11_covering_setsweep (test-1k.vcf, comunica):Suite exit 0, 6/6 rows recorded. Before the fix, row2 failed and aborted the sweep, so it recorded 2 of 6 rows — rows 3–6 had never run at all.
Also in this PR: pinning pip in CI
Separate from the validation fix, and included here because it surfaced while
verifying this branch.
Every CI job began with
pip install --upgrade pip, so each run resolveddependencies with whatever pip released most recently. That makes CI
non-reproducible by construction — the same commit can pass or fail depending on
the day's pip, with nothing in the repository to show for it.
PIP_VERSIONisnow pinned once per workflow (
26.2.1) and referenced from all six installsteps, so a resolver change arrives as its own reviewable commit.
This does not fix a transient index failure, and is not offered as one. The
failure that prompted it looked like this:
The evidence that it was the index rather than this branch:
d5a2087)3f93b47)ubuntu-22.04andmacos-latestpassed inside the same failing run, andmdurlis a pure-Python
py3-none-anywheel while the job pins Python 3.11 — so nothingabout the environment made it uninstallable. The right response to that is a
re-run; the right response to an unpinned toolchain is the pin.
build,twineandcoverageremain unpinned in the publish and coverage jobs.The same argument applies to them, and they are deliberately left for a separate
change.
How it was found
11_covering_seton a live benchmark run. Row 2 is the only row pairing raw INFO with single-strategy HDT. Worth noting the blast radius: only07_representation_axesand11_covering_setvary info-representation, and07does not validate — so this is invisible unless the covering set runs.🤖 Generated with Claude Code