Skip to content

feat: pre-flight layout probe before crawling - #7

Merged
Hydaspex merged 2 commits into
mainfrom
feat/preflight-check
Aug 8, 2026
Merged

feat: pre-flight layout probe before crawling#7
Hydaspex merged 2 commits into
mainfrom
feat/preflight-check

Conversation

@Hydaspex

@Hydaspex Hydaspex commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Addresses the gap identified in the drift discussion: a site layout change previously surfaced only as a silently empty CSV after a full crawl. Now a canary probe runs before any crawl and aborts with named failures. Follows on from #6.

What's included

pipeline/preflight.py

  • probe_layout(page) -> LayoutProbeResult — pure function running five structural checks against the load-bearing signals the extractor depends on:
    1. <h1> provider heading
    2. section.specialty blocks
    3. recognised h4 metric headings
    4. waiting-time tables with an "Average waiting time" header
    5. Page last updated: DD/MM/YYYY footer
  • Extractor end-to-end signal — only when all structural checks pass, the extractor itself runs on the canary; a structurally valid page yielding zero records is flagged (the subtlest drift: markup present, semantics changed).
  • LayoutDriftError — carries url + failures for diagnosable aborts.

pipeline/run.pyrun_pipeline(..., preflight=True) (default): scrapes one canary page (first seed), probes it, and raises LayoutDriftError before any crawl call is made. preflight=False preserves the previous lenient behaviour.

cli.py--no-preflight flag; on drift the CLI prints each named failure and exits 2 — a distinct code so scheduled workflows can alert on drift specifically.

tests/fixtures/trust_page_drifted.html — the same trust restructured (tables → divs, renamed headings, changed footer) proving the probe catches real drift.

tests/test_preflight.py (12 tests) — probe pass/full-drift/partial-drift/end-to-end-signal/canary-must-be-data-bearing; pipeline abort-before-crawl (asserts zero crawl calls), golden pass-through, disabled-preflight behaviour; CLI flag, exit-2-on-drift with monkeypatched backend, and the full success path writing a CSV.

Verification

Probe executed in the sandbox: good layout passes clean, fully drifted page yields all 5 named failures, partial drift (footer format) yields exactly 1. Extractor end-to-end signal confirmed both directions.

Design decisions to review

  1. One canary per run, not per seed — drift on this site would be platform-wide; per-seed probing would double request volume for no signal.
  2. Preflight on by default — the safe posture for scheduled runs; --no-preflight exists for debugging, not production.
  3. Exit code 2 for drift — distinct from generic failure (1) and diff-changes (1 on nhs-scraper-diff); scheduling alerts can key on it precisely.
  4. Canary must be data-bearing — encoded as a test: a specialty-unavailable page is not a valid canary.

- probe_layout: five structural checks (h1, specialty sections, metric
  headings, waiting-time table header, last-updated footer) plus an
  extractor end-to-end signal for structurally valid pages that yield
  no records — the subtlest drift
- run_pipeline(preflight=True): scrapes one canary page per run and
  raises LayoutDriftError listing every failed assertion before any
  deep crawl; preflight=False preserves previous behaviour
- CLI: --no-preflight flag; exit 2 with named failures on drift
- Drifted-layout fixture proves the probe catches restructured pages;
  probe, pipeline and CLI paths all verified in the sandbox
With preflight on by default, run_pipeline scrapes a canary first; this
test's empty FakeBackend has no canary page (strict scrape -> KeyError).
The test isolates crawl behaviour, so opt out of preflight explicitly —
preflight itself is covered by tests/test_preflight.py.
@Hydaspex
Hydaspex merged commit b03da3b into main Aug 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant