evidence-anchor/README.md
tegwick 113358c13c
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
Post WP-0002/0003 hygiene: update docs and archive finished workplans
Refresh README and SCOPE to reflect stale/fuzzy/DOM capabilities. Move
EANCH-WP-0001 through EANCH-WP-0003 to workplans/archived/260709-*.
2026-07-09 09:29:50 +02:00

91 lines
4.3 KiB
Markdown

# evidence-anchor
Selector creation, resolution, and the `DocumentViewerAdapter` contract that
every document viewer in the citation-evidence workspace implements. This repo
turns annotations from static marks into durable, reopenable source references.
- **Owns:** selector *behavior*`createSelectors`, `resolveSelectors`, PDF
selector math, the viewer-adapter contract, and highlight/scroll helpers.
- **Does not own:** selector *type interfaces* — those live in `citation-engine`
(`shared/selector`). See `ADR-0006` and `SharedContracts.md` §8.
- **May depend on:** `citation-engine` only (DependencyMap §4). Nothing from
`binder/`, `source/`, or `work/` may flow back into it.
See `SCOPE.md` for the boundary and `INTENT.md` for the long-range intent.
## Status: extracted; umbrella consumes this package
The anchor slice has been extracted from the umbrella and now lives here.
`citation-evidence` consumes it as `@citation-evidence/evidence-anchor`
(`link:../evidence-anchor`); its former `src/anchor/` directory is gone and the
`@anchor` alias is retired. Shared-contract changes still happen in the umbrella
(`citation-evidence/wiki/`), not here.
EANCH-WP-0002 and EANCH-WP-0003 delivered stale/orphan/fuzzy resolution,
`PdfViewerAdapter`, and HTML/Markdown selectors plus `evidence-anchor/dom`.
Remaining work (FragmentSelector, umbrella viewer wiring) is tracked in
`workplans/`.
## Install model
Sibling-checkout, linked-package model — this repo is checked out next to its
consumers and consumed via a local link (e.g. `link:../evidence-anchor`), not
published to a registry during MVP. Its only shared-type dependency is
`citation-engine`, imported through the engine's public `shared` entrypoint
(`@citation-evidence/engine/shared`) rather than umbrella-only `@shared/*`
aliases.
## Package layout (initial extracted version)
```text
src/
index.ts public entrypoint — full barrel (core + pdf)
types.ts adapter-side types: SelectionCapture,
ResolvedAnchorTarget, AnchorResolution,
HighlightRenderOptions, DocumentViewerAdapter
css.d.ts ambient decl for side-effect .css imports
selectors/ pure core — no viewer/UI deps
index.ts createSelectors, resolveSelectors, fuzzy, orphan helpers
create.ts selector creation (PDF + DOM branches)
resolve.ts resolution ladder + stale/fuzzy recovery
fuzzy.ts / orphan.ts / dom-path.ts
*.test.ts
pdf/ PDF adapter boundary
index.ts subpath entry `evidence-anchor/pdf`
pdf-viewer-adapter-spike.tsx PdfViewerAdapter (+ PdfSpikeViewer alias)
pdf-selector-math.ts / scroll-job.ts / *.css
dom/ HTML/Markdown adapter boundary
index.ts subpath entry `evidence-anchor/dom`
html-viewer-adapter.tsx HtmlViewerAdapter
dom-path.ts Range ↔ DomNodePath serialization
```
Boundary rules for the layout (enforced by `eslint.config.js`):
- viewer-library imports (`pdfjs-dist`, `react`, `react-pdf-highlighter-plus`)
are confined to `src/pdf/` — the pure zone (`src/selectors/**`, `src/types.ts`)
may not import them;
- `src/selectors/` is pure and depends only on `citation-engine` shared types;
- the **root** entrypoint (`evidence-anchor`) is the full barrel — selector
creation/resolution, the adapter types/contract, and the PDF adapter — so
consumers resolve every anchor symbol (and their test `vi.mock(...)` calls)
from a single specifier, matching the umbrella's prior `@anchor/index`;
- focused subpath entries: **`evidence-anchor/pdf`** (PDF adapter) and
**`evidence-anchor/dom`** (HTML/Markdown adapter). The root barrel re-exports
both for consumers that want a single import path.
## Public API (target surface)
```ts
import {
createSelectors,
resolveSelectors,
type DocumentViewerAdapter,
type AnchorResolution,
} from "@citation-evidence/evidence-anchor";
```
Resolution is explicit about uncertainty — `AnchorResolution.status` is one of
`resolved` / `ambiguous` / `unresolved` / `stale` with a `0..1` confidence, so a
caller can highlight, ask the user to confirm, or mark a citation stale rather
than silently highlight the wrong passage.