Re-uploading the same PDF attaches bytes to the existing document (keeping
evidence) instead of creating a twin. On restore, merge duplicate fingerprint
groups and migrate annotations onto the evidence-bearing primary.
Stop inventing /fixtures/pdfs/<title> URLs when blob bytes are missing;
rely on IndexedDB-hydrated byte store. Seeded tests set an explicit fixture
uri. Session metadata already survived; PDF bytes now survive too.
Alias and dedupe pdfjs-dist so GlobalWorkerOptions.workerSrc set in main.tsx
reaches getDocument in the linked evidence-source package; allow sibling fs roots.
Maintainer decision, 2026-07-29: adopts TRSL V1C1 as this repo's
preliminary governing license, per target-revenue's
workplans/TREV-WP-0008-governance-and-pilot-rollout.md T05. Full
specialist legal review is deferred until out of beta (target-revenue
SCOPE.md §1). No Phase is yet declared for this repo.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cut review mode over to the extracted citation-work package instead of a local
src/work/ implementation.
- Add @citation-evidence/work as a link: dependency
- Repoint the @work alias (tsconfig + vite) to ../citation-work/src/work and
allow vite fs access to the sibling
- Remove the local src/work/ implementation (now owned by citation-work)
Typecheck, lint, and the full test suite (51 tests) pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cut over the binder subsystem to the extracted @citation-evidence/
evidence-binder repo. The @binder alias (tsconfig + vite) now points at
../evidence-binder/src, the duplicate src/binder/ tree is deleted, and
vite fs.allow is widened to serve the sibling checkout.
No app code changed — all imports were already via the @binder alias.
typecheck + lint green, 58 tests passing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the in-repo src/anchor/ slice with a dependency on the extracted
@citation-evidence/evidence-anchor package (link:../evidence-anchor).
- package.json: add the link dependency
- repoint all @anchor/{index,selectors,types} imports and vi.mock targets to
the package barrel; the node-env anchor-source-roundtrip test uses the pure
./selectors and ./types subpaths (no pdfjs pulled into a node environment)
- drop the @anchor alias from tsconfig paths and vite resolve
- delete src/anchor/ (behavior now owned by evidence-anchor)
Verified green: pnpm typecheck, pnpm test (26 files / 95 tests), pnpm build.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the unfilled template with the umbrella's actual boundary:
app/viewer/session + anchoring/evidence/binders in scope; headless
ingest (evidence-source) and contracts (citation-engine) out of scope.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the local src/source PDF slice with the standalone
@citation-evidence/evidence-source package (link:../evidence-source).
- src/source/index.ts is now a thin façade re-exporting the ingest core
and browser upload helpers from the package
- viewer-url stays local (viewer concern) but takes PdfByteStore from
the package
- extracted ingest/extract/fingerprint/byte-store/upload files removed
- anchor-source round-trip integration test now exercises the package
across the repo boundary
Full suite (125 tests), typecheck, and lint all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sync AGENTS.md, CLAUDE.md, and .claude/rules from updated project_rules
templates: workplan-first session protocol, legacy terminology footnote,
and GET /workplans/ examples.
Honest first-pass maturity vector grounded in README/docs/tests present
in this repo; no invented evidence. Flagged for human review before
publish. See reuse-surface history/2026-07-06-coverage-classification.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Align agent files with on-disk workplan prefixes (infer from workplan ids)
- Set workplan domain to registered domain_slug; add topic_slug where applicable
- Repair frontmatter delimiter formatting; migrate legacy task status literals
- Regenerate AGENTS.md, CLAUDE.md, and .claude/rules from State Hub templates
Verify sibling citation-engine checkout, link dependency resolution,
toolchain, and absence of stale in-repo engine copies. Prints actionable
fix hints when the installation layout is wrong.
Capture mode state lived only in React memory and was lost when
reopening a session or remounting EngineProvider.
- Add per-session localStorage capture snapshot (schema, values, links)
- Restore on session mount; persist on field/schema/link changes
- Seed binder links from storage without spurious bus events
- Clean up capture key when session is deleted
- Integration test for reload persistence
PdfLoader reloads the PDF when its document prop is a new object each
render. Memoize the loader config on pdfUrl only.
Also stabilize SpikeHighlightContainer via context (no remount on focus
change) and narrow scroll-effect deps to highlight id signature.
- Wire fieldValues state in FormsApp so controlled inputs persist typed data
- Add runScrollToHighlightJob with rAF retries when utils/highlights not ready
- Re-trigger scroll when highlights update after PDF load
- Tests: scroll-job unit test, forms-field-values integration tests
- Workplan CE-WP-0008 marked done
The version of pdf_viewer.css bundled with react-pdf-highlighter-plus
is only a minimal *override* (≈40 lines: opacity, z-index, blend
mode). It's missing the foundational rules that PDF.js's TextLayer
relies on — `position: absolute`, `inset: 0`, and the entire
`--scale-factor` CSS-variable machinery that PDF.js 4.x uses to
position each glyph.
Without those rules, each text-layer span gets rendered with default
positioning context and `font-size: calc(<base> * var(--scale-factor))`
collapses to 0 → spans either pile up at the top-left of the page or
land at wrong y-coordinates regardless of where the glyph actually
sits on the canvas. The reported symptom ("origin seems to be the top
of the page always") matches exactly.
Importing `pdfjs-dist/web/pdf_viewer.css` first, then the library's
overrides on top, gives PDF.js the CSS it expects.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Strong likelihood that the "text layer is misplaced / body text not
selectable" symptoms across multiple PDFs come from PDF.js falling
back to substitute font metrics. Without the cmaps directory (CID
character maps for non-Latin fonts) and the standard_fonts directory
(Helvetica/Times/Courier metrics for unembedded standard fonts), the
canvas glyphs use embedded font data while the text-layer span
positions are computed from fallback metrics. The two diverge — text
spans land in the wrong place, or text content can't be decoded at
all, leaving the body unselectable.
Both directories are now copied into the served root by
vite-plugin-static-copy and passed to pdfjs.getDocument() as
`cMapUrl: "/cmaps/"` + `cMapPacked: true` + `standardFontDataUrl:
"/standard_fonts/"` via PdfLoader's `document` prop (which accepts a
full DocumentInitParameters object).
If this is the right diagnosis, the textLayer overlay should now line
up with the visible glyphs on the same PDFs that were producing
fragmented captures. If the body text is still unselectable, the PDF
genuinely lacks a text layer for those glyphs (image-only content)
and OCR would be the only path forward.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>