Four bugs this cycle share one shape: a source was implemented, gated, allowlisted and unit-tested,
and did not work.
|
found by |
passed its unit tests |
| #413 |
five Tier-2 sources never called |
yes |
| #442 |
three Tier-3 sources never called |
yes |
| #454 |
Tier-3 allowlists never registered in the client |
yes |
| #458 |
Tier-3 chain skipped whenever Crossref answers |
yes |
In every case the unit test drove the Source impl directly, or asserted that a builder returned
the right value, and the production entry point was never in the picture. #454's guard even had a
doc comment describing the failure it could not catch.
Each fix added a targeted regression test, which is right, but they were written after a human
drove the real thing and noticed. Nothing drives the real thing on a schedule.
What is missing
A suite that starts where a user starts — doiget fetch, doiget_fetch_paper over MCP stdio —
and asserts on the observable outcome, for a small fixed set of DOIs chosen because each one
exercises a different route.
Not a replacement for the unit tests. The thing they cannot do is notice that a correct component
is never reached.
Sketch
| DOI |
route it exercises |
expected |
10.1109/TSP.2018.2812747 |
hybrid OA, repository copy, host not curated |
blocked, denial_context.attempted names the repository host |
same, trust_academic_repos = true |
the user-extension trust flag |
fetched, non-zero bytes |
10.1090/s0025-5718-04-01692-8 |
bronze OA, publisher rate-limits (#445) |
blocked, and the trace names every enabled source |
| an arXiv-preprinted DOI |
the #325 preprint fallback |
fetched via arXiv, PreprintFallback |
| a gold-OA DOAJ DOI |
the ADR-0037 apex redirect |
fetched |
| a DOI Crossref cannot resolve |
the Tier-2 optional chain |
the trace distinguishes "asked, nothing" from "never asked" |
Each row asserts which route produced the outcome, not merely that one occurred — that is the
distinction every bug above slipped through.
Constraints, and the awkward part
These need the network, so they cannot sit in the ordinary test job: the network-purity job
exists precisely to keep the default suite hermetic. Options:
- a separate scheduled workflow (nightly),
continue-on-error: false but off the PR path, so an
upstream change surfaces as a failing cron rather than a blocked PR;
#[ignore] by default, run explicitly;
- record the responses as fixtures and replay them, with a much rarer live job that re-records.
The third is the most stable and the least likely to notice that the real world changed, which
is the whole point. Probably the first, accepting the flakiness, with the DOI list kept small and
the failures triaged rather than muted.
Politeness matters: a fixed handful of DOIs, a contact address set, and the existing rate limiter.
Why now
#430 shipped a source justified by a corpus nobody had fetched end-to-end. Driving it revealed
#458, #459 and #460 in one session — none of which any unit test could have found. That is a
strong argument that this suite pays for itself.
Refs #413, #442, #454, #458, #459, #460, #445.
Four bugs this cycle share one shape: a source was implemented, gated, allowlisted and unit-tested,
and did not work.
In every case the unit test drove the
Sourceimpl directly, or asserted that a builder returnedthe right value, and the production entry point was never in the picture. #454's guard even had a
doc comment describing the failure it could not catch.
Each fix added a targeted regression test, which is right, but they were written after a human
drove the real thing and noticed. Nothing drives the real thing on a schedule.
What is missing
A suite that starts where a user starts —
doiget fetch,doiget_fetch_paperover MCP stdio —and asserts on the observable outcome, for a small fixed set of DOIs chosen because each one
exercises a different route.
Not a replacement for the unit tests. The thing they cannot do is notice that a correct component
is never reached.
Sketch
10.1109/TSP.2018.2812747denial_context.attemptednames the repository hosttrust_academic_repos = true10.1090/s0025-5718-04-01692-8PreprintFallbackEach row asserts which route produced the outcome, not merely that one occurred — that is the
distinction every bug above slipped through.
Constraints, and the awkward part
These need the network, so they cannot sit in the ordinary
testjob: thenetwork-purityjobexists precisely to keep the default suite hermetic. Options:
continue-on-error: falsebut off the PR path, so anupstream change surfaces as a failing cron rather than a blocked PR;
#[ignore]by default, run explicitly;The third is the most stable and the least likely to notice that the real world changed, which
is the whole point. Probably the first, accepting the flakiness, with the DOI list kept small and
the failures triaged rather than muted.
Politeness matters: a fixed handful of DOIs, a contact address set, and the existing rate limiter.
Why now
#430 shipped a source justified by a corpus nobody had fetched end-to-end. Driving it revealed
#458, #459 and #460 in one session — none of which any unit test could have found. That is a
strong argument that this suite pays for itself.
Refs #413, #442, #454, #458, #459, #460, #445.