diff --git a/.claude/ralph-loop.local.md b/.claude/ralph-loop.local.md new file mode 100644 index 0000000..a336f9d --- /dev/null +++ b/.claude/ralph-loop.local.md @@ -0,0 +1,21 @@ +--- +active: true +iteration: 1 +session_id: b236681f-560d-497b-aa7d-07eab42bba2b +max_iterations: 12 +completion_promise: "HEUREKA" +workplan_id: EANCH-WP-0001 +workplan_file: workplans/EANCH-WP-0001-intent-placeholder.md +started_at: "2026-07-08T18:31:44Z" +--- + +Read the workplan at `workplans/EANCH-WP-0001-intent-placeholder.md`. + +If every task has `status: done` AND frontmatter `status: done`: +run `rm -f .claude/ralph-loop.local.md` first (deactivates the loop so the stop hook exits cleanly), +then output HEUREKA. + +Otherwise implement the next `todo` task as described in the workplan. +Set task `in_progress` when starting, `done` when complete. +When all tasks are done set frontmatter `status: done`. + diff --git a/README.md b/README.md index c298f8e..eabce3d 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,82 @@ # evidence-anchor Selector creation, resolution, and the `DocumentViewerAdapter` contract that -every document viewer in the workspace implements. +every document viewer in the citation-evidence workspace implements. This repo +turns annotations from static marks into durable, reopenable source references. -## MVP status: INTENT only +- **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. -During the citation-evidence MVP, code lives upstream in -[`citation-evidence`](../citation-evidence/) under `src/anchor/`. This repo -currently holds `INTENT.md` describing what will move here. Contract -changes belong in -[`citation-evidence/wiki/SharedContracts.md`](../citation-evidence/wiki/SharedContracts.md), -not here. +See `SCOPE.md` for the boundary and `INTENT.md` for the long-range intent. -Per the dependency map, anchor depends on `shared/` and `engine/` only; -nothing in `binder/`, `source/`, or `work/` may flow back into it. +## Status: extracting from the umbrella + +The concrete anchor slice currently lives upstream in +[`../citation-evidence/src/anchor/`](../citation-evidence/src/anchor/). Workplan +`EANCH-WP-0001` moves it here as a standalone TypeScript package, wires the +umbrella to consume this package, and verifies the round-trip. Shared-contract +changes still happen in the umbrella (`citation-evidence/wiki/`), not here. + +## 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 (re-exports the surfaces below) + types.ts adapter-side types: SelectionCapture, + ResolvedAnchorTarget, AnchorResolution, + HighlightRenderOptions, DocumentViewerAdapter + selectors/ + index.ts createSelectors, resolveSelectors, DEFAULT_CONTEXT_CHARS + create.ts selector creation from a captured selection + resolve.ts resolution + the exact-match confidence ladder + create.test.ts + resolve.test.ts + pdf/ + pdf-selector-math.ts page number + normalized page-rectangle math + pdf-selector-math.test.ts + pdf-viewer-adapter.tsx concrete PDF DocumentViewerAdapter (from the spike) + highlight/ + scroll-job.ts scroll-to-target helper + scroll-job.test.ts + highlight-styles.css highlight rendering styles + debug-textlayer.css optional text-layer debugging styles +``` + +Boundary rules for the layout: + +- viewer-library imports (`pdfjs`, `react-pdf-highlighter-plus`) are confined to + `src/pdf/` — they never appear on `types.ts` or on the public surface; +- `src/selectors/` is pure (no viewer/UI deps) and depends only on + `citation-engine` shared types; +- the public entrypoint re-exports the stable surface consumers rely on: + `createSelectors`, `resolveSelectors`, the selector/resolution types, the + `DocumentViewerAdapter` contract, and the PDF adapter. + +## Public API (target surface) + +```ts +import { + createSelectors, + resolveSelectors, + type DocumentViewerAdapter, + type AnchorResolution, +} from "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. diff --git a/SCOPE.md b/SCOPE.md index d48e39a..59af1ce 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -8,130 +8,143 @@ ## One-liner - - +Selector creation, resolution, re-anchoring, and highlight/scroll contracts that +keep citation-evidence annotations attached to their source passages. --- ## Core Idea - - +An **anchor** is a resolvable reference to a passage in a document, represented +by several complementary *selectors* (visual, text, structural, context). Given +a stored selector set and a document representation, this repo answers: *where is +this passage now, and how confident are we?* — returning a confidence-scored +result (`resolved` / `ambiguous` / `unresolved` / `stale`) rather than a silent +guess. It also owns the `DocumentViewerAdapter` contract every viewer implements. --- ## In Scope - - +- selector **creation** from a captured viewer selection (`createSelectors`) +- selector **resolution** against a document representation (`resolveSelectors`) +- the exact-match confidence ladder and selector-redundancy rules +- PDF selector math (page number + normalized page rectangles, page-local text) +- the format-neutral `DocumentViewerAdapter` contract and the first PDF adapter +- scroll-to-target and highlight-render contracts + helpers +- anchor confidence scoring and ambiguous/unresolved/stale reporting -- -- -- +Selector *behavior* lives here; selector *type interfaces* live in +`citation-engine` (see ADR-0006 and SharedContracts §8). --- ## Out of Scope - - +- selector *type definitions* — owned by `citation-engine` (`shared/selector`) +- persistence policy, the canonical evidence domain model, citation-card rendering +- document ingestion, OCR, metadata extraction, external source lookup +- form-field binding semantics, guide-overlay UI, application shell / deployment +- becoming a viewer implementation itself (it defines the adapter, not the viewer) -- -- -- +During the umbrella-first MVP these belong to the appropriate citation-evidence +subsystem. This repo may depend on **`citation-engine` only** (DependencyMap §4). + +### Not in this extraction slice (EANCH-WP-0001) + +- full HTML/Markdown (`DomSelectionCapture`) selector implementation +- production-grade fuzzy / recovery-oriented re-anchoring +- `stale` and orphaned-annotation semantics beyond what upstream already ships + +These are real INTENT.md goals but are **registered as follow-on work**, not +built during the initial extract-and-verify pass. --- ## Relevant When - - -- -- -- +- creating anchors from a user text selection in a document viewer +- resolving stored selectors back into a representation to reopen a citation +- implementing a new `DocumentViewerAdapter` (PDF today; HTML/Markdown later) +- scrolling to and highlighting a cited passage --- ## Not Relevant When - - -- -- -- +- you need selector *type* shapes only — import from `citation-engine` +- you are working on ingestion, persistence, binding, or the app shell +- you need the integrated review workspace UX — that is `citation-work` / umbrella --- ## Current State - - -- Status: -- Implementation: -- Stability: -- Usage: - - +- Status: experimental — extracting from the umbrella into a standalone package +- Implementation: partial — pure selector + PDF adapter slice exists upstream in + `../citation-evidence/src/anchor/`; extraction tracked by EANCH-WP-0001 +- Stability: evolving — shared contracts stable, this repo's package API forming +- Usage: internal (consumed by `citation-evidence` during MVP) --- ## How It Fits - - -- Upstream dependencies: -- Downstream consumers: -- Often used with: +- Upstream dependencies: `citation-engine` (shared selector/document/annotation types) +- Downstream consumers: `citation-evidence` (umbrella), later `citation-work`, + `evidence-source`, `evidence-binder` +- Often used with: a concrete document viewer (PDF.js + react-pdf-highlighter-plus) --- ## Terminology - - - -- Preferred terms: -- Also known as: -- Potentially confusing terms: +- Preferred terms: anchor, selector, resolution, re-anchoring, highlight contract +- Also known as: "the anchoring layer" +- Potentially confusing terms: `Selector` (the *type* is engine-owned; the + *behavior* is anchor-owned — see ADR-0006) --- ## Related / Overlapping Repositories - - - -- +- `citation-engine` — owns shared selector/document/annotation type interfaces +- `citation-evidence` — umbrella; current home of the code being extracted +- `evidence-source` — document ingestion / representations (consumer) +- `citation-work` — review workspace UX (consumer) +- `evidence-binder` — evidence-to-target binding (consumer) --- ## Getting Oriented - - -- Start with: -- Key files / directories: -- Entry points: +- Start with: `INTENT.md` (intended responsibilities), then this file +- Key files / directories: upstream `../citation-evidence/src/anchor/` is the + extraction source; post-extraction the package layout is in `README.md` +- Entry points: `createSelectors`, `resolveSelectors`, `DocumentViewerAdapter` --- ## Provided Capabilities - - - - - --- ## Notes - +Shared contracts are maintained in the umbrella and must not be contradicted here: +`citation-evidence/wiki/SharedContracts.md`, `wiki/DependencyMap.md`, +`docs/decisions/ADR-0006-selector-ownership-split.md`. diff --git a/workplans/EANCH-WP-0001-intent-placeholder.md b/workplans/EANCH-WP-0001-intent-placeholder.md index ba35700..3edbcf6 100644 --- a/workplans/EANCH-WP-0001-intent-placeholder.md +++ b/workplans/EANCH-WP-0001-intent-placeholder.md @@ -104,7 +104,7 @@ T01 boundary + package shape ```task id: EANCH-WP-0001-T01 priority: high -status: todo +status: done state_hub_task_id: "ef88ff6a-590f-4858-a674-33f84c1d6116" ```