Inline Web BLAST search-space drift recalibration¶
Motivation¶
The verified Web BLAST search space for core_nt was a single pinned constant
calibrated against the 2026-05-09 snapshot (db-len = 1,041,443,571,674,
db-num = 125,619,662, searchsp = 32,156,241,807,668). When the live database
was re-downloaded and its statistics drifted, the submit gate could no longer
match the pinned value and blocked browser New Search (and degraded the
Service Bus bridge), even though the run was otherwise valid. Recovering parity
previously implied a manual recalibration with a full-database BLAST run.
A spike confirmed the search space is a deterministic function of the live DB statistics for the fixed 64 nt calibration query:
L = 33 reproduces the pinned value EXACTLY from the calibrated stats and is
insensitive to modest snapshot drift (it tracks log(db_len)). So the verified
search space can be recomputed inline from the live stats — no NCBI
round-trip, no full-database run, no background job, no cluster dependency.
User-facing change¶
- New Search now stays precise after a
core_ntsnapshot drift. The dashboard recomputesweb_blast_searchspfrom the livetotal_letters/total_sequencesit already reads, the browser forwards both stats, and the submit gate recomputes the same value and accepts it asweb_blast_compatible_sharded. - Graceful degrade is preserved where it is still correct. A caller that
replays the stale pinned value against drifted stats (or sends drifted
db_total_letterswithoutdb_total_sequences, so the value cannot be recomputed) still degrades to approximate sharding with a warning instead of blocking. - Bad overrides still block. A
db_effective_search_spacethat matches neither the recomputed nor the pinned value is rejected as before.
API / IaC diff summary¶
api/services/web_blast_searchsp.py— addedcompute_web_blast_searchsp()(pure formula) andcalibrated_searchsp_for_stats()(recompute-or-pinned).api/services/storage/database_list.py—web_blast_searchspis recomputed from live stats when available (newweb_blast_searchsp_sourcefield:recomputed_live_snapshot/pinned_calibration).api/services/blast/submit_payload.py—resolve_sharding_planrecomputes the verified value from forwardeddb_total_letters/db_total_sequences, accepts a matching value as precise, degrades on a genuine drift, and blocks a bad override. Removed the now-superseded_calibration_snapshot_errorequality gate. Addeddb_total_sequencesto the submit option allowlist.api/services/blast/compatibility.py— the compatibility contract compares the configured search space against the live-recomputed value.web/—db_total_sequencesis forwarded on both the submit and pre-flight payloads (blast.types.ts,blast.ts,useSubmitMutation.ts,usePreFlight.ts,BlastSubmit.tsx).
Validation evidence¶
uv run pytest -q api/tests— 3934 passed, 3 skipped.- New tests:
api/tests/test_searchsp_recalibration.py(recompute-accept, stale-pinned degrade, no-stats pinned fallback, bad-override block),api/tests/test_web_blast_searchsp.py(formula reproduces the pinned value EXACTLY), plus recompute cases intest_blast_compatibility.pyandtest_storage_data.py. cd web && npx vitest run— 900 passed;npm run buildclean (strict TS).