Skip to content

Remove the closed PDF backend study - #783

Merged
willhea merged 4 commits into
developfrom
chore/retire-pdf-study
Oct 5, 2026
Merged

willhea merged 4 commits into
developfrom
chore/retire-pdf-study

Conversation

@willhea

@willhea willhea commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

What

Removes the closed PDF backend study from the tree, under the research-retention rule (AGENTS.md, "Research artifacts are working material"). #740 closed it as inconclusive, with no architecture recommendation. Git history keeps everything; CLOSEOUT.md at 4171e32d is the citable record.

Removed Size
docs/research/pdf-backend-bakeoff/ bulk of the ~27 MB
docs/research/staffer-delivery/ 15 files
tests/data/p3/ (3 PDFs) read only by bake-off probes (confirm_safe_failure.py, x01_contamination.py)
.gitignore bake-off block holdout corpus and external-validity result rules

328 tracked files deleted. CLOSEOUT.md goes too: once its conclusions have homes, it is a closure document whose only job is recording what was deleted.

What survives, and why

Two probes still answer live questions, so they move to scripts/ instead of being deleted:

Script Live question Verified on develop d3935ee1
scripts/pyodide_parity.py + .mjs (was staffer-delivery/probes/verify_parity.py, parity_pyodide.mjs) The gate #751 names for the lazy pypdfium2 import; in-browser delivery is still open in #112 3 fixtures × 2 artifacts IDENTICAL, exit 0. --mutate: every HTML row MISMATCH, exit 0. No node dir: exit 2. Hashes identical before and after the move
scripts/make_scan_fixture.py (was pdf-backend-bakeoff/probes/make_scan_fixture.py) The only executable reproduction of open bug #550 (two scanned PDFs compare as "no changes"); no test owns it DEFECT REPRODUCED: both 20-page scans extract 20 lines, guard_declines=False, changes=0

Both are cataloged in scripts/README.md. make_scan_fixture.py needs pypdf, which only the probes' own requirements.txt provided. It runs with uv run --with pypdf rather than adding a project dependency, and its catalog row says to delete it once a test owns #550.

Fixed in passing: verify_parity.py's docstring said --mutate exits 1; the code exits 0 when the corruption is detected and 1 when it is not. The harness no longer defaults to node_modules beside itself, since that would land untracked in scripts/.

Where the conclusions went

Written as present-state facts into the ADRs that own them (ADRs here are living records), each with one evidence link to CLOSEOUT.md at 4171e32d:

  • ADR 0002 (PDFium engine): PDFium is the engine for anchoring and chrome handling, not for a measured accuracy lead. No backend dominates (pdfminer.six best against the XML, PDFium-WASM exact on production output and faster), and no design for plugging in a second backend was selected.
  • ADR 0003 (client-side extraction): the Python engine runs under Pyodide with byte-identical XML output; the module-scope pypdfium2 import is its one obstacle (The XML comparison cannot load in a browser because it imports a PDF library it never uses #751); PDFium-WASM exposes the per-glyph data the extractor uses. The PDF path has not run end to end in a browser.
  • ADR 0011 (local-only processing): CSP alone cannot give a browser channel zero egress. window.open and WebRTC are outside CSP; Speculation Rules is closed only when script-src drops 'unsafe-inline'. Closing the rest needs a browser- or device-level control.

pyproject.toml's extend-exclude stays, since provision-matching/ and pdf-matching-convergence/ still have probes and other studies have write-ups. Its comment loses the clause about a frozen preservation manifest, which existed only in the bake-off.

Consumer trace

Issue text updated for the new paths

Applied with the maintainer's approval, in place (all three are the maintainer's own text):

The new scripts/ paths resolve once this merges.

Verification

  • ruff check . and ruff format --check .: clean.
  • Fast suite from outside the checkout (-m "not slow and not browser", as CI runs it): 2130 passed, 4 skipped, 15 xfailed.
  • tests/test_adr_index.py and tests/test_docs_consistency.py pass with the ADR edits.
  • The slow tiers were not run locally: nothing they read was removed or changed.

🤖 Generated with Claude Code

willhea and others added 4 commits October 4, 2026 20:11
verify_parity.py and parity_pyodide.mjs are the one live part of the
staffer-delivery study: #751 (lazy pypdfium2 import) names them as its
gate, and the in-browser channel is still open in #112. Relocate them as
scripts/pyodide_parity.{py,mjs} so they outlive the study directory.

- ROOT now resolves from scripts/.
- No default node_modules beside the script: it is not gitignored, so
  --node-dir or DT_PYODIDE_DIR is required and must sit outside the
  checkout.
- The docstring said --mutate exits 1; it exits 0 when the corruption is
  detected and 1 when it is not. Corrected to match the code.

Verified on develop d3935ee with pyodide 314.0.7 / node 22: 3 fixtures
x 2 artifacts IDENTICAL, exit 0; --mutate reports MISMATCH on every HTML
row, exit 0; no node dir, exit 2. Hashes match the pre-move run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The PDF backend study is being removed from the tree. Its conclusions
that still constrain current decisions move to the records that own
them, stated as present-state facts:

- ADR 0002: PDFium is the engine for anchoring and chrome handling, not
  a measured accuracy lead; no backend dominates, and no design for a
  second-backend seam was selected.
- ADR 0003: the Python engine runs under Pyodide with byte-identical XML
  output (scripts/pyodide_parity.py); the module-scope pypdfium2 import
  is the one obstacle (#751); PDFium-WASM exposes the per-glyph data the
  extractor needs. The PDF path has not run end to end in a browser.
- ADR 0011: CSP alone cannot give a browser channel zero egress;
  window.open and WebRTC are outside it, and Speculation Rules needs
  script-src without 'unsafe-inline'.

Each cites CLOSEOUT.md at the #740 merge commit as evidence.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
make_scan_fixture.py lives in the PDF bake-off's probes, which are being
removed, but it is the only executable reproduction of #550 (two
different scanned PDFs compare as "no changes"). #550 is open and no
test owns it, so under the research-retention rule it survives the
study. The issue's own comment names it as the reproduction.

- REPO resolves from scripts/; the sys.path insert of src/ is dropped,
  since the engine is installed (ADR 0017).
- pypdf came from the probes' own requirements.txt, not the project.
  Run with `uv run --with pypdf` rather than adding a dependency.

Verified on develop d3935ee: both 20-page scans extract 20 lines,
guard_declines=False, compare_pdfs -> changes=0, "DEFECT REPRODUCED".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The PDF study closed in #740 as inconclusive, with no architecture
recommendation. Under the research-retention rule its materials no
longer answer a live question, so they leave the tree:

- docs/research/pdf-backend-bakeoff/ (including CLOSEOUT.md, whose
  conclusions now live in ADRs 0002, 0003 and 0011)
- docs/research/staffer-delivery/
- tests/data/p3/, read only by bake-off probes
- the bake-off's .gitignore block
- the pyproject comment clause about a frozen preservation manifest,
  which existed only in the bake-off. The extend-exclude itself stays
  for the remaining studies' probes and write-ups.

The two probes still answering open questions moved to scripts/ in the
preceding commits. Git history keeps everything; CLOSEOUT.md at
4171e32 is the citable record.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@willhea
willhea added this pull request to the merge queue Oct 5, 2026
Merged via the queue into develop with commit 7fde55f Oct 5, 2026
9 checks passed
@willhea
willhea deleted the chore/retire-pdf-study branch October 5, 2026 00:40
willhea added a commit that referenced this pull request Oct 5, 2026
Resolve the .gitignore conflict with #783: each side removed its own
study's ignore block, so neither survives. With the PDF bake-off and
staffer-delivery Python gone, the bills_corpus comment drops "for
research sweeps" and the fixture-layout exemption names the
financial-semantics stress tests as what still reads the download tree.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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