--- id: EANCH-WP-0003 type: workplan title: "Non-PDF selectors: HTML/Markdown DOM range + structural anchoring" domain: infotech repo: evidence-anchor status: proposed owner: codex topic_slug: citation_evidence_mvp created: "2026-07-08" updated: "2026-07-08" spec_refs: - INTENT.md - SCOPE.md - ../citation-evidence/wiki/SharedContracts.md - ../citation-evidence/docs/decisions/ADR-0006-selector-ownership-split.md state_hub_workstream_id: "04f8a4b7-41fe-4546-8471-364a8b9a6c26" --- # EANCH-WP-0003 — Non-PDF Selectors (HTML / Markdown) ## Goal Extend anchoring beyond PDFs to non-paginated documents (HTML, Markdown), delivering the `DomRangeSelector` and `StructuralSelector` concepts that `INTENT.md` names but the MVP left as `never`. The extracted package already models format-neutral resolution (`DocumentViewerAdapter`, canonical-text selectors); this workplan fills in the DOM branch of `SelectionCapture` and a concrete HTML/Markdown viewer adapter. Depends on the extraction (`EANCH-WP-0001`) being complete. Independent of the resolution-hardening track (`EANCH-WP-0002`) except where both touch the shared enum — coordinate contract changes in the umbrella wiki first. ## Background - `src/types.ts`: `DomSelectionCapture = never` (reserved) — the capture union only has a PDF branch today. - `citation-engine` shared selector types already declare `DomRangeSelector` and `StructuralSelector` as `never` placeholders; promoting them is a shared-contract change and must land in `citation-engine` first (ADR-0006: selector *types* live in engine). ## Task Breakdown ## T01 — Contract: promote DomRange/Structural selector types in citation-engine ```task id: EANCH-WP-0003-T01 status: todo priority: high state_hub_task_id: "de7df94f-2ddf-4920-949e-6e693131a9de" ``` Define the real `DomRangeSelector` and `StructuralSelector` shapes (DOM path + range offsets; heading/section/block/AST path) in `citation-engine`'s shared selector module, plus the `DomSelectionCapture` payload contract in the wiki. Land this in the engine + `SharedContracts.md` before writing anchor behavior. ## T02 — Selector creation from a DOM/Markdown selection ```task id: EANCH-WP-0003-T02 status: todo priority: high depends_on: [T01] state_hub_task_id: "aa1bc68d-c15a-41e0-813d-c4ccec4914c9" ``` Implement `createSelectors` for the DOM branch: build TextQuote + TextPosition (against canonical text) plus DomRange + Structural selectors from a captured DOM selection. Add unit tests mirroring the PDF create tests. ## T03 — Resolution for non-paginated documents ```task id: EANCH-WP-0003-T03 status: todo priority: high depends_on: [T02] state_hub_task_id: "2bdedc91-1ed2-41ed-b4a0-a9a0d7a6b4b0" ``` Extend `resolveSelectors` to resolve DomRange/Structural selectors and rank them in the confidence ladder alongside the existing text selectors, keeping paginated (PDF) and non-paginated resolution on shared concepts. Tests for re-render stability (structural fallback when offsets shift). ## T04 — HTML/Markdown viewer adapter ```task id: EANCH-WP-0003-T04 status: todo priority: medium depends_on: [T03] state_hub_task_id: "286267fe-d348-4494-bbe2-dd7818bcadbd" ``` Add a `DocumentViewerAdapter` implementation for rendered HTML/Markdown (selection capture, scroll-to-target, highlight render), behind a subpath export analogous to `evidence-anchor/pdf`, with viewer-specific deps confined to that boundary. ## T05 — Verification + close-out ```task id: EANCH-WP-0003-T05 status: todo priority: high depends_on: [T04] state_hub_task_id: "9ff39c83-eca8-46a1-9b28-8a728ddf220d" ``` Package green (`pnpm test`/`typecheck`/`lint`); engine contract change verified in `citation-engine`; any umbrella consumer green; `fix-consistency` clean; progress note.