Bootstrap evidence-source from the citation-evidence src/source PDF slice. - Headless core (src/pdf): ingest/extract/fingerprint, importing domain contracts from @citation-evidence/engine/shared (no local copies) - Browser upload helpers isolated under src/browser behind a ./browser entry point, with an eslint boundary keeping the core browser-free - pnpm/TS/vitest/eslint scaffold; 52 tests (contract + determinism) - Fixtures resolved from the sibling citation-evidence checkout, not duplicated (real PII) — see docs/ADR-0002; suites skip when absent - Boundary + fixture decisions recorded as docs/ADR-0001 / ADR-0002 - README/SCOPE rewritten; capability.infotech.pdf-evidence-ingest registered, NO_CAPABILITIES removed - Follow-on workplans ESRC-WP-0002..0004 queued; ESRC-WP-0001 finished Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.7 KiB
ADR-0001 — PDF extraction boundary for evidence-source
- Status: accepted
- Date: 2026-07-08
- Workplan: ESRC-WP-0001 (T01)
Context
evidence-source is being bootstrapped from the PDF slice that currently
lives in ../citation-evidence/src/source/. That slice already implements a
working, tested headless ingest pipeline plus a set of browser/session helpers.
This ADR locks which files cross the boundary, where they land, and which
contracts they may depend on, so the extraction is mechanical rather than a
series of ad-hoc judgement calls.
The shared domain contracts (Document, DocumentRepresentation, PageMap,
OffsetMap, newId, normalize, …) are owned by citation-engine and are
published from its package as @citation-evidence/engine/shared. Nothing in
this extraction copies those types locally.
Decision
In-scope — headless ingest core (src/pdf/)
Moved into this repo immediately; these are pure, runtime-agnostic, and the reason this repo exists:
| Upstream file | New home | Notes |
|---|---|---|
src/source/pdf/ingest.ts |
src/pdf/ingest.ts |
ingestPdf |
src/source/pdf/extract.ts |
src/pdf/extract.ts |
extractPdf |
src/source/pdf/fingerprint.ts |
src/pdf/fingerprint.ts |
fingerprintBytes |
The only change to these files is the import specifier: @shared/* becomes the
published package subpath @citation-evidence/engine/shared.
In-scope but explicitly isolated — browser helpers (src/browser/)
Useful for browser upload flows, but not headless ingest. They are kept in
this repo behind a separate ./browser entry point and documented as
browser-facing so they never blur into the headless core:
| Upstream file | New home | Notes |
|---|---|---|
src/source/pdf/byte-store.ts |
src/browser/byte-store.ts |
in-memory blob: byte store |
src/source/pdf/upload.ts |
src/browser/upload.ts |
ingestPdfFromFile — thin wrapper over ingestPdf |
Out of scope — stays in citation-evidence
| Upstream file | Reason |
|---|---|
src/source/pdf/viewer-url.ts |
Pure viewer/app concern: it encodes the umbrella's /fixtures/pdfs/… URL convention and the app's blob-vs-fixture fallback policy. It consumes PdfByteStore (a type this repo now owns) but the resolution policy belongs to the viewer. It stays upstream and imports the PdfByteStore type from this package. |
tests/integration/anchor-source-roundtrip.test.ts |
Cross-subsystem (source ↔ anchor) contract. Remains an umbrella integration test; it is not a private test of this repo. |
Contracts
All domain contracts come from @citation-evidence/engine/shared. This repo
declares @citation-evidence/engine as a link:../citation-engine dependency
and never re-declares Document/DocumentRepresentation/etc. locally.
Fixture corpus
The PDF fixture corpus (../citation-evidence/fixtures/pdfs/) is not copied
into this repo. The files are real personal/legal documents (utility statements,
court letters, admission forms) containing PII; duplicating them into a package
that advertises reusable ingest capability is undesirable. Instead this repo's
tests resolve the corpus from the sibling checkout (default
../citation-evidence/fixtures/pdfs, override via
EVIDENCE_SOURCE_FIXTURE_DIR). This mirrors the sibling-checkout link: model
already used for the engine dependency and keeps the corpus single-owned
upstream. See ADR-0002.
Consequences
- The extraction is a 5-file move (3 core + 2 browser) plus import rewrites.
citation-evidencekeepsviewer-url.tsand the round-trip integration test.- Tests here require a sibling
citation-evidencecheckout for fixtures — an accepted coupling, identical in spirit to the enginelink:dependency.