--- id: CE-WP-0006 type: workplan title: "Forms & review UX refinements — blob stability, scroll-center, linking, visual guide" domain: citation_evidence repo: citation-evidence repo_id: a677c189-b4e2-4f2a-9e48-faa482c277e6 topic_slug: citation_evidence_mvp topic_id: 96fa8e80-9f74-40f2-84cd-644e9747b9ec status: done owner: Bernd created: 2026-06-07 updated: 2026-06-07 depends_on_workplan: CE-WP-0005 planning_order: 6 planning_priority: high spec_refs: - wiki/ProductRequirementsDocument.md - wiki/ArchitectureOverview.md - wiki/SharedContracts.md - history/2026-06-07-ecosystem-state-assessment.md state_hub_workstream_id: "97493fdb-a793-4e79-bc7c-6a56b6085873" --- # CE-WP-0006 — Forms & Review UX Refinements User-facing polish before architectural expansion (Markdown/HTML, citation recovery, subsystem extraction). Addresses six issues observed during manual demo use on `http://localhost:5173/`. ## User requirements (locked) 1. **PDF blob load failure on evidence capture** — saving a new evidence item with commentary triggers `Unexpected server response (0) while retrieving PDF "blob:http://…"`. 2. **Center cited region on evidence select** — clicking an evidence item must scroll the document viewport so the marked passage is centred, not merely brought into view at an edge. 3. **Visual guide from footer strip only** — in Forms mode, connection lines must originate from the bottom evidence strip cards, not duplicate cards below the form. The field end of each line should attach to the **bottom edge of the form pane** to reduce overlap with field inputs. 4. **Evidence strip visibility filter** — the bottom row supports an optional filter (`all` | `attached`). Focusing a form field switches the filter to `attached` (evidence linked to that field only). 5. **Bidirectional linking** — linking must work both ways: - evidence → field (existing staged flow), and - field → evidence (select/focus field, then click evidence card to link). 6. **Link indicators on evidence cards** — connected cards show one or more link symbols in the upper-right. Hover shows a tooltip listing connected form field titles. Clicking a symbol removes that specific link. ## Scoping decisions - **No architecture extraction** in this workplan — all changes stay in the umbrella repo under existing `src/{work,binder,app,anchor,source}/` folders. - **Review mode and Forms mode** both benefit from T01 (blob stability) and T02 (scroll centre); T03–T06 are Forms-mode focused. - **ActiveEvidenceChips** (`src/app/forms/ActiveEvidenceChips.tsx`) is removed from the form pane layout; its rect-registration responsibility moves to the footer `EvidenceStrip`. The module may remain as a thin helper or be inlined — but it must not render duplicate cards below the form. - **Unlink** uses `bindings.unlinkEvidence(linkId)` (hard delete per current MVP semantics in `src/binder/services/bindings.ts`). ## Dependency order ``` T01 (blob URL stability) └─ T02 (viewport centre on evidence select) T03 (strip-only visual guide + remove duplicate chips) ├─ T04 (strip filter: all | attached) ├─ T05 (bidirectional linking) └─ T06 (link badges + tooltip + unlink) └─ T07 (integration tests) T08 (update workplans/README.md) — parallel once file exists ``` --- ## T01 — Fix PDF blob URL failure during evidence capture ```task id: CE-WP-0006-T01 priority: critical status: done state_hub_task_id: "3cc6a93a-e506-4477-8ef7-8c6dee405bc8" ``` **Problem:** uploaded PDFs are served via ephemeral `blob:` URLs minted by `PdfByteStore` and stamped onto `document.uri`. A full viewer remount (e.g. `ViewerShell` re-keyed on `scrollVersion`) or persistence round-trip can leave PDF.js fetching a revoked or stale blob URL. **Investigate and fix:** - `ViewerShell` should resolve the viewer URL from the live `PdfByteStore` entry for `document.id` when bytes are present; treat persisted `document.uri` blob URLs as hints only, never as the sole source after reload. - Avoid unnecessary full `PdfSpikeViewer` remounts when only scroll-target changes (split scroll trigger from component `key` if that is the root cause). - Ensure `captureSnapshot` / restore does not persist blob URLs that cannot be rehydrated, or re-mint blob URLs from stored bytes on session/engine restore when ZIP import or upload repopulates the byte store. - Add a regression test reproducing capture-after-upload without blob error (`src/work/` or `tests/integration/`). **Acceptance:** upload a PDF, select text, add commentary, save evidence — no PDF.js blob fetch error; viewer remains usable. --- ## T02 — Centre viewport on marked region when selecting evidence ```task id: CE-WP-0006-T02 priority: high status: done depends_on: [T01] state_hub_task_id: "e09d8fa1-862e-4c83-b1c4-19c6826e4610" ``` **Problem:** `scrollToHighlight` brings the passage into view but does not centre it. Users lose context when the highlight lands at the viewport edge. **Implement:** - Extend the viewer adapter scroll contract (`PdfSpikeViewer` / `react-pdf-highlighter-plus` utils) so scroll-to-annotation centres the highlight rect vertically (and horizontally when wider than viewport). - Wire through `useScrollToAnnotation` callers: `EvidenceSidebar`, `ViewerShell` highlight click, `ScrollBridge` in Forms mode. - Unit test for scroll math helper if extracted; DOM integration test asserting scroll request includes centre intent (mock utils acceptable per ADR-0004). **Acceptance:** click any evidence item in Review or Forms — the cited passage appears centred in the document pane. --- ## T03 — Visual guide from footer evidence strip; remove duplicate form cards ```task id: CE-WP-0006-T03 priority: high status: done depends_on: [T02] state_hub_task_id: "f30df6ee-a1c4-4a1b-80e0-d44e54f7b9b6" ``` **Problem:** `FormPane` renders `ActiveEvidenceChips` below the form while `EvidenceStrip` already shows the same cards at the bottom. The SVG overlay (`Overlay.tsx`) draws field→card→highlight using rects registered by the duplicate chips. **Implement:** - Remove `ActiveEvidenceChips` from `FormPane` in `FormsApp.tsx`. - Register `kind="evidence-card"` rects from `EvidenceStrip` buttons instead (one registration per visible card). - Update `Overlay` path geometry: - field end → **bottom-centre** of the active field row (or bottom of form pane when no specific field is active), - card end → top-centre of the strip card, - highlight end → unchanged. - Adjust `forms-overlay-e2e.dom.test.tsx` expectations for the new anchor points and single card location. **Acceptance:** only one evidence card row (footer strip); visual guide connects form bottom → strip card → PDF highlight with no duplicate cards under the form. --- ## T04 — Evidence strip filter (all vs attached-to-active-field) ```task id: CE-WP-0006-T04 priority: medium status: done depends_on: [T03] state_hub_task_id: "1dafa73d-1d8c-43b6-8934-2fbf038fc3be" ``` **Implement in `EvidenceStrip`:** - Filter state: `all` (default) | `attached`. - UI toggle in the strip header (e.g. "All" / "Linked to field"). - When a form field receives focus (`FormFieldActivated` or `useActiveState().activeTarget`), set filter to `attached` and show only evidence items with an `EvidenceLink` to that target. - When no field is active, `attached` filter shows evidence linked to any field in the demo schema, or falls back to `all` — pick the less surprising option and document it in the task commit message. - Clearing field focus returns filter to user’s last explicit choice (not forced back to `all`). **Acceptance:** focus "Summary" field → strip shows only evidence linked to `summary`; toggle restores full list. --- ## T05 — Bidirectional evidence ↔ field linking ```task id: CE-WP-0006-T05 priority: high status: done depends_on: [T03] state_hub_task_id: "2d7c9278-1ecc-4b59-ae3b-1a5d1e513885" ``` **Current:** evidence-first only — stage card in strip, then click field. **Add field-first:** - Click/focus a form field → enter "field staged for linking" state (banner parallel to existing evidence-staged banner). - Click an evidence card in the strip → `bindings.linkEvidenceToTarget` with the staged field as target; clear staging. - Evidence-first path remains unchanged. - Mutual exclusion: staging evidence clears field staging and vice versa. - Emit existing `EvidenceLinkCreated` event; link count chips on fields update. **Acceptance:** link works via evidence→field and field→evidence; cancel clears staging; duplicate link to same target is prevented or noop with user feedback. --- ## T06 — Link badges on evidence cards (tooltip + unlink) ```task id: CE-WP-0006-T06 priority: high status: done depends_on: [T05] state_hub_task_id: "064f6e48-e791-4cf5-9d04-df3fb7a11e48" ``` **On each evidence card in `EvidenceStrip`:** - Query `bindings.listTargetsForEvidence(item.id)`. - Render one link icon per connected form field in the card’s upper-right (stack or count badge when >3). - `title` / `aria-label` on hover: field label from `DEMO_SCHEMA` (fallback to `targetId`). - Click icon → `bindings.unlinkEvidence(linkId)` for that target; refresh strip and field link counts. - Do not trigger link-staging when clicking the unlink control (stop propagation). **Acceptance:** linked cards show indicators; tooltip names fields; click removes link without staging a new one. --- ## T07 — Integration tests for refined Forms UX ```task id: CE-WP-0006-T07 priority: high status: done depends_on: [T04, T05, T06] state_hub_task_id: "c50f9700-9902-4520-b8e2-6a010431b7ef" ``` Extend or add happy-dom integration tests: - `tests/integration/forms-link-flow.dom.test.tsx` — bidirectional linking. - `tests/integration/forms-overlay-e2e.dom.test.tsx` — strip-only rects, bottom anchor geometry (path count / data attributes). - `tests/integration/app-prd-scenario.dom.test.tsx` — capture-after-upload no blob error (if not covered in T01 unit test). - New or extended test for strip `attached` filter behaviour. **Acceptance:** `pnpm test` green; tests document the six user requirements. --- ## T08 — Update workplans README index ```task id: CE-WP-0006-T08 priority: low status: done state_hub_task_id: "715edb39-9b97-4d7f-b89b-71a0130326e8" ``` Update `workplans/README.md` to list CE-WP-0001..0006 with correct statuses (0001–0005 `done`, 0006 `active`). **Acceptance:** README table matches workplan frontmatter. --- ## Acceptance for the workplan After CE-WP-0006: 1. Evidence capture on uploaded PDFs does not break the viewer. 2. Selecting evidence centres the cited passage in the document viewport. 3. Forms visual guide uses footer strip cards only; lines attach to form bottom. 4. Evidence strip supports all/attached filter; field focus narrows to attached. 5. Linking works evidence→field and field→evidence. 6. Linked evidence cards show unlinkable field indicators with tooltips.