2026-05-25 00:13:12 +02:00
|
|
|
# evidence-source
|
2026-05-24 13:49:33 +00:00
|
|
|
|
2026-07-08 20:55:28 +02:00
|
|
|
Headless document ingest for the citation-evidence ecosystem. Turns raw PDF
|
|
|
|
|
bytes into engine-owned evidence contracts — a `Document` (media type,
|
|
|
|
|
SHA-256 fingerprint, optional title/uri/metadata) and a
|
|
|
|
|
`DocumentRepresentation` (`pdf-text`: canonical text, page map, gap-free
|
|
|
|
|
offset map). Ingest is pure over bytes: no persistence, no viewer state, no
|
|
|
|
|
React.
|
2026-05-25 00:13:12 +02:00
|
|
|
|
2026-07-08 20:55:28 +02:00
|
|
|
## Status
|
2026-05-25 00:13:12 +02:00
|
|
|
|
2026-07-08 20:55:28 +02:00
|
|
|
**Implemented: the PDF slice.** As of ESRC-WP-0001 this repo hosts the
|
|
|
|
|
extracted PDF ingest core that previously lived in `citation-evidence/src/source/`.
|
|
|
|
|
HTML/Markdown representations, richer metadata enrichment, and citation
|
|
|
|
|
recovery are deferred to follow-on workplans (see `workplans/`).
|
2026-05-25 00:13:12 +02:00
|
|
|
|
2026-07-08 20:55:28 +02:00
|
|
|
## Install
|
|
|
|
|
|
|
|
|
|
Requires a sibling checkout of `citation-engine` (domain contracts) and, for
|
|
|
|
|
tests, `citation-evidence` (fixture corpus — see `docs/ADR-0002-fixture-ownership.md`).
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
pnpm install # resolves @citation-evidence/engine via link:../citation-engine
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
import { ingestPdf } from "@citation-evidence/evidence-source";
|
|
|
|
|
|
|
|
|
|
const { document, representation } = await ingestPdf(pdfBytes, {
|
|
|
|
|
filename: "contract.pdf",
|
|
|
|
|
});
|
|
|
|
|
// document.fingerprint -> SHA-256 hex
|
|
|
|
|
// representation.canonicalText / pageMap / offsetMap
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Browser upload helpers (in-memory `blob:` byte store + `ingestPdfFromFile`)
|
|
|
|
|
live behind a separate, clearly-isolated entry point so headless consumers do
|
|
|
|
|
not pull in browser machinery:
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
import { createPdfByteStore, ingestPdfFromFile }
|
|
|
|
|
from "@citation-evidence/evidence-source/browser";
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Extraction requires the host to configure the PDF.js worker
|
|
|
|
|
(`GlobalWorkerOptions.workerSrc`) before calling `extractPdf`/`ingestPdf`; the
|
|
|
|
|
module itself does no worker setup so it loads cleanly in Node and browsers.
|
|
|
|
|
|
|
|
|
|
## Dev commands
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
pnpm test # vitest (fixture suites skip if the corpus is absent)
|
|
|
|
|
pnpm typecheck # tsc --noEmit
|
|
|
|
|
pnpm lint # eslint
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Point `EVIDENCE_SOURCE_FIXTURE_DIR` at the PDF corpus when the sibling
|
|
|
|
|
`citation-evidence` checkout is not at `../citation-evidence`.
|
|
|
|
|
|
|
|
|
|
## Architecture
|
|
|
|
|
|
|
|
|
|
- `src/pdf/` — headless core: `ingest`, `extract`, `fingerprint`. Runtime-agnostic.
|
|
|
|
|
- `src/browser/` — browser upload surface: `byte-store`, `upload`. Separated by
|
|
|
|
|
an ESLint boundary so the core never imports it.
|
|
|
|
|
- Domain contracts come from `@citation-evidence/engine/shared`; none are
|
|
|
|
|
copied locally.
|
|
|
|
|
- Boundary and fixture decisions: `docs/ADR-0001`, `docs/ADR-0002`.
|
|
|
|
|
|
|
|
|
|
`viewer-url` resolution stays in the consuming app (`citation-evidence`), which
|
|
|
|
|
imports this package's ingest core through a thin façade.
|