@agent-native/core 0.80.9 → 0.80.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +7 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/cli/design-connect.ts +28 -2
  5. package/corpus/core/src/cli/skills.ts +45 -24
  6. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +717 -0
  7. package/corpus/templates/design/actions/add-breakpoint.ts +143 -0
  8. package/corpus/templates/design/actions/add-localhost-screens.ts +5 -0
  9. package/corpus/templates/design/actions/apply-a11y-fix.ts +317 -0
  10. package/corpus/templates/design/actions/apply-component-prop-edit.ts +433 -0
  11. package/corpus/templates/design/actions/apply-design-state.ts +200 -0
  12. package/corpus/templates/design/actions/apply-design-token-edit.ts +202 -0
  13. package/corpus/templates/design/actions/apply-motion-edit.ts +450 -0
  14. package/corpus/templates/design/actions/apply-shader-fill.ts +404 -0
  15. package/corpus/templates/design/actions/apply-visual-edit.ts +191 -5
  16. package/corpus/templates/design/actions/capture-design-state.ts +224 -0
  17. package/corpus/templates/design/actions/connect-builder-app.ts +162 -0
  18. package/corpus/templates/design/actions/create-component.ts +447 -0
  19. package/corpus/templates/design/actions/create-design-branch.ts +263 -0
  20. package/corpus/templates/design/actions/create-design-state.ts +162 -0
  21. package/corpus/templates/design/actions/delete-design-state.ts +55 -0
  22. package/corpus/templates/design/actions/deploy-design-preview.ts +275 -0
  23. package/corpus/templates/design/actions/get-component-details.ts +242 -0
  24. package/corpus/templates/design/actions/get-design-branch-diff.ts +362 -0
  25. package/corpus/templates/design/actions/get-design-review.ts +314 -0
  26. package/corpus/templates/design/actions/get-design-surface-index.ts +582 -0
  27. package/corpus/templates/design/actions/get-motion-timeline.ts +99 -0
  28. package/corpus/templates/design/actions/index-components.ts +258 -0
  29. package/corpus/templates/design/actions/index-design-tokens.ts +273 -0
  30. package/corpus/templates/design/actions/list-design-extensions.ts +309 -0
  31. package/corpus/templates/design/actions/list-design-source-capabilities.ts +153 -0
  32. package/corpus/templates/design/actions/list-design-states.ts +72 -0
  33. package/corpus/templates/design/actions/migrate-inline-design-to-app.ts +298 -0
  34. package/corpus/templates/design/actions/open-component-source.ts +237 -0
  35. package/corpus/templates/design/actions/preview-component-prop-edit.ts +254 -0
  36. package/corpus/templates/design/actions/preview-design-token-edit.ts +113 -0
  37. package/corpus/templates/design/actions/preview-shader-fill.ts +189 -0
  38. package/corpus/templates/design/actions/remove-breakpoint.ts +103 -0
  39. package/corpus/templates/design/actions/remove-motion-timeline.ts +196 -0
  40. package/corpus/templates/design/actions/run-design-audit.ts +421 -0
  41. package/corpus/templates/design/actions/run-design-extension-action.ts +284 -0
  42. package/corpus/templates/design/actions/set-active-breakpoint.ts +39 -0
  43. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +1414 -71
  44. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +632 -43
  45. package/corpus/templates/design/app/components/design/DrawOverlay.tsx +1 -1
  46. package/corpus/templates/design/app/components/design/EditPanel.tsx +1391 -52
  47. package/corpus/templates/design/app/components/design/LayersPanel.tsx +4 -3
  48. package/corpus/templates/design/app/components/design/LocalSourceEditBanner.tsx +157 -0
  49. package/corpus/templates/design/app/components/design/MotionDock.tsx +1062 -0
  50. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1052 -98
  51. package/corpus/templates/design/app/components/design/ReviewPanel.tsx +759 -0
  52. package/corpus/templates/design/app/components/design/StatesPanel.tsx +579 -0
  53. package/corpus/templates/design/app/components/design/TokensPanel.tsx +573 -0
  54. package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +241 -0
  55. package/corpus/templates/design/app/components/design/index.ts +16 -0
  56. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +15 -6
  57. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +66 -3
  58. package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +145 -0
  59. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +42 -12
  60. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +1 -1
  61. package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +131 -0
  62. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +3 -1
  63. package/corpus/templates/design/app/i18n/zh-TW.ts +31 -0
  64. package/corpus/templates/design/app/i18n-data.ts +269 -0
  65. package/corpus/templates/design/app/pages/DesignEditor.tsx +2478 -386
  66. package/corpus/templates/design/changelog/2026-06-29-added-a-review-panel-in-the-design-editor-s-inspector-with-a.md +6 -0
  67. package/corpus/templates/design/changelog/2026-06-29-copying-and-pasting-layers-no-longer-shows-success-notificat.md +6 -0
  68. package/corpus/templates/design/changelog/2026-06-29-device-presets-in-all-screens-view-resize-the-selected-previ.md +6 -0
  69. package/corpus/templates/design/changelog/2026-06-29-layer-and-canvas-drags-keep-the-layer-list-stable-while-chan.md +6 -0
  70. package/corpus/templates/design/changelog/2026-06-29-layer-moves-can-be-undone-and-redone-without-flashing-the-ca.md +6 -0
  71. package/corpus/templates/design/changelog/2026-06-29-screen-previews-use-a-single-blue-hover-border-in-all-screen.md +6 -0
  72. package/corpus/templates/design/changelog/2026-06-29-selected-containers-show-draggable-padding-and-gap-guides-on.md +6 -0
  73. package/corpus/templates/design/changelog/2026-06-29-the-design-editor-adds-a-studio-layer-with-tokens-respon.md +6 -0
  74. package/corpus/templates/design/changelog/2026-06-30-accessibility-findings-now-offer-a-one-click-fix.md +6 -0
  75. package/corpus/templates/design/changelog/2026-06-30-component-instances-now-have-editable-props-in-the-inspe.md +6 -0
  76. package/corpus/templates/design/changelog/2026-06-30-inspect-code-now-shows-the-elements-opening-tag-at-a-gla.md +6 -0
  77. package/corpus/templates/design/changelog/2026-06-30-shader-fill-presets-can-now-be-applied-to-an-element.md +6 -0
  78. package/corpus/templates/design/changelog/2026-06-30-the-motion-timeline-can-now-add-a-track-to-any-element-a.md +6 -0
  79. package/corpus/templates/design/changelog/2026-06-30-visual-editor-selection-layer-paint-and-drawing-controls-are-more-reliable.md +6 -0
  80. package/corpus/templates/design/e2e/helpers.ts +10 -4
  81. package/corpus/templates/design/server/db/schema.ts +123 -0
  82. package/corpus/templates/design/server/plugins/db.ts +90 -0
  83. package/corpus/templates/design/shared/builder-app.ts +297 -0
  84. package/corpus/templates/design/shared/capability-resolver.ts +123 -0
  85. package/corpus/templates/design/shared/capture-sanitize.ts +70 -0
  86. package/corpus/templates/design/shared/code-layer.ts +1016 -71
  87. package/corpus/templates/design/shared/component-model.ts +239 -0
  88. package/corpus/templates/design/shared/design-review.ts +275 -0
  89. package/corpus/templates/design/shared/design-source-capabilities.ts +286 -0
  90. package/corpus/templates/design/shared/design-state.ts +112 -0
  91. package/corpus/templates/design/shared/design-surface-index.ts +258 -0
  92. package/corpus/templates/design/shared/motion-compiler.ts +278 -0
  93. package/corpus/templates/design/shared/motion-timeline.ts +193 -0
  94. package/corpus/templates/design/shared/responsive-classes.ts +452 -0
  95. package/corpus/templates/design/shared/shader-fill.ts +323 -0
  96. package/corpus/templates/design/shared/source-mode.ts +245 -0
  97. package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +6 -2
  98. package/corpus/templates/plan/changelog/2026-06-29-plan-canvases-open-without-an-initial-pan-and-zoom-flicker.md +6 -0
  99. package/dist/cli/design-connect.d.ts.map +1 -1
  100. package/dist/cli/design-connect.js +28 -2
  101. package/dist/cli/design-connect.js.map +1 -1
  102. package/dist/cli/skills.d.ts.map +1 -1
  103. package/dist/cli/skills.js +37 -21
  104. package/dist/cli/skills.js.map +1 -1
  105. package/dist/collab/routes.d.ts +1 -1
  106. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  107. package/dist/notifications/routes.d.ts +2 -2
  108. package/dist/observability/routes.d.ts +7 -7
  109. package/dist/resources/handlers.d.ts +2 -2
  110. package/dist/server/transcribe-voice.d.ts +1 -1
  111. package/package.json +1 -1
@@ -0,0 +1,717 @@
1
+ # Code-Native Design Studio — Canonical Implementation Plan
2
+
3
+ > Converged plan, merged from two independent passes (Claude + Codex) and their
4
+ > cross-reviews. This is the single source of truth; implement from this doc.
5
+ >
6
+ > - **Product / runtime-tier spine** (the organizing principle).
7
+ > - **Capability matrix + preview/apply actions + application-state shape +
8
+ > atomic-motion guardrail + screenshot acceptance criteria** (the contract).
9
+ > - **Builder-hosted branch + `fusion` first; our own durable container later.**
10
+ > - **First cheap win: Tokens on the existing Tweaks loop + CSS-first motion on
11
+ > inline designs.**
12
+ >
13
+ > Visual source of truth: the published visual plan
14
+ > <https://plan.agent-native.com/plans/plan-88dc4a09fb0c46bc> (workbench, motion
15
+ > dock, tokens, states, review, extensions). Its artboards are the acceptance
16
+ > references for the panels below.
17
+
18
+ ---
19
+
20
+ ## 0. Goal & thesis
21
+
22
+ Turn the Design template into a Figma-class editor where the canvas and the
23
+ codebase are two views of the same product. The thesis: **when a source can
24
+ safely support it, a visual edit writes real code, and a source edit shows up on
25
+ the canvas.** Keep the editor minimal and Figma-esque — left pages/layers,
26
+ central canvas, right inspector, and a bottom dock only when motion or review
27
+ needs it — and add code-backed components, tokens, motion, states/captures,
28
+ accessibility review, visual diffs, assets/shaders/plugins, and a real-app path.
29
+
30
+ ---
31
+
32
+ ## 1. Runtime tiers (the organizing principle)
33
+
34
+ The editor already has a `sourceType` contract — `inline | localhost | fusion`
35
+ (`templates/design/shared/source-mode.ts`). Treat those as **two capability
36
+ tiers**:
37
+
38
+ ### Tier A — Inline (HTML + Alpine), zero-setup
39
+
40
+ A design is a sandboxed iframe of semantic HTML + Tailwind + a little Alpine,
41
+ stored in SQL (`designs.data`, `design_files`, rendered via `srcdoc`). No build,
42
+ no module graph, no TypeScript, no real routes/server. This is the instant,
43
+ shareable, "open a URL and design" on-ramp and the default.
44
+
45
+ ### Tier B — Real app (localhost **or** fusion / Builder)
46
+
47
+ A design is backed by a real React/TS codebase.
48
+
49
+ - **`localhost`** — the bridge talks to a dev server on the user's machine
50
+ (`designLocalhostConnections`, `connect-localhost.ts`).
51
+ - **`fusion`** _(the new hosted tier)_ — connect Builder.io and run the app as a
52
+ Builder-hosted branch (today) or, later, our own durable container. Same
53
+ capabilities as localhost but hosted, collaborative, and deployable.
54
+
55
+ > `localhost` and `fusion` are the **same "real app" capability tier** seen
56
+ > through two transports. Everything gated to "real apps" works in both; the only
57
+ > difference is where the code lives.
58
+
59
+ ### 1.1 Tiers are coarse; capabilities are the real gate
60
+
61
+ The UI must **never infer write ability from `sourceType` alone.** Each source
62
+ advertises an explicit capability set, and every control reads it. A control is
63
+ **enabled**, **preview-only / read-only**, or a **migration CTA** purely as a
64
+ function of capabilities. This is what stops the agent or UI from ever promising
65
+ a write the bridge can't perform (localhost can read but not write _yet_; `fusion`
66
+ starts preview-only until its bridge is real). The tier table in §2 is the
67
+ _consequence_ of these capability sets, not a parallel switch. The capability
68
+ matrix is defined in §5.
69
+
70
+ ---
71
+
72
+ ## 2. Feature tiering — Alpine vs. real app
73
+
74
+ | Capability | Inline / Alpine | Real app (localhost / fusion) | Why |
75
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | ----------------------------- | ------------------------------------------------ |
76
+ | Reusable blocks / Alpine "components" — annotate a DOM subtree or `Alpine.data()` island; simple `x-data` variants | ✅ (kept deliberately **light**) | ✅ (superset) | Pure markup |
77
+ | **Full code components** — prop tables from TS / `cva` / `tailwind-variants`, Storybook variants, instance outlines, **jump to source**, edit canonical component, detach | **Real app** → CTA | ✅ | Needs module graph + TS types + multi-file edits |
78
+ | Tokens — live CSS-var editing (friendly swatches for the design's own `:root` vars) | ✅ | ✅ | Design owns its CSS vars |
79
+ | **Tokens-as-code** — parse `globals.css` / `tailwind.config` and **write back to source** | **Real app** → CTA | ✅ | Auto-parse + source write-back needs real files |
80
+ | **Motion** — multi-layer keyframe timeline → managed `<style data-agent-native-motion>` block | ✅ | ✅ | CSS is the runtime truth; works on any HTML |
81
+ | Motion source export — write to real CSS modules / `motion`-react two-way / Dev Mode export | **Real app** → CTA | ✅ | Two-way code round-trip needs real files |
82
+ | Responsive / breakpoints | ✅ | ✅ | CSS media queries |
83
+ | Simple design states (logged out, empty, loading, error) as alternate `x-data` / DOM | ✅ | ✅ | Markup snapshots |
84
+ | **Data fixtures & live captures** (real running-app data, route, props, API) | **Real app** → CTA | ✅ | No live data on a static design |
85
+ | Accessibility audit (contrast, tap targets, roles, alt) | ✅ | ✅ | Reads the rendered DOM |
86
+ | Version diff (`design_versions`) | ✅ | ✅ | SQL versions already exist |
87
+ | **Real branches + PRs + deploy** | **Real app** → CTA | ✅ | Needs git + branch + deploy |
88
+ | Extensions / shaders / asset library | ✅ | ✅ | Extensions are the Alpine substrate |
89
+ | Semantic a11y fixes in code; plugins needing the app's own APIs/build | **Real app** → CTA | ✅ | Needs real source / build |
90
+
91
+ **The one-line rule:** if a feature only needs the **rendered DOM or the design's
92
+ own HTML/CSS+SQL**, it ships in Alpine. If it needs the **module graph, TS types,
93
+ a real build, real routes, server data, or git/deploy**, it's a **real-app**
94
+ feature behind a Connect-Builder CTA. _Motion crosses into Alpine because we make
95
+ it CSS-first._
96
+
97
+ ---
98
+
99
+ ## 3. The "Make it real" upgrade flow (Connect Builder)
100
+
101
+ Advanced panels are never dead ends; they are CTAs. On an inline design, the
102
+ gated controls render an inline upgrade card (progressive disclosure — only when
103
+ the user reaches for a real-app feature):
104
+
105
+ > **Make this a real app** — connect Builder.io to unlock components, props, data
106
+ > states, branches, and deploys.
107
+
108
+ ### 3.1 What already exists vs. what's new
109
+
110
+ Most of the backend exists. The genuinely-new pieces are small:
111
+
112
+ 1. **Connect** _(exists)_ — the `connect-builder` card
113
+ (`packages/core/src/server/agent-chat-plugin.ts`, `kind:
114
+ "connect-builder-card"`, `{ configured, builderEnabled, connectUrl }`) runs the
115
+ Builder OAuth / `cli-auth` flow and stores a scoped credential
116
+ (`credential-provider.ts`). `builderEnabled` flips true once a branch project is
117
+ configured (`resolveBuilderBranchProjectId()`). Vault owns the secret; the app
118
+ owns a scoped reader.
119
+ 2. **Migrate** _(NEW)_ — there is no inline→React migration today. Feed the
120
+ design's semantic HTML **plus** its `:root` CSS vars / Brand Kit tokens as the
121
+ seed to the existing Builder cloud agent (`runBuilderAgent()` via
122
+ `startWorkspaceAppCreation()`, `packages/dispatch/.../app-creation-store.ts`),
123
+ producing a real React + Tailwind app. Tokens carry over 1:1 by seeding the
124
+ app's token config from the Brand Kit; annotated Alpine "components" map to real
125
+ components where possible (`implementWithDesignSystem` / `planWithDesignSystem`
126
+ from builder-mcp assist).
127
+ 3. **Provision** _(exists; today = Builder-hosted branch)_ —
128
+ `startWorkspaceAppCreation()` returns `{ branchName, url, status }`: a GitHub
129
+ branch in Builder's hosting running as a full React app, tracked pending until
130
+ merged. **No per-user container is required for v1.** _Our own isolated dev
131
+ containers are the `SandboxAdapter` Docker adapter — a blueprint
132
+ (`packages/core/blueprints/sandbox/docker.md`); only the local child-process
133
+ adapter is built. Treat self-hosted containers as an optional, heavier
134
+ follow-on._
135
+ 4. **Reconnect** _(NEW — implement `fusion`)_ — flip the design's `sourceType`
136
+ from `inline` to `fusion` (the enum + i18n exist; the bridge/rendering is the
137
+ stub to fill in). `fusion` points the editor at the Builder-hosted app's dev URL
138
+ and uses the bridge for snapshot + code context. Gated panels light up.
139
+ 5. **Deploy** _(exists)_ — merge the Builder branch → the existing template deploy
140
+ path (`packages/core/src/deploy/build.ts`, Netlify / CF Pages).
141
+
142
+ ### 3.2 The three genuinely-new pieces (everything else is reuse)
143
+
144
+ 1. **Migration**: inline HTML/Alpine + tokens → a real React seed for the Builder
145
+ cloud agent.
146
+ 2. **`fusion` source mode**: bridge + rendering so the editor drives a
147
+ Builder-hosted app the same way it drives an inline iframe.
148
+ 3. **Bridge write hardening**: promote `readFile` / `applyEdit` / `writeFile` from
149
+ `planned` → `available` behind the bridge permission model.
150
+
151
+ ### 3.3 Reversibility
152
+
153
+ Migration is additive and non-destructive: the original inline design is kept as a
154
+ `design_version` snapshot so "make it real" can be previewed/rolled back. The user
155
+ approves the generated app before cutover.
156
+
157
+ ---
158
+
159
+ ## 4. Architecture
160
+
161
+ ### 4.1 Foundations we reuse (do not rebuild)
162
+
163
+ - **Source modes & bridge** — `source-mode.ts` defines `inline | localhost |
164
+ fusion` plus the `DesignBridgeRequest` op set: `select`, `resolveNodeToFile`,
165
+ `readFile`, `applyEdit`, `writeFile`, `captureSnapshot`, `captureState`.
166
+ `select` / `resolveNodeToFile` / `captureSnapshot` / `captureState` are
167
+ **`available`**; `readFile` / `applyEdit` / `writeFile` are **`planned`**
168
+ (`connect-localhost.ts` — _"Local file writes require the next bridge hardening
169
+ pass"_). The iframe postMessage bridge in `DesignCanvas.tsx` already carries
170
+ parent→iframe (`tweak-values`, `style-change`, `replace-document-content`,
171
+ `select-element`, `layer-states`, `delete-element`) and iframe→parent
172
+ (`element-select`, `visual-style-change`, `visual-structure-change`,
173
+ `text-content-change`, …). New writes add **named** messages (e.g.
174
+ `motion-preview`), never ad-hoc ones.
175
+ - **Code-layer projection** — `code-layer.ts` (+ `get-code-layer-projection.ts`)
176
+ models nodes, selectors, and `CodeLayerSourceSpan` byte offsets, mapping
177
+ elements to source via `data-agent-native-node-id` (stamped by
178
+ `ensureCodeLayerNodeIdsInHtml`; rename target `data-agent-native-layer-name`).
179
+ - **Deterministic edit path** — `apply-visual-edit.ts` + the
180
+ `replace-document-content` bridge message already do inline HTML writes
181
+ (preview + persist via the Yjs/collab path, `applyLocalContentUpdate`).
182
+ - **Tweaks (CSS-var write path)** — a `TweakDefinition` (`shared/api.ts`) carries a
183
+ `cssVar`; `resolveTweaksToCssVars` (`resolve-tweaks.ts`, byte-identical
184
+ client/server) → `{ "--var": value }`; `apply-tweaks` persists to
185
+ `designs.data.tweakSelections`; the injected `TWEAK_BRIDGE_SCRIPT` applies
186
+ `tweak-values` live via `documentElement.style.setProperty`. **This is the
187
+ Tier-A Tokens write path.**
188
+ - **Brand Kit & token parsing** — `packages/core/src/brand-kit/types.ts`
189
+ (`BrandKitData`) is the shared shape; `DesignSystemData` extends it.
190
+ `design-token-utils.ts` parses CSS vars (`extractCssVars`), Tailwind
191
+ (`parseTailwindConfig`), CSS/SCSS (`parseCss`), JSON/theme files, HTML URLs,
192
+ GitHub (≤10 files), uploads — **import/read-only today** (no write-back).
193
+ `import-code.ts` is the import entry. `design_systems` rows store a `data` JSON
194
+ blob; the current UI edits metadata + shows a read-only token preview.
195
+ - **Versions** — `design_versions` exists; reused for diff + migration snapshots.
196
+ - **Canvas frames** — `canvas-frames.ts` + `MultiScreenCanvas.tsx` for overview
197
+ geometry; reused by states/responsive.
198
+ - **Extensions** — the sandboxed Alpine mini-app substrate +
199
+ `DesignExtensionsPanel.tsx` inspector slot; shaders/plugins are extensions.
200
+ - **Builder & app-creation** — `connect-builder` card, `runBuilderAgent()`,
201
+ `startWorkspaceAppCreation()`, `create_workspace_app` (scaffold), `build.ts`
202
+ (deploy) all exist; the real-app tier wires these, it does not invent them.
203
+
204
+ ### 4.2 Design Surface Index — a lazy read-model, not an up-front cache
205
+
206
+ Normalize what already exists (nodes, components, tokens, motion, states, review,
207
+ extension contributions) into **one queryable surface** that both UI panels and
208
+ agent actions read. **Grow it lazily from the existing `code-layer.ts` projection
209
+ and per-feature needs; do not build a normalized cache table up front.** Add a
210
+ cache (`design_surface_indexes`) only if/when re-parsing proves to be a real
211
+ performance problem, with incremental rebuilds keyed by file/source hash and an
212
+ initial scope limited to the active route/screen. Shared types live under
213
+ `templates/design/shared/`: `design-surface-index.ts`,
214
+ `design-source-capabilities.ts`, `motion-timeline.ts`, `design-state.ts`,
215
+ `design-review.ts`.
216
+
217
+ ### 4.3 New durable data (additive only)
218
+
219
+ Additive — never drop/rename/retype. All tables use `ownableColumns()` and are
220
+ read/written through `accessFilter` / `assertAccess`.
221
+
222
+ ```
223
+ component_index # real-app component metadata
224
+ id (pk); design_id -> designs.id; source_ref
225
+ name; file_path; export_name
226
+ props jsonb # parsed prop types / cva variants
227
+ variants jsonb; stories jsonb
228
+ runtime_selectors jsonb; created_at; updated_at
229
+
230
+ motion_timeline # scoped to design + source + screen/file (MANY per design)
231
+ id (pk); design_id -> designs.id; source_ref
232
+ file_path # null for inline (lives in the managed <style> block)
233
+ tracks jsonb # [{ target_node_id, property, keyframes:[{t,value,ease}] }]
234
+ # -- multiple target layers, each with property tracks
235
+ duration_ms; default_ease
236
+ compiled_hash # keep timeline JSON and compiled CSS in lockstep
237
+ created_at; updated_at
238
+
239
+ design_state # states, fixtures, captures
240
+ id (pk); design_id -> designs.id; source_ref
241
+ name; kind # 'state' | 'fixture' | 'capture'
242
+ breakpoint # 'auto' | 'desktop' | 'tablet' | 'mobile'
243
+ route; fixture_data jsonb; capture_data jsonb; preview_ref
244
+ created_at; updated_at
245
+
246
+ design_review_snapshot # cache a11y + visual-diff results (add when needed)
247
+ id (pk); design_id -> designs.id
248
+ base_version_id; compare_version_id; source_ref
249
+ a11y_findings jsonb; visual_diff jsonb; status
250
+ created_at; updated_at
251
+ ```
252
+
253
+ `designs.source_type` already exists; migration flips `inline` → `fusion`.
254
+ `design_versions` is reused for diff + snapshots.
255
+
256
+ ---
257
+
258
+ ## 5. Source capabilities (the contract)
259
+
260
+ Every source advertises what it can safely do; the UI gates on this, never on
261
+ `sourceType`.
262
+
263
+ ```
264
+ readFile writeFile applyEdit resolveNodeToFile previewPatch diffPatch
265
+ captureSnapshot captureState indexComponents indexTokens writeTokens
266
+ previewMotion writeMotion branch deployPreview deploy
267
+ ```
268
+
269
+ Behavior:
270
+
271
+ - **Inline / design-file** — HTML/CSS preview + controlled writes through the
272
+ existing deterministic path (`replace-document-content` / `apply-tweaks`);
273
+ `previewMotion` + Tier-A `writeMotion` (managed `<style>` block) and CSS-var
274
+ token edits are available without the file-write bridge.
275
+ - **localhost** — starts read-only/preview-only; `readFile` / `applyEdit` /
276
+ `writeFile` become available only after bridge hardening.
277
+ - **fusion (Builder)** — starts preview-only; unlocks the full set
278
+ (`indexComponents`, `writeTokens`, `writeMotion`, `branch`, `deploy`) once the
279
+ bridge proves capabilities.
280
+ - A control reads the matrix and renders **enabled**, **preview-only**, or
281
+ **migration CTA**. The agent reads the same matrix and never claims an
282
+ unsupported write.
283
+
284
+ ---
285
+
286
+ ## 6. Feature workstreams
287
+
288
+ Each workstream touches the four required areas — **UI, actions,
289
+ skills/instructions, application state** — and names its Alpine vs. real-app
290
+ behavior. UI binds through `useActionQuery` / `useActionMutation`; never raw fetch.
291
+
292
+ ### 6.1 Editor workbench & components
293
+
294
+ **UI (matches the workbench artboard):** quiet top toolbar (title, segmented
295
+ `Edit / Interact / Annotate`, device dropdown, zoom dropdown, avatar, Share); left
296
+ rail (search → Screens → Layers, component rows marked with an accent diamond,
297
+ selected instance in a soft accent row); canvas (central frame, selected-instance
298
+ accent outline, a source-aware tag like `PrimaryButton →`, a small bottom local
299
+ toolbar, a compact Motion disclosure); right inspector keeps `Design / Tweaks /
300
+ Extensions` compact, with component details shown **contextually inside Design**
301
+ (no permanent Components tab unless real usage proves the need).
302
+
303
+ **Alpine:** annotate a DOM subtree with `data-agent-native-component="Name"` (or an
304
+ `Alpine.data()` island); code-layer marks instances; canvas outlines them; the
305
+ Design tab shows the simple `x-data` variants. **Deliberately light — a bridge to
306
+ real apps, not a fake component system.**
307
+
308
+ **Real app:** `index-components` runs a build-time index (TS prop types, `cva` /
309
+ `tailwind-variants`, Storybook stories) and injects dev metadata
310
+ (`data-agent-native-component`, `data-agent-native-prop-*`, source span) via a
311
+ Vite/Babel transform; canvas outlines real instances; jump-to-source reuses the
312
+ bridge `resolveNodeToFile` op keyed off `data-agent-native-node-id`; the inspector
313
+ renders prop controls from the prop types; detach/instance edits write through the
314
+ bridge. Indexing modes: static AST parse on connect first, dev transform later for
315
+ runtime-variant fidelity; config/annotation escape hatches (`agent-native.design.ts`).
316
+
317
+ **Acceptance:** selecting a component instance outlines it in the accent color; in
318
+ a real app the inspector shows name, source file, variant/size/state controls,
319
+ token usage, and an **Edit component** action; in Alpine the user gets lightweight
320
+ region hints + the real-app CTA; the agent sees selected-component context via
321
+ `view-screen`.
322
+
323
+ ### 6.2 Tokens / design systems
324
+
325
+ **UI (matches the tokens artboard):** friendly token names + swatches, CSS-var
326
+ name on the right, type-scale section, radius input, a source chip (e.g.
327
+ `globals.css`), a **New token** action; grouped by color / type / spacing-radius /
328
+ shadows-effects.
329
+
330
+ **Alpine:** the panel is a first-class face on the **Tweaks** loop — edits go
331
+ through `apply-tweaks` (live `tweak-values` preview, persisted in
332
+ `designs.data.tweakSelections`).
333
+
334
+ **Real app:** additionally auto-parses `globals.css` / `tailwind.config` / theme
335
+ JSON (`design-token-utils.ts`) and **writes back to source** via `apply-design-token-edit`
336
+ through the hardened write bridge; tokens become tokens-as-code; the Brand Kit is
337
+ the shared shape across Design / Slides / Assets.
338
+
339
+ **Acceptance:** editing a token previews immediately; writing patches the source
340
+ only through a capability-gated action.
341
+
342
+ ### 6.3 Motion dock (CSS-first; the headline)
343
+
344
+ **Both tiers.** A `MotionTimeline` compiles into a managed `<style
345
+ data-agent-native-motion>` block targeting layers by `data-agent-native-node-id`.
346
+ The CSS is the runtime truth; the JSON `tracks` only aid editing.
347
+
348
+ - **UI (matches the motion artboard):** a full-width, collapsible **Motion dock**
349
+ at the bottom of `DesignEditor.tsx` (animated layer rows, property tracks, time
350
+ ruler, diamond keyframes, play/scrub, auto-keyframe toggle, **Write to CSS**),
351
+ with the canvas still visible above; a compact **Motion section** in the
352
+ inspector for the selected keyframe (numeric + easing + transform/opacity).
353
+ - **Preview:** scrubbing sends preview-only bridge messages (`motion-preview` /
354
+ playhead); it **never** writes to DB / Yjs / source.
355
+ - **Apply (atomic, non-negotiable):** `apply-motion-edit` updates timeline
356
+ metadata, compiled CSS, Yjs/collab state, revision check, diff + rollback proof,
357
+ and iframe refresh **together**; `compiled_hash` guards drift. Include a
358
+ reduced-motion strategy in both preview and output.
359
+
360
+ **Real-app superset:** write keyframes into real CSS modules, optional
361
+ `motion`-react round-trip, Dev Mode export.
362
+
363
+ **Acceptance:** scrubbing never writes; **Write to CSS** is one atomic action with
364
+ diff/rollback proof; multiple layers and tracks animate.
365
+
366
+ ### 6.4 States, responsive & captures
367
+
368
+ #### Responsive — multi-breakpoint editing (Framer / Figma-Sites style)
369
+
370
+ Show one screen at several breakpoints **side by side** in the overview and edit
371
+ each independently. Researched models we borrow from:
372
+
373
+ - **Framer** — Desktop (the parent) + Tablet **810** + Phone **390** as
374
+ side-by-side frames; added via a **Breakpoint button** on the page selection
375
+ (infinite, resizable). Desktop-first: a frame drawn on Desktop propagates down to
376
+ smaller breakpoints; a smaller-breakpoint edit overrides only that frame.
377
+ - **Figma Sites** — Desktop **1280** / Tablet **800** / Mobile **375**; a **`+` in
378
+ the webpage header on the canvas** adds a predefined or custom width; primary →
379
+ secondary cascade (default primary = Desktop ⇒ desktop-first); **"Set as primary
380
+ breakpoint"** flips to mobile-first; per-property, per-breakpoint overrides;
381
+ **"Reset all changes"** reverts a layer to the inherited (primary) value;
382
+ responsive components auto-match variants by breakpoint name.
383
+
384
+ **Our model — mobile-first by default, because the output is Tailwind.** Unlike
385
+ Framer/Figma (desktop-first), we make the **base = mobile** and let larger
386
+ breakpoints layer overrides upward — which is exactly Tailwind's min-width cascade
387
+ (`base` → `md:` → `lg:`). This matches the requested preference and makes "edit on
388
+ screen → responsive class" deterministic.
389
+
390
+ - **Overview:** a screen carries a **breakpoint set**; `MultiScreenCanvas` renders
391
+ one iframe **per breakpoint at its width**, laid left→right (Mobile → Tablet →
392
+ Desktop), all bound to the **same source** (same `srcdoc` for inline, same URL for
393
+ localhost/fusion). A **`+` at the right edge** adds the next device size
394
+ (Mobile 390 / Tablet 768 / Desktop 1280, or a custom width). Store the set by
395
+ extending `canvas-frames.ts` geometry to a per-breakpoint frame list (not a fixed
396
+ single geometry per file). Frames **snap to Tailwind breakpoint min-widths**
397
+ (`md` 768, `lg` 1024, `xl` 1280) so each frame maps 1:1 to a prefix.
398
+ - **Per-breakpoint editing = the active frame is the edit scope.** Editing a layer in
399
+ the **Mobile** frame writes the **unprefixed** class (the base); the same edit in
400
+ **Tablet** writes `md:…`; in **Desktop** writes `lg:`/`xl:…`. Inherited values
401
+ cascade up from base unless a prefixed override exists. For non-Tailwind / inline
402
+ CSS, the edit writes into a `@media (min-width: …)` block in the managed style.
403
+ - **This is the main new code-layer work.** Today the projection **detects but
404
+ strips** Tailwind `sm:`/`md:`/`lg:` prefixes and all class edits are global
405
+ (`code-layer.ts`; `EditCapability` has no responsive kind). Add a
406
+ **responsive-aware class model**: parse class tokens grouped by breakpoint
407
+ (base, `sm:`, `md:`, `lg:`, `xl:`, `2xl:`), expose each property's value _per
408
+ breakpoint_, and add an `EditCapability` of `kind: "responsive-class"` whose
409
+ add/replace targets the active breakpoint's prefix. Surface **override indicators**
410
+ (which properties differ from base at this breakpoint) with a **Reset to base**
411
+ affordance (cf. Figma's "Reset all changes").
412
+ - **Tiering:** the multi-frame overview + base/Tailwind-prefix editing works in
413
+ **Alpine today** — inline designs already load Tailwind CDN + use `sm:/md:/lg:`,
414
+ the device frame already sets the iframe width, and class edits already flow
415
+ through the deterministic `replace-document-content` path (no bridge write). For
416
+ **real apps**, the same per-breakpoint edit writes prefixed classes / media rules
417
+ to the real source (needs the bridge write hardening, phase 5).
418
+
419
+ #### States
420
+
421
+ Design states (Default / Logged out / Empty / Loading / Error and pseudo-states) as
422
+ alternate `x-data` / DOM snapshots in `design_state`. Breakpoint and state are
423
+ **orthogonal axes** — any state can be viewed at any breakpoint.
424
+
425
+ #### Captures (real app)
426
+
427
+ `capture-design-state` snaps the running app's route + props + data into a
428
+ `design_state` row (the bridge `captureState` op is **already `available`**).
429
+
430
+ Selected **breakpoint + state** persist in application state (`breakpoint` already
431
+ in the §8 shape; add `breakpointSetId` / `activeBreakpointId`) and are agent-visible
432
+ via `view-screen`. New actions (§7): `add-breakpoint`, `remove-breakpoint`,
433
+ `set-active-breakpoint`, `reset-breakpoint-overrides`.
434
+
435
+ #### `visual-edit` skill upgrade
436
+
437
+ Today `/visual-edit` opens one URL at one size. Upgrade a screen from a single
438
+ URL+size to a **route × breakpoint matrix** — the same URL (or inline design)
439
+ rendered at Mobile/Tablet/Desktop side by side, editing only the frame that needs
440
+ fixing. Identical mechanism for inline (Alpine) and real (React) apps: same source,
441
+ N widths. Flow states (`?step=…`) and breakpoints compose as two axes.
442
+
443
+ **Acceptance:** a screen shows Mobile/Tablet/Desktop side by side with a `+` to add a
444
+ width; editing a layer in one frame writes a breakpoint-scoped class and the other
445
+ frames reflect the cascade; overridden properties show a reset-to-base control; real
446
+ apps additionally capture running state; the agent sees the selected
447
+ breakpoint/state/route via `view-screen`.
448
+
449
+ ### 6.5 Accessibility & review (read-only first)
450
+
451
+ `run-design-audit` over the rendered DOM (contrast, tap targets, focus
452
+ visibility, missing names/labels, reduced-motion). The **Review** panel (matches
453
+ the review artboard) shows severity-dot findings with optional **Fix** + a visual
454
+ diff over `design_versions` (base/compare selector, changed-surface rows, before/
455
+ after). Findings navigate to the affected canvas/source node. Fix actions are
456
+ **capability-gated** (semantic code fixes are real-app only).
457
+
458
+ ### 6.6 Branches, Builder & deploy
459
+
460
+ **Alpine:** version diff between two `design_versions`.
461
+ **Real app:** `connect-builder-app` / `migrate-inline-design-to-app` /
462
+ `create-design-branch` (Builder-hosted branch today via `runBuilderAgent`) /
463
+ `get-design-branch-diff` / `deploy-design-preview`, with rollback. (Our own durable
464
+ container is the later `SandboxAdapter` path.)
465
+
466
+ ### 6.7 Extensions, shaders & assets
467
+
468
+ Extensions are the substrate (both tiers), inline via `DesignExtensionsPanel`.
469
+ First-party: **asset library** (selection-aware insertion — can ship early),
470
+ **shader fills**, **token auditor**, **motion presets**. **Shaders: preview-first;
471
+ `apply-shader-fill` stays disabled until runtime rendering + a real source-write
472
+ path + a generated fallback + diff proof all exist.** No permanent chrome.
473
+
474
+ ---
475
+
476
+ ## 7. Action surface
477
+
478
+ Actions are the shared UI/agent contract; every editable surface splits into a
479
+ cheap ephemeral **preview** and a deliberate atomic **apply**.
480
+
481
+ - **Foundation:** `get-design-surface-index` (read), `refresh-design-surface-index`,
482
+ `list-design-source-capabilities` (read).
483
+ - **Components:** `index-components`, `get-component-details` (read),
484
+ `preview-component-prop-edit`, `apply-component-prop-edit`, `open-component-source`.
485
+ - **Tokens:** `index-design-tokens`, `preview-design-token-edit`,
486
+ `apply-design-token-edit`, `create-design-token`.
487
+ - **Motion:** `get-motion-timeline` (read), `preview-motion-frame`,
488
+ `apply-motion-edit` (atomic), `remove-motion-timeline`.
489
+ - **States/captures:** `list-design-states` (read), `create-design-state`,
490
+ `capture-design-state`, `apply-design-state`, `delete-design-state`.
491
+ - **Responsive/breakpoints:** `add-breakpoint`, `remove-breakpoint`,
492
+ `set-active-breakpoint`, `reset-breakpoint-overrides`. Per-breakpoint style edits
493
+ reuse `preview-component-prop-edit` / `apply-visual-edit` with an `EditCapability`
494
+ of `kind: "responsive-class"` scoped to the active breakpoint's Tailwind prefix.
495
+ - **Review:** `run-design-audit`, `get-design-review` (read), `preview-a11y-fix`,
496
+ `apply-a11y-fix` (gated), `create-design-review-snapshot`.
497
+ - **Builder/branch:** `connect-builder-app`, `migrate-inline-design-to-app`,
498
+ `create-design-branch`, `get-design-branch-diff`, `deploy-design-preview`.
499
+ - **Extensions/assets/shaders:** `list-design-extensions`,
500
+ `run-design-extension-action`, `insert-design-asset`, `preview-shader-fill`,
501
+ `apply-shader-fill` _(stays disabled until contracts are real)_.
502
+
503
+ Every write action declares its `accessTarget` for the audit log and re-checks
504
+ source capabilities server-side.
505
+
506
+ ---
507
+
508
+ ## 8. Application state
509
+
510
+ Publish the exact design context so the agent sees what the user sees. `view-screen`
511
+ returns selected component/source metadata, current capabilities, selected token/
512
+ state/motion context, current panel/dock, recent audit/diff summary, and CTA
513
+ availability.
514
+
515
+ ```ts
516
+ type DesignNavigationState = {
517
+ view: "design-editor" | "design-overview" | "design-review";
518
+ designId: string;
519
+ sourceType: "inline" | "localhost" | "fusion"; // Builder is a flavor of fusion
520
+ screenId?: string;
521
+ fileId?: string;
522
+ route?: string;
523
+ mode: "edit" | "interact" | "annotate";
524
+ selectedNodeIds: string[];
525
+ selectedComponentId?: string;
526
+ selectedTokenId?: string;
527
+ selectedStateId?: string;
528
+ inspectorTab: "design" | "tweaks" | "extensions";
529
+ inspectorSection?:
530
+ | "component"
531
+ | "tokens"
532
+ | "motion"
533
+ | "states"
534
+ | "review"
535
+ | "extension";
536
+ dock?: { kind: "motion" | "review" | null; open: boolean };
537
+ motion?: {
538
+ timelineId?: string;
539
+ playheadMs: number;
540
+ selectedTrackId?: string;
541
+ selectedKeyframeId?: string;
542
+ previewing: boolean;
543
+ };
544
+ breakpoint?: "auto" | "desktop" | "tablet" | "mobile"; // active breakpoint
545
+ breakpointSetId?: string; // the screen's side-by-side breakpoint set
546
+ activeBreakpointId?: string; // which frame is the current edit scope
547
+ sourceCapabilities: string[];
548
+ };
549
+ ```
550
+
551
+ Wire writes through `navigate` / `view-screen` plus selection, motion-dock,
552
+ state, and review state writes.
553
+
554
+ ---
555
+
556
+ ## 9. Agent instructions & skills
557
+
558
+ Update `templates/design/AGENTS.md`:
559
+
560
+ - **Mode boundary** — Alpine is lightweight; full components, data states, branches,
561
+ deploys, and deep token writes are real-app features.
562
+ - **Capability gate rule** — never claim a write unless capabilities advertise it.
563
+ - **Action map** — index/read, component, token, motion, state/capture, review,
564
+ Builder/branch/deploy.
565
+ - **Motion rule** — preview-only scrubbing; atomic `apply-motion-edit` to commit.
566
+ - **Shader rule** — keep writes gated until runtime/write seams are real.
567
+ - **Visual rule** — preserve the minimal Figma-esque shell and the screenshot
568
+ acceptance criteria.
569
+
570
+ Add `.agents/skills/design-studio/SKILL.md`: how to inspect capabilities, index a
571
+ surface before editing, choose Alpine vs real-app behavior, apply token/component/
572
+ motion edits safely, use review outputs, and offer Builder migration CTAs.
573
+
574
+ ---
575
+
576
+ ## 10. Cross-cutting
577
+
578
+ - **Four areas** — every feature touches UI + actions + skills/instructions + app
579
+ state.
580
+ - **Preview vs apply** — cheap ephemeral preview (bridge message) vs deliberate,
581
+ atomic, revision-checked, diffable apply. Scrub/drag/nudge previews; commit writes.
582
+ - **Security** — Builder credentials via Vault + scoped reader (never copied into
583
+ app rows); all new tables `ownableColumns()` + access-checked; source writes only
584
+ in capability-advertising modes behind bridge auth.
585
+ - **Reliability** — writes are single atomic actions, never per-frame loops;
586
+ migration reports proof-of-done.
587
+
588
+ ---
589
+
590
+ ## 11. Rollout phases
591
+
592
+ 0. **Capability gates + CTA skeleton (thin honesty layer).** Sources advertise
593
+ capabilities; controls gate to enabled / preview-only / migration-CTA; the "Make
594
+ it real" CTA renders wherever a control is gated. No new _feature_ yet. Cheap;
595
+ unblocks everything. **Not blocked on bridge write-hardening** — inline writes
596
+ already work through `replace-document-content` / `apply-tweaks`; hardening lands
597
+ with the real-app lane (phase 5). Add screenshot visual-regression coverage of
598
+ the editor shell + panel primitives.
599
+ 1. **Tokens + CSS-keyframe Motion on inline (first user-visible win).** Tokens panel
600
+ on the Tweaks loop; Motion dock with managed-keyframes `apply-motion-edit`. Zero
601
+ new infra; proves "visual edit → code" at small scale. Ship the cheap half of
602
+ responsive here too: the **multi-breakpoint preview** — render the same inline
603
+ source at Mobile/Tablet/Desktop side by side with a `+` to add a width (the device
604
+ frame already width-controls the iframe; this is just N iframes + a button).
605
+ 2. **Components.** Light annotated Alpine components + the real-app component index +
606
+ prop controls behind the CTA.
607
+ 3. **States, responsive & captures.** Design states; the **responsive-aware
608
+ code-layer** (per-breakpoint Tailwind-prefix editing with override / reset-to-base,
609
+ the new `kind: "responsive-class"` edit capability) so editing one frame writes a
610
+ scoped class; then real-app data captures.
611
+ 4. **Accessibility + version diff (read-only Review panel).**
612
+ 5. **Connect Builder / real-app tier.** Harden bridge writes, implement `fusion`,
613
+ wire migration; unlock full components / tokens-as-code / branches / deploy.
614
+ 6. **Shaders & plugins (gated, last).** Preview-first; apply/export only after
615
+ runtime + source-write + fallback + diff proof.
616
+
617
+ **First user-visible milestone:** on an inline design, edit a token (live, persisted)
618
+ and add a keyframe animation that **Write to CSS** commits with a visible diff —
619
+ "visual edit becomes persisted code/CSS" without the whole real-app stack.
620
+
621
+ ---
622
+
623
+ ## 12. Parallel workstreams (clear ownership)
624
+
625
+ 1. Capability gates + surface index (shared types, source-mode contract, index
626
+ actions, app-state/`view-screen`).
627
+ 2. UI shell + visual primitives (chrome, compact rows, swatches, segmented
628
+ controls, severity rows, property groups, CTA rows; screenshot-matching states).
629
+ 3. Components + real-app CTA.
630
+ 4. Tokens (parser/indexer, panel, preview/apply).
631
+ 5. Motion (timeline model, compiler/parser, dock UI, preview messages, atomic apply).
632
+ 6. States/captures.
633
+ 7. Review/diff/a11y.
634
+ 8. Builder/branches/deploy.
635
+ 9. Extensions/assets/shaders.
636
+
637
+ ---
638
+
639
+ ## 13. Verification
640
+
641
+ - **Unit/action:** surface index builds for inline files; capability gates disable
642
+ unsupported writes; token parser handles CSS vars + Tailwind; motion compiler
643
+ emits deterministic CSS and the parser reads the managed block back;
644
+ `apply-motion-edit` is atomic + revision-checked; component index handles
645
+ representative React/`cva`; state/capture actions persist + are app-state-visible;
646
+ audit returns stable findings.
647
+ - **UI (screenshot-driven Playwright):** component-selected workbench, motion dock
648
+ open, tokens panel, states panel, review panel, extensions panel, the Alpine
649
+ real-app CTA.
650
+ - **Agent parity:** agent can inspect the selected component via `view-screen`,
651
+ refresh the index, preview+apply a token edit where supported, add motion
652
+ keyframes via the action path, create/select a state, run review, and navigate to
653
+ an affected surface.
654
+ - **Real-app smoke (Builder/React fixture):** select a React component → props +
655
+ variants → preview a prop edit → apply a safe source edit → parse tokens → apply a
656
+ token change → capture a route state → run review → produce a branch/visual diff.
657
+ - **Responsive smoke:** a screen renders at Mobile/Tablet/Desktop side by side; a `+`
658
+ adds a width; editing a layer in the Tablet frame writes a `md:` class while base
659
+ (Mobile) is untouched; the Desktop frame reflects the cascade; reset-to-base clears
660
+ the override; the same flow works on an inline design and a real-app URL.
661
+ - **Alpine smoke:** edit layout/styles; preview + persist a CSS-var token change;
662
+ add simple keyframes and Write to CSS; run a basic a11y scan; see the real-app CTA
663
+ for full component controls.
664
+
665
+ ---
666
+
667
+ ## 14. Risks & mitigations
668
+
669
+ - **Split motion source of truth** — CSS is truth, JSON is metadata,
670
+ `apply-motion-edit` updates both atomically, store `compiled_hash` + revision,
671
+ provide rollback/diff proof.
672
+ - **Overclaiming localhost/React writes** — strict capability matrix; read-only /
673
+ preview-only fallback; CTA when the source lacks fidelity. (`readFile` /
674
+ `applyEdit` / `writeFile` are `planned` today.)
675
+ - **Inspector sprawl** — contextual sections inside the existing inspector; one
676
+ bottom dock for motion/review; extension-contributed panels; no new top-level tab
677
+ without usage proof.
678
+ - **Building-the-framework-first** — grow the Surface Index lazily; add cache tables
679
+ only when re-parsing is a measured problem; first cheap win (Tokens) ships before
680
+ any framework phase completes.
681
+ - **Over-investing in Alpine components** — keep them annotated regions, not a fake
682
+ component system; they are a bridge to real apps.
683
+ - **Shader prematurity** — preview-first; apply disabled until runtime + fallback +
684
+ source write + diff exist.
685
+ - **Component index accuracy** — static AST + config/annotation overrides first;
686
+ Vite/Babel dev transform later; tie controls to confidence/capability metadata.
687
+ - **Performance** — cache indexes when needed; incremental rebuilds by file/source
688
+ hash; initial scope = active route/screen; show freshness in UI + actions.
689
+ - **Container assumption** — the real-app tier is a Builder-hosted branch today, not
690
+ our own container; the Docker `SandboxAdapter` is a later, optional path.
691
+
692
+ ---
693
+
694
+ ## 15. Open decisions
695
+
696
+ 1. **Component indexing transport (real apps)** — Vite/Babel dev transform injecting
697
+ `data-agent-native-*` metadata (most accurate; needs the dev server wired through
698
+ the bridge) **[recommended]** vs. static TS/AST parse on connect (no runtime hook,
699
+ misses runtime-only variants). _Mitigation: ship static first, add the transform
700
+ for fidelity._
701
+ 2. **Motion source format (real apps)** — managed CSS keyframes block **[recommended;
702
+ one mental model with Alpine]** vs. a `motion`-react representation (richer
703
+ springs, ties output to the library).
704
+ 3. **Real-app hosting** — Builder-hosted branch **[recommended for v1; exists]** vs.
705
+ our own durable container (`SandboxAdapter` Docker; not built). Affects deploy +
706
+ data residency.
707
+ 4. **Migration fidelity** — pixel-match gate vs. "good enough + agent cleanup"
708
+ before cutover. Affects how aggressive the Connect-Builder CTA can be.
709
+ 5. **Breakpoint defaults & cascade** — mobile-first base + Tailwind min-width prefixes
710
+ **[recommended; deterministic with our output]** vs. also offering a per-design
711
+ desktop-first / "set as primary breakpoint" flip like Figma Sites. Default frame
712
+ widths (390 / 768 / 1280, snapped to Tailwind `md` / `lg` / `xl`) and whether to
713
+ allow fully custom widths.
714
+
715
+ ```
716
+
717
+ ```