Run 2: ux-prototype Bridge & Highlights
Overview
Section titled “Overview”Implement the full Agentation → Hypothesis bridge in the ux-prototype Storybook site: API proxy, annotation transform, bridge integration with localStorage cleanup, Hypothesis sidebar embed, and DOM highlight layer with badge rendering.
Repository & Branch Setup
Section titled “Repository & Branch Setup”- Repository:
/ux-prototype - Base branch:
jmpicnic/item-image-upload-components - Working branch:
jmpicnic/integrate-agentation-hypothesis - Worktree: Required — other sessions are active on the repo.
- Path:
integrate-hypothesis-worktrees/ux-prototype - Create from base branch before starting work.
- Path:
Worktree Strategy
Section titled “Worktree Strategy”Single agent, single worktree. No integration branch needed.
# Create worktreegit -C /Users/jmp/code/arda/ux-prototype worktree add \ /Users/jmp/code/arda/integrate-hypothesis-worktrees/ux-prototype \ -b jmpicnic/integrate-agentation-hypothesis \ jmpicnic/item-image-upload-componentsAll tool calls (Read, Edit, Write, Glob, Grep, Bash) must use absolute paths
rooted at /Users/jmp/code/arda/integrate-hypothesis-worktrees/ux-prototype.
Cleanup
Section titled “Cleanup”After all work is complete and the user signals approval:
git -C /Users/jmp/code/arda/ux-prototype worktree remove \ /Users/jmp/code/arda/integrate-hypothesis-worktrees/ux-prototypeEntry Criteria
Section titled “Entry Criteria”| # | Criterion | Verification Command | Expected Output |
|---|---|---|---|
| 1 | Base branch exists locally | git -C /Users/jmp/code/arda/ux-prototype branch --list jmpicnic/item-image-upload-components | Branch name listed |
| 2 | Worktree created successfully | test -d /Users/jmp/code/arda/integrate-hypothesis-worktrees/ux-prototype/.storybook | Exit code 0 |
| 3 | Storybook builds on base branch | cd /Users/jmp/code/arda/integrate-hypothesis-worktrees/ux-prototype && npx storybook build 2>&1 | tail -5 | Build succeeded |
| 4 | Lint passes on base branch | cd /Users/jmp/code/arda/integrate-hypothesis-worktrees/ux-prototype && npm run lint | No errors |
Artifact Specifications
Section titled “Artifact Specifications”| Artifact | Path | Format | Description |
|---|---|---|---|
| API proxy middleware | .storybook/middleware.ts | TypeScript | Express middleware proxying Hypothesis API |
| Hypothesis config | .storybook/preview-body.html | HTML | embed.js injection into preview iframe |
| Bridge constants | .storybook/addons/hypothesis-bridge/constants.ts | TypeScript | Group ID, tag names, proxy base URL |
| Annotation transform | .storybook/addons/hypothesis-bridge/transform.ts | TypeScript | Agentation JSON → Hypothesis payload |
| Proxy client | .storybook/addons/hypothesis-bridge/client.ts | TypeScript | Fetch wrapper for proxy endpoints |
| Highlight layer | .storybook/addons/hypothesis-bridge/highlight-layer.tsx | React TSX | Badge rendering + positioning + observers |
| Highlight decorator | .storybook/addons/hypothesis-bridge/with-highlights.tsx | React TSX | Storybook decorator |
| Transform tests | .storybook/addons/hypothesis-bridge/__tests__/transform.test.ts | Vitest | Field mapping, URL normalization, tag generation, edge cases |
| Client tests | .storybook/addons/hypothesis-bridge/__tests__/client.test.ts | Vitest | Proxy URL construction, fetch mocking, error handling |
| Middleware tests | .storybook/addons/hypothesis-bridge/__tests__/middleware.test.ts | Vitest | Route matching, token injection, unproxied route rejection |
| Highlight utils tests | .storybook/addons/hypothesis-bridge/__tests__/highlight-utils.test.ts | Vitest | Selector tag parsing, severity color mapping, annotation filtering |
Task List
Section titled “Task List”Phase A: Infrastructure
Section titled “Phase A: Infrastructure”| # | Task | Persona | Depends On | Status | Acceptance Criteria |
|---|---|---|---|---|---|
| 2.1 | Create worktree and working branch from base | front-end | — | Pending | Worktree at expected path, on correct branch |
| 2.2 | Create constants.ts with group ID, tag names, proxy URL | front-end | 2.1 | Pending | Constants exported and importable |
| 2.3 | Create .storybook/middleware.ts — Hypothesis API proxy | front-end | 2.2 | Pending | POST/GET/PATCH routes proxy to hypothes.is with Bearer token from env var |
| 2.4 | Create transform.ts — Agentation → Hypothesis payload mapping | front-end | 2.2 | Pending | Maps all fields per spec: uri (normalized), text (Markdown + HTML comment), tags (Forensic, agentation, selector, intent, severity), target (CssSelector + optional TextQuoteSelector) |
| 2.5 | Create client.ts — thin HTTP client for proxy endpoints | front-end | 2.2 | Pending | postAnnotation() and searchAnnotations() functions |
| 2.6 | Create .storybook/preview-body.html — Hypothesis sidebar embed | front-end | 2.1 | Pending | embed.js loaded in preview iframe, sidebar toggle visible, openSidebar: false |
Phase B: Unit Tests for Infrastructure
Section titled “Phase B: Unit Tests for Infrastructure”Write tests immediately after the modules they cover, before integration.
| # | Task | Persona | Depends On | Status | Acceptance Criteria |
|---|---|---|---|---|---|
| 2.7 | Unit tests for transform.ts | front-end | 2.4 | Pending | See Transform Test Coverage |
| 2.8 | Unit tests for client.ts | front-end | 2.5 | Pending | See Client Test Coverage |
| 2.9 | Unit tests for middleware.ts | front-end | 2.3 | Pending | See Middleware Test Coverage |
Phase C: Integration + Highlight Layer
Section titled “Phase C: Integration + Highlight Layer”| # | Task | Persona | Depends On | Status | Acceptance Criteria |
|---|---|---|---|---|---|
| 2.10 | Modify with-agentation.tsx — bridge onSubmit + localStorage cleanup | front-end | 2.3, 2.4, 2.5 | Pending | On submit: transform, POST via proxy, clear localStorage via saveAnnotations(pathname, []), copy JSON to clipboard, dispatch hypothesis-annotations-updated event |
| 2.11 | Create highlight-layer.tsx — badge rendering React component. Extract pure utility functions (selector tag parsing, severity color mapping, annotation filtering, URL normalization) into a separate highlight-utils.ts module. | front-end | 2.5 | Pending | Fetches agentation-tagged annotations, resolves CSS selectors to DOM elements, renders numbered badges color-coded by severity, ResizeObserver + MutationObserver for repositioning, tooltip on hover |
| 2.12 | Unit tests for highlight-utils.ts | front-end | 2.11 | Pending | See Highlight Utils Test Coverage |
| 2.13 | Create with-highlights.tsx — Storybook decorator | front-end | 2.11 | Pending | Decorator renders HighlightLayer with current story URL |
| 2.14 | Modify preview.ts — register highlight decorator | front-end | 2.13 | Pending | decorators: [withAgentation, withHighlights, withFullAppProviders] |
Phase D: Verification
Section titled “Phase D: Verification”| # | Task | Persona | Depends On | Status | Acceptance Criteria |
|---|---|---|---|---|---|
| 2.15 | Run all checks: lint, tsc, Storybook build, tests | front-end | 2.14 | Pending | All pass with zero errors |
| 2.16 | Signal user for further instructions | front-end | 2.15 | Pending | User notified that work is complete and ready for review |
Test Coverage Specifications
Section titled “Test Coverage Specifications”Transform Test Coverage
Section titled “Transform Test Coverage”File: .storybook/addons/hypothesis-bridge/__tests__/transform.test.ts
| Test Case | Description |
|---|---|
| Maps all required fields | Full Agentation annotation → Hypothesis payload with uri, text, tags, group, target |
Includes Forensic tag | Every output includes Forensic in tags array |
Includes agentation origin tag | Every output includes agentation in tags array |
Generates selector: tag | elementPath encoded as selector:<cssPath> tag |
| Includes intent and severity tags | fix/change/question/approve and blocking/important/suggestion |
| Formats Markdown text body | HTML comment with elementPath, human-readable metadata block below --- |
| Normalizes URL | Strips volatile query params (viewMode, args), retains id |
Handles missing selectedText | No TextQuoteSelector in target when selectedText absent |
| Includes TextQuoteSelector | When selectedText present, adds TextQuoteSelector to target selectors |
| Handles missing optional fields | Gracefully handles absent reactComponents, cssClasses, intent, severity |
| Batch transform | Multiple annotations produce an array of payloads |
Client Test Coverage
Section titled “Client Test Coverage”File: .storybook/addons/hypothesis-bridge/__tests__/client.test.ts
| Test Case | Description |
|---|---|
postAnnotation sends POST to proxy | Calls /hypothesis-proxy/annotations with correct method, headers, body |
postAnnotation returns created annotation | Parses JSON response, returns annotation with id |
postAnnotation throws on HTTP error | Non-2xx response throws with status and message |
searchAnnotations sends GET with query params | Constructs URL with uri, tag, group, limit params |
searchAnnotations returns parsed results | Returns { total, rows } from response |
searchAnnotations URL-encodes parameters | Special characters in uri/tag are properly encoded |
Middleware Test Coverage
Section titled “Middleware Test Coverage”File: .storybook/addons/hypothesis-bridge/__tests__/middleware.test.ts
| Test Case | Description |
|---|---|
Proxies POST to /hypothesis-proxy/annotations | Forwards body to https://hypothes.is/api/annotations with Bearer token |
Proxies GET to /hypothesis-proxy/search | Forwards query params to https://hypothes.is/api/search with Bearer token |
Proxies PATCH to /hypothesis-proxy/annotations/:id | Forwards body to https://hypothes.is/api/annotations/:id |
| Injects Authorization header | Every proxied request includes Authorization: Bearer <token> |
| Returns Hypothesis response verbatim | Status code and body from Hypothesis API passed through |
| Rejects unrecognized routes | Requests to /hypothesis-proxy/other receive 404 |
Handles missing HYPOTHESIS_API_TOKEN | Returns 500 with descriptive error when env var not set |
Highlight Utils Test Coverage
Section titled “Highlight Utils Test Coverage”File: .storybook/addons/hypothesis-bridge/__tests__/highlight-utils.test.ts
| Test Case | Description |
|---|---|
Parses selector: tag | Extracts CSS selector from selector:div.container > form > button tag |
| Handles missing selector tag | Returns null when no selector: tag present |
| Maps severity to color | blocking → red, important → orange, suggestion → blue, default → gray |
| Filters agentation-origin annotations | Keeps only annotations with agentation tag |
| Extracts severity from tags | Identifies severity tag from mixed tag array |
| Extracts intent from tags | Identifies intent tag from mixed tag array |
| Normalizes story URL | Same logic as transform: strips volatile params, retains id |
| Parses HTML comment for elementPath | Extracts elementPath from <!-- agentation:elementPath=... --> |
Internal Dependency Graph
Section titled “Internal Dependency Graph”Phase A: Infrastructure 2.1 (worktree setup) ├── 2.2 (constants) ──┬── 2.3 (middleware) │ ├── 2.4 (transform) │ └── 2.5 (client) └── 2.6 (sidebar embed)
Phase B: Unit Tests 2.7 (transform tests) ← 2.4 2.8 (client tests) ← 2.5 2.9 (middleware tests) ← 2.3
Phase C: Integration + Highlights 2.10 (bridge onSubmit) ← 2.3 + 2.4 + 2.5 2.11 (highlight layer) ← 2.5 2.12 (highlight utils tests) ← 2.11 2.13 (highlight decorator) ← 2.11 2.14 (register decorator) ← 2.13
Phase D: Verification 2.15 (run checks) ← all above 2.16 (signal user) ← 2.15Parallelizable within Phase A: Tasks 2.3, 2.4, 2.5, 2.6 can proceed in any order after 2.2. Since this is a single agent, they are done sequentially.
Test-then-integrate: Phase B tests validate infrastructure modules before Phase C wires them together. This catches field mapping and API contract issues early, before integration makes debugging harder.
Exit Criteria
Section titled “Exit Criteria”| # | Criterion | Verification Command | Expected Output |
|---|---|---|---|
| 1 | Lint passes | cd $WT && npm run lint | No errors |
| 2 | TypeScript compiles | cd $WT && npx tsc --noEmit | No errors |
| 3 | Storybook builds | cd $WT && npx storybook build 2>&1 | tail -3 | Build succeeded |
| 4 | All unit tests pass (including new) | cd $WT && npm run test | All tests pass |
| 5 | Bridge files exist | ls $WT/.storybook/addons/hypothesis-bridge/ | transform.ts, client.ts, constants.ts, highlight-layer.tsx, highlight-utils.ts, with-highlights.tsx |
| 6 | Test files exist | ls $WT/.storybook/addons/hypothesis-bridge/__tests__/ | transform.test.ts, client.test.ts, middleware.test.ts, highlight-utils.test.ts |
| 7 | Middleware exists | test -f $WT/.storybook/middleware.ts | Exit code 0 |
| 8 | Sidebar embed exists | test -f $WT/.storybook/preview-body.html | Exit code 0 |
| 9 | Highlight decorator registered | grep -c 'withHighlights' $WT/.storybook/preview.ts | At least 1 |
Where $WT=/Users/jmp/code/arda/integrate-hypothesis-worktrees/ux-prototype.
Agent Prompt Templates
Section titled “Agent Prompt Templates”Front-End Engineer — fe-hypothesis-bridge
Section titled “Front-End Engineer — fe-hypothesis-bridge”You are working in a worktree at
/Users/jmp/code/arda/integrate-hypothesis-worktrees/ux-prototype. Use absolute paths for ALL tool calls.Goal: Implement the Agentation → Hypothesis bridge in the ux-prototype Storybook site: API proxy, annotation transform, bridge integration with localStorage cleanup, Hypothesis sidebar embed, and DOM highlight layer.
Base branch:
jmpicnic/item-image-upload-componentsWorking branch:jmpicnic/integrate-agentation-hypothesisTasks: See Run 2 task list in the project plan.
Specification: Read
/Users/jmp/code/arda/documentation/src/content/docs/roadmap/completed/integrate-agentation-hypothesis/specification.mdfor complete component specifications (Components 1-5).Key patterns to follow:
- Existing addon structure:
/Users/jmp/code/arda/ux-prototype/.storybook/addons/agentation-toggle/- Decorator pattern:
with-agentation.tsx- Storybook globals pattern:
preview.tsinitialGlobalsTag convention: All annotations must include
Forensictag by default.localStorage cleanup: After posting to Hypothesis, call
saveAnnotations(pathname, [])from theagentationpackage to clear submitted annotations.Testing strategy: Write unit tests for each pure-logic module immediately after implementing it (Phase B before Phase C). Extract testable pure functions from
highlight-layer.tsxinto ahighlight-utils.tsmodule. Test files go in__tests__/alongside the source. See the Test Coverage Specifications section for exact test cases per module. Use Vitest withvi.fn()/vi.mock()for mocking fetch and environment. The project uses@testing-library/jest-dom/vitest(not@testing-library/jest-dom).After completing all tasks: Run all checks (
npm run lint,npx tsc --noEmit,npm run test,npx storybook build). Signal the user for further instructions.
Handoff
Section titled “Handoff”Artifacts Consumed (from previous runs)
Section titled “Artifacts Consumed (from previous runs)”| Artifact | Source Run | Path |
|---|---|---|
| hypothesis-mcp API contract (optional) | Run 1 | /hypothesis-mcp/src/client.ts |
Note: Run 2 does not depend on Run 1’s completion. The bridge calls the
Hypothesis REST API directly, not the MCP. The target parameter with
CssSelector is a progressive enhancement.
Artifacts Produced (for subsequent runs)
Section titled “Artifacts Produced (for subsequent runs)”None — this is the final run.
Copyright: © Arda Systems 2025-2026, All rights reserved