EANCH-WP-0001 T02: bootstrap standalone TS package + test harness

Add package.json (name evidence-anchor, exports . and ./pdf, scripts
test/typecheck/lint), tsconfig.json (mirrors engine, DOM+jsx), vitest.config.ts
(happy-dom + react plugin), eslint.config.js (confines viewer libs to src/pdf/),
.nvmrc, and placeholder src entrypoints. Depends on @citation-evidence/engine
via sibling-checkout link only; no citation-evidence internals.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-07-08 20:37:59 +02:00
parent 08b3105454
commit 0e93b68982
9 changed files with 170 additions and 2 deletions

View file

@ -1,6 +1,6 @@
---
active: true
iteration: 1
iteration: 2
session_id: b236681f-560d-497b-aa7d-07eab42bba2b
max_iterations: 12
completion_promise: "HEUREKA"

1
.nvmrc Normal file
View file

@ -0,0 +1 @@
20.10.0

49
eslint.config.js Normal file
View file

@ -0,0 +1,49 @@
// ESLint flat config — keeps viewer-library imports behind the PDF adapter
// boundary and the selector/resolution core pure.
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import importPlugin from "eslint-plugin-import";
import globals from "globals";
const VIEWER_LIBS = ["pdfjs-dist", "react", "react-dom", "react-pdf-highlighter-plus"];
export default tseslint.config(
{
ignores: ["dist/", "node_modules/", "coverage/", "**/*.d.ts"],
},
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ["src/**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
globals: { ...globals.node, ...globals.browser },
},
plugins: {
import: importPlugin,
},
settings: {
"import/resolver": {
typescript: { project: "./tsconfig.json" },
},
},
},
{
// The pure core (selectors, resolution, highlight helpers) must not pull in
// any concrete viewer library — those live only under src/pdf/.
files: ["src/selectors/**/*.ts", "src/highlight/**/*.ts", "src/types.ts"],
rules: {
"no-restricted-imports": [
"error",
{
paths: VIEWER_LIBS.map((name) => ({
name,
message: "Viewer libraries are confined to src/pdf/ (adapter boundary).",
})),
},
],
},
},
);

59
package.json Normal file
View file

@ -0,0 +1,59 @@
{
"name": "evidence-anchor",
"version": "0.1.0",
"private": true,
"description": "Selector creation, resolution, re-anchoring, and highlight/scroll contracts for the citation-evidence ecosystem.",
"license": "Apache-2.0",
"type": "module",
"packageManager": "pnpm@9.15.0",
"engines": {
"node": ">=20.10.0"
},
"files": [
"src",
"README.md",
"SCOPE.md",
"INTENT.md",
"LICENSE"
],
"exports": {
".": "./src/index.ts",
"./pdf": "./src/pdf/index.ts"
},
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"lint": "eslint .",
"typecheck": "tsc -b --noEmit"
},
"dependencies": {
"@citation-evidence/engine": "link:../citation-engine"
},
"peerDependencies": {
"pdfjs-dist": "^4.4.168",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-pdf-highlighter-plus": "^1.1.4"
},
"devDependencies": {
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^20.14.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"eslint": "^9.7.0",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.30.0",
"globals": "^15.9.0",
"happy-dom": "^20.9.0",
"pdfjs-dist": "^4.4.168",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-pdf-highlighter-plus": "^1.1.4",
"typescript": "^5.5.4",
"typescript-eslint": "^8.0.0",
"vitest": "^2.0.5"
}
}

10
src/index.ts Normal file
View file

@ -0,0 +1,10 @@
// Public entrypoint for `evidence-anchor`.
//
// The stable surface consumers depend on is re-exported from here:
// - selector creation/resolution: ./selectors (T03)
// - adapter-side types + contract: ./types (T03)
// - the concrete PDF adapter: ./pdf (T04, also exposed at `evidence-anchor/pdf`)
//
// Populated during the extraction tasks; kept as an explicit placeholder so the
// package resolves and typechecks before the code lands.
export {};

6
src/pdf/index.ts Normal file
View file

@ -0,0 +1,6 @@
// Subpath entrypoint `evidence-anchor/pdf` — the concrete PDF viewer adapter and
// its helpers. Keeping the adapter behind a subpath lets pure consumers use the
// selector/resolution core without pulling PDF.js or React into their bundle.
//
// Populated in T04 (PDF adapter extraction); explicit placeholder for now.
export {};

26
tsconfig.json Normal file
View file

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "Bundler",
"jsx": "react-jsx",
"strict": true,
"noImplicitOverride": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noEmit": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"verbatimModuleSyntax": true,
"baseUrl": "."
},
"include": ["src", "vitest.config.ts"],
"exclude": ["node_modules", "dist"]
}

17
vitest.config.ts Normal file
View file

@ -0,0 +1,17 @@
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
// Pure selector/resolution tests are node-safe; the scroll/highlight and PDF
// adapter tests touch the DOM, so the default environment is happy-dom. The
// react plugin lets the PDF adapter (.tsx) compile under test.
//
// The one shared-type dependency, `@citation-evidence/engine`, resolves through
// its package `exports` map (`./shared`) via the sibling-checkout link — no
// local alias needed. Nothing here imports `citation-evidence` internals.
export default defineConfig({
plugins: [react()],
test: {
environment: "happy-dom",
globals: false,
},
});

View file

@ -144,7 +144,7 @@ here and what must stay elsewhere.
```task
id: EANCH-WP-0001-T02
status: todo
status: done
priority: high
depends_on: [T01]
state_hub_task_id: "59c07bc6-7a80-4f58-b1cf-ee2f0c26e8ed"