Files
citation-evidence/workplans/CE-WP-0003-form-binding-visual-guide.md
tegwick d06a456c2a Establish shared-contracts home, dependency map, MVP workplans, and umbrella-first strategy
- INTENT.md: declare umbrella as the home for shared contracts; document
  umbrella-first MVP decision (code lives here until subsystems stabilize)
- wiki/SharedContracts.md: vocabulary, state enums, relation types,
  selector taxonomy, event vocabulary, viewer adapter contract,
  canonical text normalization, rect-registry contract
- wiki/DependencyMap.md: allowed dependency edges; folder layout +
  lint-rule strategy during umbrella-first phase
- history/2026-05-24-initial-assessment.md: alignment review, technical
  risks, and the umbrella-first pivot rationale
- workplans/CE-WP-0001..0004: four ralph-compatible workplans covering
  foundations, PDF review slice, form binding + visual guide, and
  citation card export — implementing PRD §20 end-to-end

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 16:42:25 +02:00

247 lines
7.1 KiB
Markdown

---
id: CE-WP-0003
type: workplan
title: "Form binding + visual guide — EvidenceLink, rect registry, SVG overlay"
domain: citation_evidence
repo: citation-evidence
repo_id: a677c189-b4e2-4f2a-9e48-faa482c277e6
status: todo
owner: Bernd
created: 2026-05-24
updated: 2026-05-24
depends_on_workplan: CE-WP-0002
spec_refs:
- wiki/ProductRequirementsDocument.md
- wiki/ArchitectureOverview.md
- wiki/SharedContracts.md
---
# CE-WP-0003 — Form Binding + Visual Guide
Build the evidence-backed form mode and the SVG visual guide overlay.
After this workplan, a user can:
1. Open a form next to the document viewer.
2. Drag (or click-to-link) an evidence item from the sidebar onto a form
field.
3. Click a form field → its linked evidence items appear → the active
evidence's source passage is scrolled into view and highlighted → an SVG
guide visually connects the field, the evidence card, and the highlight.
4. Cycle through multiple evidence items on the same field.
This is the workplan that stress-tests the rect-registry contract from
`wiki/SharedContracts.md` §7. The form, the evidence card, and the viewer's
highlight all need to publish rects to a single overlay that re-renders on
scroll/resize/focus.
## Dependency Order
```
T01 (EvidenceLink + EvidenceSet types + relation/status enums)
└─ T02 (binding service + in-memory link repo + active-state machine)
└─ T03 (rect registry — the contract from SharedContracts.md §7)
└─ T04 (form schema + simple field renderer)
└─ T05 (side-by-side layout + drag-or-click to link)
└─ T06 (active-evidence cycling on a field)
└─ T07 (SVG visual guide overlay)
└─ T08 (E2E test of PRD scenario steps 5-9)
```
---
## T01 — `EvidenceLink` + `EvidenceSet` types
```task
id: CE-WP-0003-T01
priority: critical
status: todo
```
Add under `src/shared/`:
- `src/shared/evidence-link.ts``EvidenceLink`, `EvidenceLink.status`
enum per SharedContracts §2.4, `EvidenceLink.relation` enum per §2.5,
`EvidenceTarget` generic shape
- `src/shared/evidence-set.ts``EvidenceSet` with `activeEvidenceItemId`
No services. Pure shapes.
Add a unit test asserting that the union of all enum values matches the
`SharedContracts.md` lists exactly — if someone adds a value without
updating the doc, the test fails.
---
## T02 — Binding service + in-memory link repo + active-state machine
```task
id: CE-WP-0003-T02
priority: high
status: todo
depends_on: [T01]
```
Under `src/binder/`:
- `repos/in-memory-links.ts` — Map-backed `EvidenceLinkRepository`
- `services/bindings.ts``linkEvidenceToTarget`, `unlinkEvidence`,
`listEvidenceForTarget`, `setActiveEvidence`
- `state/active.ts` — a small machine tracking
`(activeTarget, activeEvidenceItem, activeAnnotation)`. Exposed as a React
context.
Emit the events from SharedContracts §4 (`EvidenceLinkCreated`,
`EvidenceItemActivated`, `FormFieldActivated`).
---
## T03 — Rect registry (the SharedContracts §7 contract)
```task
id: CE-WP-0003-T03
priority: critical
status: todo
depends_on: [T02]
```
Implement under `src/binder/visual-guide/`:
- `rect-registry.ts``RectRegistry` with `register`, `getRect`,
`subscribe` per SharedContracts §7
- `react-hooks.ts``useRegisterRect(kind, id, ref)` for components to
register a ref-derived rect
- `events.ts` — registry emits `rect-changed` events on
scroll/resize/focus/active-evidence-change (use ResizeObserver +
IntersectionObserver + window resize + window scroll listeners)
Unit tests: register a fake field, evidence card, and highlight; mutate
their bounding rects; assert subscribers fire with the new rects.
**This contract must not change after T03.** Three subsystems will depend on
it in T05/T06/T07.
---
## T04 — Form schema + simple field renderer
```task
id: CE-WP-0003-T04
priority: medium
status: todo
depends_on: [T01]
```
A deliberately minimal form schema lives in `src/app/forms/demo-schema.ts`:
```ts
type FormFieldSchema =
| { type: "text"; id: string; label: string }
| { type: "textarea"; id: string; label: string }
| { type: "date"; id: string; label: string };
```
JSON Schema is **not** used yet — defer that to a later ADR. The MVP form
just needs to render 3-4 fields and accept evidence links.
- `src/work/FormRenderer.tsx` renders the schema as a basic form
- Each field registers itself with the rect registry as kind `"field"` with
the field's `id`
---
## T05 — Side-by-side layout + link evidence to field
```task
id: CE-WP-0003-T05
priority: high
status: todo
depends_on: [T02, T04]
```
A new app route `/forms/demo` shows the side-by-side layout from Architecture
§12.2:
- Left: `FormRenderer` with a demo schema (3 fields)
- Right: viewer (reusing `ViewerShell` from CE-WP-0002)
- Bottom strip or popover: evidence list
Linking interaction: click an evidence item, then click a field → link
created. (Drag-and-drop is a polish item, not MVP.) Visual indication on
linked fields (e.g. a chip showing the count of linked evidence items).
---
## T06 — Active-evidence cycling on a field
```task
id: CE-WP-0003-T06
priority: high
status: todo
depends_on: [T05]
```
When a field is focused:
1. Binder loads the field's evidence set.
2. The first evidence item becomes active.
3. The viewer scrolls to and highlights its annotation.
4. Keyboard `Tab`/`Shift-Tab` within the field's evidence chips cycles
active evidence; viewer scrolls accordingly.
5. The evidence sidebar highlights the active evidence card.
Each evidence card registers itself with the rect registry as
`"evidence-card"`.
---
## T07 — SVG visual guide overlay
```task
id: CE-WP-0003-T07
priority: high
status: todo
depends_on: [T03, T06]
```
Implement `src/binder/visual-guide/Overlay.tsx`:
- Single absolutely-positioned SVG covering the viewport
- Subscribes to the rect registry
- On every change, redraws two curves: `field → evidence-card` and
`evidence-card → highlight`
- Active-only — only the currently active triple gets drawn
- Throttled to animation frames
Acceptance: scroll the viewer, resize the window, change active evidence —
the guide tracks every change without visible lag.
The viewer adapter from CE-WP-0002 must expose
`getHighlightClientRects(annotationId)` so the highlight's rect can be
registered.
---
## T08 — E2E test of PRD scenario steps 5-9
```task
id: CE-WP-0003-T08
priority: high
status: todo
depends_on: [T05, T07]
```
Extend the Playwright E2E from CE-WP-0002-T09:
5. Navigate to `/forms/demo`.
6. Link the previously-created evidence item to the "summary" field.
7. Click the "summary" field.
8. Assert the field, the evidence card, and the highlight all have an
`aria-current="true"` (or equivalent active marker).
9. Assert the SVG overlay contains exactly two `<path>` elements (one
field→card, one card→highlight).
10. Scroll the viewer; assert the SVG paths' endpoints update within the
next animation frame.
If this passes, the form-binding slice is complete and CE-WP-0004 may run
in parallel with any deferred polish work.