---
id: 09-editor-package
epic: walking-skeleton
title: editor package — React Flow board, iframe frame node, canvas-protocol client
type: technical-story
status: todo
feature: editor
depends-on: [02-core-runner-protocol]
blocks: [10-web-next-wiring]
created: 2026-07-12T10:24:14Z
---

## Goal

Ship `packages/editor` v0 — the first code of the ADR-029 rebuild: a React Flow board shell, one iframe frame node hosting the adapter origin, a canvas-protocol client proving the selection round-trip, a minimal zustand store (registry + selection only), and an editor-side selection overlay rendered from agent-reported geometry. Stories + tests from day one.

## Why

The editor ↔ iframe canvas seam across the origin boundary is the third risk this epic burns down (ADR-028): chrome renders as editor-side overlays from agent-reported geometry, never inside the repo's frame, and `targetOrigin` is pinned in both directions. ADR-029 mandates template conventions from the first commit — `component-must-have-story`/`-test`, React 19, no prototype vendoring — so the skeleton editor is the permanent foundation, not a throwaway.

## Done when

- `@repo/editor` exists as a green package following template conventions (vitest `@` alias, `rootDir: "."`, conformance ESLint rules active).
- Canvas-protocol client handles `runtime.ready`, geometry reports, and click-target resolution with pinned `targetOrigin` both directions; unit-tested against a scripted agent double (PRD Testing decisions).
- Zustand store holds registry + selection only (no document tree — DesignDoc v1 arrives with `design-doc-and-editor-foundation`).
- React Flow board with one frame node hosting the adapter iframe; the frame renders a single Element (the discovered component with default props) requested via `render-frame`.
- Selection overlay renders editor-side from agent-reported geometry; board pan/zoom stays editor-side (< 16 ms/frame — no protocol round-trip on drag; PRD budget).
- Every component has a story + test (`component-must-have-story` / `component-must-have-test`).
- React Flow + zustand runtime deps are covered by the `platform-retrofit` pre-approved traces (ADR-022) — no new trace expected; if any additional runtime dep is needed, it gets an `/evaluate-library` trace.
- `pnpm typecheck && pnpm lint && pnpm test && pnpm conformance && pnpm fallow:audit && pnpm coverage:diff` all pass after each task.

## In scope

- Package scaffold for `packages/editor`.
- Canvas-protocol client + scripted agent double tests.
- Zustand store (registry + selection).
- Board shell, frame node, selection overlay, stories + component tests.

## Out of scope

- Design-doc persistence — the frame is an ephemeral in-memory doc (PRD Out of scope).
- AI compose, Polish, history, multi-view frames, isolation, code panel.
- The web-next route hosting the board (story 10).

## Tasks

- [ ] Scaffold `packages/editor` (`@repo/editor`) as a green package shell using `pnpm turbo gen core-package` output as the baseline shape (adapted for a non-core package): tsconfig `rootDir: "."`, vitest config with `@` alias, conformance ESLint rules active; React 19; React Flow + zustand wired against the pre-approved `platform-retrofit` traces.
- [ ] Add the canvas-protocol client (pinned `targetOrigin` both directions; `runtime.ready`, geometry reports, click-target selection round-trip) unit-tested against a scripted agent double + the minimal zustand store holding registry + selection only.
- [ ] Add the React Flow board shell + one iframe frame node hosting the adapter origin + editor-side selection overlay rendered from agent-reported geometry; the frame renders a single Element (discovered component, default props) requested via `render-frame`; pan/zoom stays editor-side (< 16 ms/frame, no protocol round-trip on drag); stories + component tests for board/frame/overlay.
