Implement CE-WP-0002 T01-T02: engine types + PDF viewer adapter spike

T01: shared engine types (Document, Selector union, Annotation, EvidenceItem,
branded IDs with newId factory) per wiki/SharedContracts.md §1-§3.

T02: react-pdf-highlighter-plus v1.1.4 spike behind the §5
DocumentViewerAdapter contract in src/anchor/. Pure round-trip math
extracted to pdf-selector-math.ts with 11 unit tests proving lossless
capture → selectors → JSON → restored-rects. ADR-0004 accepted; full
user-flow Playwright verification deferred to T09.

Adds Vite app shell (index.html, src/app/SpikeApp.tsx) so the spike is
exercisable via pnpm dev. tsconfig --noEmit prevents tsc -b from
littering src/ with stray .js outputs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 02:21:31 +02:00
parent 2f25f99cae
commit 2a7b05c190
22 changed files with 2538 additions and 13 deletions

45
src/shared/annotation.ts Normal file
View File

@@ -0,0 +1,45 @@
/**
* The Annotation type.
*
* Implements `wiki/SharedContracts.md` §1 (vocabulary), §2.1 (resolutionStatus)
* and `wiki/ArchitectureOverview.md` §4.4. Annotations are the *technical*
* mark on a document range — meaning and commentary live on EvidenceItem.
*/
import type { AnnotationId, DocumentId, RepresentationId } from "./ids";
import type { Selector } from "./selector";
/** Closed enum per `wiki/SharedContracts.md` §2.1. */
export type AnnotationResolutionStatus =
| "resolved"
| "ambiguous"
| "unresolved"
| "stale";
export interface Annotation {
readonly id: AnnotationId;
readonly documentId: DocumentId;
readonly representationId?: RepresentationId;
/**
* All available selectors for this passage, in order of expected
* resolution confidence. Per the §3 redundancy rule, the system stores
* every selector kind it could derive at capture time.
*/
readonly selectors: readonly Selector[];
/** Verbatim canonical text at capture time. */
readonly quote?: string;
/** Short human note attached to the technical mark. */
readonly note?: string;
/**
* Version of `normalize()` that was active when these selectors were
* stored. Recorded so future normalization changes can be detected as a
* migration concern. See `src/shared/text/normalize.ts`.
*/
readonly normalizeVersion: number;
readonly resolutionStatus?: AnnotationResolutionStatus;
readonly createdBy?: string;
/** ISO-8601 timestamp. */
readonly createdAt: string;
/** ISO-8601 timestamp. */
readonly updatedAt: string;
}