Add a validate subcommand for post-export sanity checks#2
Open
gaurav wants to merge 4 commits into
Open
Conversation
Offline structural validation of exported NDJSON shards plus optional Entrez-backed coverage/field/deletion cross-checks, all funneled through a single monkeypatchable _eutils seam. Produces a gated report dict whose errors/warnings lead and whose optional (DB, previous-report, network) sections stay blank when unavailable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reads a shard directory, uses the DuckDB DB only when it exists and has articles, writes validation_report.json, prints a quiet-on-success summary, and exits non-zero on errors (--fail-on-warn also fails on warnings). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Covers structural pass/fail, dual-denominator coverage, sampled field matches and mismatches, missing-from-API detection, DB-sourced deletion confirmation, and the CLI happy/fail paths — no network. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Summary
Adds
pubmed2db validate <dir>, which inspects a finished JSON export (adirectory of NDJSON shards) and writes an archivable, gated
validation_report.json. It answers "does this export make sense?" after an HPCrun. Targets
initial-implementationso it can be reviewed after the base branch.Four checks, split into an offline phase (fast, deterministic) and an
online phase (Entrez eutils cross-checks; skip with
--offline):10-field record shape (reuses
export._document/month_to_abbrev); flagsmalformed lines, missing/extra fields, nulls, bad
ids, invalid months, andcross-shard duplicate PMIDs. Per-shard reservoir sampling keeps memory bounded.
(
einfo, a loose sanity band) and the locallatest_articlecount (ashortfall is an error — rows were dropped); plus drift vs.
--previous-report.efetchandcompared field-by-field (fuzzy abstract via
difflib). Journal name/abbrevare warning-only (different source); a sampled PMID PubMed no longer serves is
an error.
deleted_pmids not reinstated by a later version,confirms they're absent from the export and gone from PubMed.
Report & gating
The report leads with
errors/warningsarrays that are empty on a cleanrun; the stdout summary is quiet on success and loud on findings. Exit is
non-zero on errors (
--fail-on-warnextends to warnings) so it can gate apipeline. The DuckDB database and a previous report are optional inputs used
when present and left blank (noted in
skipped_checks) when not.Notes for review
validate._eutilsseam (rate-limited,retrying), which tests monkeypatch — the suite stays fully offline.
diffing is deferred (would need a PMID manifest sidecar) — see
FUTURE.md.requests,lxmlalready present).Testing
uv run pytest— 51 passing (34 existing + 17 new), no network.export (FAIL with itemized errors, exit 1).
🤖 Generated with Claude Code