Promote DomRange and Structural selector types for non-PDF anchoring
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 9s

Define real DomRangeSelector, StructuralSelector, StructureMap, and
containerPath fields so evidence-anchor can implement HTML/Markdown
selector creation and resolution. Update SharedContracts.md with field
shapes and DomSelectionCapture payload.
This commit is contained in:
tegwick 2026-07-09 09:18:42 +02:00
parent 67a3d82dfa
commit 86d10e7e90
3 changed files with 111 additions and 12 deletions

View file

@ -6,6 +6,7 @@
*/
import type { DocumentId, RepresentationId } from "./ids";
import type { DomNodePath, StructuralPathSegment } from "./selector";
/**
* The kind of normalized view derived from a source document.
@ -56,10 +57,23 @@ export interface PageOffsetRange {
export type OffsetMap = readonly PageOffsetRange[];
/**
* Reserved for `StructuralSelector` (heading/section/AST path).
* Not implementable in MVP type is `never` to enforce that at compile time.
* Maps canonical-text offset ranges to structural paths for non-paginated
* representations (`html-dom`, `markdown-rendered`).
*
* Entries are sorted by `globalStart`, are non-overlapping, and together
* cover `[0, canonicalText.length)`.
*/
export type StructureMap = never;
export interface StructureRange {
/** Inclusive canonical-text offset where this block begins. */
readonly globalStart: number;
/** Exclusive canonical-text offset where this block ends. */
readonly globalEnd: number;
readonly path: readonly StructuralPathSegment[];
/** DOM path to the block's text container, when captured from a viewer. */
readonly containerPath?: DomNodePath;
}
export type StructureMap = readonly StructureRange[];
/** A source document known to the system. */
export interface Document {

View file

@ -7,9 +7,8 @@
*
* The MVP implements the four PDF-relevant variants
* (`TextQuoteSelector`, `TextPositionSelector`, `PdfRectSelector`,
* `PdfPageTextSelector`). The other three kinds (DOM, structural, fragment)
* are reserved as `never`-typed stubs so adding them later is a localised
* change.
* `PdfPageTextSelector`) plus DOM/structural selectors for HTML/Markdown.
* `FragmentSelector` remains a `never`-typed stub.
*/
/** Exact quote with optional surrounding context (W3C-aligned). */
@ -54,11 +53,41 @@ export interface PdfPageTextSelector {
readonly end: number;
}
/** Reserved for HTML/Markdown viewer adapters. Not implementable in MVP. */
export type DomRangeSelector = never;
/**
* Child-index path from the document root to a text container node.
* Each entry is the 0-based index among `childNodes` at that level.
*/
export type DomNodePath = readonly number[];
/** Reserved for heading/section/AST-path locators. Not implementable in MVP. */
export type StructuralSelector = never;
/** DOM range for rendered HTML/Markdown (W3C Range-aligned). */
export interface DomRangeSelector {
readonly type: "DomRangeSelector";
readonly startPath: DomNodePath;
readonly startOffset: number;
readonly endPath: DomNodePath;
readonly endOffset: number;
}
/** One segment of a structural path (heading, section, or block). */
export interface StructuralPathSegment {
readonly kind: "heading" | "section" | "block";
/** 0-based index among siblings of the same kind at this level. */
readonly index: number;
/** Heading level (16) when `kind` is `heading`. */
readonly level?: number;
/** Snapshot of heading/section label text when known. */
readonly label?: string;
}
/** Structural locator for re-render-stable anchoring in HTML/Markdown. */
export interface StructuralSelector {
readonly type: "StructuralSelector";
readonly path: readonly StructuralPathSegment[];
/** Inclusive start offset within the resolved block's canonical text. */
readonly startOffset: number;
/** Exclusive end offset within the resolved block's canonical text. */
readonly endOffset: number;
}
/** Reserved for exported deep-link fragments. Not implementable in MVP. */
export type FragmentSelector = never;

View file

@ -148,6 +148,38 @@ StructuralSelector heading/section/AST path
FragmentSelector exported fragment / deep link (export-only)
```
Field shapes (non-PDF selectors, EANCH-WP-0003):
```ts
type DomNodePath = readonly number[]; // child-index path from document root
interface DomRangeSelector {
type: "DomRangeSelector";
startPath: DomNodePath;
startOffset: number;
endPath: DomNodePath;
endOffset: number;
}
interface StructuralPathSegment {
kind: "heading" | "section" | "block";
index: number;
level?: number; // headings only
label?: string;
}
interface StructuralSelector {
type: "StructuralSelector";
path: readonly StructuralPathSegment[];
startOffset: number;
endOffset: number;
}
```
`StructureMap` on `DocumentRepresentation` maps canonical-text spans to
structural paths (sorted, non-overlapping). Ingest pipelines may omit it;
viewer adapters populate it at selection time.
**Selector redundancy rule:** when an annotation is created, the system stores
*all selector types that are available* for that document representation, not
just one. Resolution tries them in order of expected confidence and stops at
@ -218,8 +250,32 @@ interface DocumentViewerAdapter {
}
```
MVP delivers a single `PDFViewerAdapter`. HTML and Markdown adapters are
deferred.
MVP delivers a single `PDFViewerAdapter`. HTML and Markdown adapters ship in
`evidence-anchor/dom`.
`SelectionCapture` is a discriminated union:
```ts
interface PdfSelectionCapture {
kind: "pdf";
text: string;
page: number;
rects: readonly NormalizedRect[];
boundingRect?: NormalizedRect;
}
interface DomSelectionCapture {
kind: "dom";
text: string;
startPath: DomNodePath;
startOffset: number;
endPath: DomNodePath;
endOffset: number;
structuralPath?: readonly StructuralPathSegment[];
}
type SelectionCapture = PdfSelectionCapture | DomSelectionCapture;
```
---