@1agh/maude 0.28.0 → 0.29.0

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 (361) hide show
  1. package/README.md +2 -2
  2. package/{plugins/design/dev-server → apps/studio}/ai-banner.tsx +1 -1
  3. package/{plugins/design/dev-server → apps/studio}/annotations-context-toolbar.tsx +286 -6
  4. package/{plugins/design/dev-server → apps/studio}/annotations-layer.tsx +1209 -122
  5. package/{plugins/design/dev-server → apps/studio}/api.ts +486 -32
  6. package/{plugins/design/dev-server → apps/studio}/artboard-activity-overlay.tsx +1 -1
  7. package/{plugins/design/dev-server → apps/studio}/artboard-marquee.tsx +1 -1
  8. package/apps/studio/bin/_motion-sample-playwright.mjs +129 -0
  9. package/{plugins/design/dev-server → apps/studio}/bin/canvas-edit.sh +1 -1
  10. package/{plugins/design/dev-server → apps/studio}/bin/draw-proof.sh +37 -2
  11. package/{plugins/design/dev-server → apps/studio}/bin/preflight.sh +1 -1
  12. package/apps/studio/bin/read-annotations.mjs +438 -0
  13. package/apps/studio/bin/read-annotations.sh +11 -0
  14. package/{plugins/design/dev-server → apps/studio}/bin/runtime-health.sh +1 -1
  15. package/{plugins/design/dev-server → apps/studio}/bin/scenario-report.mjs +1 -1
  16. package/{plugins/design/dev-server → apps/studio}/bin/screenshot.sh +62 -2
  17. package/apps/studio/bin/server-up.sh +234 -0
  18. package/apps/studio/bin/to-lottie-verify.html +68 -0
  19. package/apps/studio/bin/to-lottie.sh +128 -0
  20. package/{plugins/design/dev-server → apps/studio}/bin/visual-sanity.sh +19 -3
  21. package/{plugins/design/dev-server → apps/studio}/build.ts +5 -3
  22. package/{plugins/design/dev-server → apps/studio}/canvas-arrowheads.ts +1 -1
  23. package/{plugins/design/dev-server → apps/studio}/canvas-comment-mount.tsx +2 -2
  24. package/apps/studio/canvas-create.ts +104 -0
  25. package/{plugins/design/dev-server → apps/studio}/canvas-cursors.ts +47 -13
  26. package/{plugins/design/dev-server → apps/studio}/canvas-icons.tsx +60 -1
  27. package/{plugins/design/dev-server → apps/studio}/canvas-lib-inline.ts +1 -1
  28. package/{plugins/design/dev-server → apps/studio}/canvas-lib-resolver.ts +1 -1
  29. package/{plugins/design/dev-server → apps/studio}/canvas-lib.tsx +41 -33
  30. package/{plugins/design/dev-server → apps/studio}/canvas-shell.tsx +57 -42
  31. package/{plugins/design/dev-server → apps/studio}/client/app.jsx +1713 -530
  32. package/apps/studio/client/canvas-url.js +81 -0
  33. package/{plugins/design/dev-server → apps/studio}/client/comments-overlay.css +41 -27
  34. package/{plugins/design/dev-server → apps/studio}/client/index.html +2 -1
  35. package/apps/studio/client/styles/1-tokens-maude.css +296 -0
  36. package/apps/studio/client/styles/3-shell-maude.css +459 -0
  37. package/{plugins/design/dev-server → apps/studio}/client/styles/3-shell.css +129 -0
  38. package/apps/studio/client/styles/4-components-maude.css +74 -0
  39. package/{plugins/design/dev-server → apps/studio}/client/styles/4-components.css +357 -34
  40. package/apps/studio/client/styles/5-maude-overrides.css +123 -0
  41. package/{plugins/design/dev-server → apps/studio}/client/styles/_index.css +9 -0
  42. package/{plugins/design/dev-server → apps/studio}/client/styles.css +1 -1
  43. package/apps/studio/client/tour/overlay.jsx +191 -0
  44. package/apps/studio/client/tour/usage-tour.js +35 -0
  45. package/apps/studio/client/whats-new-seen.js +52 -0
  46. package/apps/studio/client/whats-new.jsx +250 -0
  47. package/{plugins/design/dev-server → apps/studio}/collab/index.ts +4 -4
  48. package/{plugins/design/dev-server → apps/studio}/collab/persistence.ts +1 -1
  49. package/{plugins/design/dev-server → apps/studio}/commands/annotation-strokes-command.ts +1 -1
  50. package/{plugins/design/dev-server → apps/studio}/commands/equal-spacing-command.ts +1 -1
  51. package/{plugins/design/dev-server → apps/studio}/commands/move-artboards-command.ts +1 -1
  52. package/{plugins/design/dev-server → apps/studio}/comments-overlay.tsx +25 -6
  53. package/{plugins/design/dev-server → apps/studio}/context-menu.tsx +2 -2
  54. package/{plugins/design/dev-server → apps/studio}/contextual-toolbar.tsx +4 -7
  55. package/{plugins/design/dev-server → apps/studio}/cursors-overlay.tsx +1 -1
  56. package/apps/studio/dist/client.bundle.js +22825 -0
  57. package/apps/studio/dist/comment-mount.js +1960 -0
  58. package/apps/studio/dist/runtime/lib0_decoding.js +1 -0
  59. package/apps/studio/dist/runtime/lib0_encoding.js +1 -0
  60. package/apps/studio/dist/runtime/motion.js +4 -0
  61. package/apps/studio/dist/runtime/motion_react.js +12 -0
  62. package/apps/studio/dist/runtime/pixi-js.js +3397 -0
  63. package/apps/studio/dist/runtime/react-dom.js +1 -0
  64. package/apps/studio/dist/runtime/react-dom_client.js +9 -0
  65. package/apps/studio/dist/runtime/react.js +1 -0
  66. package/apps/studio/dist/runtime/react_jsx-dev-runtime.js +1 -0
  67. package/apps/studio/dist/runtime/react_jsx-runtime.js +1 -0
  68. package/apps/studio/dist/runtime/y-protocols_awareness.js +1 -0
  69. package/apps/studio/dist/runtime/y-protocols_sync.js +1 -0
  70. package/apps/studio/dist/runtime/yjs.js +5 -0
  71. package/apps/studio/dist/styles.css +5695 -0
  72. package/{plugins/design/dev-server → apps/studio}/dom-selection.ts +75 -4
  73. package/apps/studio/draw/animate.ts +333 -0
  74. package/{plugins/design/dev-server → apps/studio}/draw/brush.ts +4 -4
  75. package/{plugins/design/dev-server → apps/studio}/draw/composition.ts +1 -1
  76. package/{plugins/design/dev-server → apps/studio}/draw/geometry.ts +1 -1
  77. package/{plugins/design/dev-server → apps/studio}/draw/index.ts +9 -6
  78. package/{plugins/design/dev-server → apps/studio}/draw/layout.ts +2 -2
  79. package/apps/studio/draw/morph.ts +204 -0
  80. package/{plugins/design/dev-server → apps/studio}/draw/optimize.ts +1 -1
  81. package/{plugins/design/dev-server → apps/studio}/draw/palette.ts +1 -1
  82. package/{plugins/design/dev-server → apps/studio}/draw/primitives.ts +1 -1
  83. package/apps/studio/draw/serialize-animate.ts +324 -0
  84. package/{plugins/design/dev-server → apps/studio}/draw/serialize.ts +9 -3
  85. package/apps/studio/draw/test/animate.test.ts +172 -0
  86. package/{plugins/design/dev-server → apps/studio}/draw/test/layout.test.ts +1 -1
  87. package/apps/studio/draw/test/morph.test.ts +107 -0
  88. package/apps/studio/draw/test/serialize-animate.test.ts +142 -0
  89. package/{plugins/design/dev-server → apps/studio}/draw/test/serialize.test.ts +1 -1
  90. package/{plugins/design/dev-server → apps/studio}/equal-spacing-detector.ts +1 -1
  91. package/{plugins/design/dev-server → apps/studio}/equal-spacing-handles.tsx +7 -29
  92. package/{plugins/design/dev-server → apps/studio}/examples/perf-100-artboards.tsx +1 -2
  93. package/{plugins/design/dev-server → apps/studio}/export-dialog.tsx +14 -2
  94. package/{plugins/design/dev-server → apps/studio}/exporters/index.ts +2 -2
  95. package/{plugins/design/dev-server → apps/studio}/http.ts +103 -2
  96. package/{plugins/design/dev-server → apps/studio}/input-router.tsx +8 -1
  97. package/{plugins/design/dev-server → apps/studio}/inspect.ts +20 -3
  98. package/{plugins/design/dev-server → apps/studio}/marquee-overlay.tsx +6 -3
  99. package/{plugins/design/dev-server → apps/studio}/participants-chrome.tsx +1 -1
  100. package/{plugins/design/dev-server → apps/studio}/paths.ts +15 -11
  101. package/{plugins/design/dev-server → apps/studio}/server.ts +19 -1
  102. package/{plugins/design/dev-server → apps/studio}/sync/index.ts +6 -6
  103. package/{plugins/design/dev-server → apps/studio}/sync/materialize.ts +2 -2
  104. package/{plugins/design/dev-server → apps/studio}/test/ai-activity.test.ts +1 -1
  105. package/{plugins/design/dev-server → apps/studio}/test/annotations-api.test.ts +1 -2
  106. package/{plugins/design/dev-server → apps/studio}/test/annotations-layer.test.ts +69 -6
  107. package/{plugins/design/dev-server → apps/studio}/test/annotations-roundtrip.test.ts +98 -1
  108. package/apps/studio/test/annotations-text-format.test.ts +396 -0
  109. package/apps/studio/test/asset-api.test.ts +149 -0
  110. package/{plugins/design/dev-server → apps/studio}/test/boot-self-heal.test.ts +1 -1
  111. package/apps/studio/test/canvas-create-api.test.ts +361 -0
  112. package/{plugins/design/dev-server → apps/studio}/test/canvas-cursors.test.ts +3 -1
  113. package/{plugins/design/dev-server → apps/studio}/test/canvas-edit.test.ts +1 -1
  114. package/{plugins/design/dev-server → apps/studio}/test/canvas-hmr-runtime.test.tsx +1 -1
  115. package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-inline.test.ts +1 -1
  116. package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-resolver.test.ts +2 -3
  117. package/apps/studio/test/canvas-media-drop.test.ts +158 -0
  118. package/{plugins/design/dev-server → apps/studio}/test/canvas-meta-api.test.ts +1 -2
  119. package/{plugins/design/dev-server → apps/studio}/test/canvas-origin-gate.test.ts +18 -3
  120. package/apps/studio/test/canvas-url.test.ts +99 -0
  121. package/{plugins/design/dev-server → apps/studio}/test/collab-annotations-bridge.test.ts +1 -1
  122. package/{plugins/design/dev-server → apps/studio}/test/collab-bridge.test.ts +1 -1
  123. package/{plugins/design/dev-server → apps/studio}/test/collab-room.test.ts +1 -1
  124. package/{plugins/design/dev-server → apps/studio}/test/collab-stress.test.ts +1 -1
  125. package/{plugins/design/dev-server → apps/studio}/test/comments-api.test.ts +1 -2
  126. package/{plugins/design/dev-server → apps/studio}/test/compile-entry.test.ts +1 -2
  127. package/{plugins/design/dev-server → apps/studio}/test/exporters/canva.test.ts +1 -2
  128. package/{plugins/design/dev-server → apps/studio}/test/exporters/history.test.ts +1 -2
  129. package/{plugins/design/dev-server → apps/studio}/test/exporters/pw-launch.test.ts +1 -1
  130. package/{plugins/design/dev-server → apps/studio}/test/exporters/scope.test.ts +1 -2
  131. package/{plugins/design/dev-server → apps/studio}/test/exporters/zip.test.ts +1 -2
  132. package/{plugins/design/dev-server → apps/studio}/test/git-lifecycle.test.ts +1 -2
  133. package/{plugins/design/dev-server → apps/studio}/test/handoff-static-frames.test.ts +1 -1
  134. package/{plugins/design/dev-server → apps/studio}/test/hmr-broadcast.test.ts +1 -1
  135. package/apps/studio/test/index-data-canvas-ds.test.ts +97 -0
  136. package/apps/studio/test/motion-sample.test.ts +35 -0
  137. package/{plugins/design/dev-server → apps/studio}/test/perf-harness.ts +1 -1
  138. package/{plugins/design/dev-server → apps/studio}/test/phase-3.6-smoke.test.ts +3 -1
  139. package/apps/studio/test/read-annotations.test.ts +409 -0
  140. package/{plugins/design/dev-server → apps/studio}/test/runtime-bundle.test.ts +1 -1
  141. package/{plugins/design/dev-server → apps/studio}/test/sanitize-annotation-svg.test.ts +108 -2
  142. package/{plugins/design/dev-server → apps/studio}/test/shared-doc-convergence.test.ts +2 -2
  143. package/{plugins/design/dev-server → apps/studio}/test/shared-doc-migrate.test.ts +2 -3
  144. package/{plugins/design/dev-server → apps/studio}/test/shared-doc-projection.test.ts +1 -1
  145. package/{plugins/design/dev-server → apps/studio}/test/snap-distance-pill.test.ts +1 -1
  146. package/{plugins/design/dev-server → apps/studio}/test/sync-agent.test.ts +2 -3
  147. package/{plugins/design/dev-server → apps/studio}/test/sync-atomic-write.test.ts +2 -3
  148. package/{plugins/design/dev-server → apps/studio}/test/sync-connection-state.test.ts +1 -1
  149. package/{plugins/design/dev-server → apps/studio}/test/sync-echo-guard.test.ts +1 -1
  150. package/{plugins/design/dev-server → apps/studio}/test/sync-fs-mirror.test.ts +1 -2
  151. package/{plugins/design/dev-server → apps/studio}/test/sync-hardening.test.ts +4 -5
  152. package/{plugins/design/dev-server → apps/studio}/test/sync-hubs-config.test.ts +1 -2
  153. package/{plugins/design/dev-server → apps/studio}/test/sync-runtime.test.ts +3 -8
  154. package/{plugins/design/dev-server → apps/studio}/test/sync-status.test.ts +1 -1
  155. package/{plugins/design/dev-server → apps/studio}/test/sync-untrusted.test.ts +1 -2
  156. package/apps/studio/test/tour-overlay.test.tsx +56 -0
  157. package/{plugins/design/dev-server → apps/studio}/test/use-agent-presence.test.tsx +4 -1
  158. package/{plugins/design/dev-server → apps/studio}/test/use-annotation-resize.test.ts +43 -0
  159. package/{plugins/design/dev-server → apps/studio}/test/use-snap-guides.test.ts +1 -1
  160. package/{plugins/design/dev-server → apps/studio}/test/use-tool-mode.test.tsx +4 -1
  161. package/apps/studio/test/whats-new.test.ts +101 -0
  162. package/apps/studio/text-imports.d.ts +9 -0
  163. package/{plugins/design/dev-server → apps/studio}/tool-palette.tsx +4 -69
  164. package/{plugins/design/dev-server → apps/studio}/undo-hud.tsx +1 -1
  165. package/{plugins/design/dev-server → apps/studio}/undo-stack.ts +1 -1
  166. package/{plugins/design/dev-server → apps/studio}/use-agent-presence.tsx +2 -2
  167. package/{plugins/design/dev-server → apps/studio}/use-annotation-resize.tsx +41 -12
  168. package/{plugins/design/dev-server → apps/studio}/use-annotation-selection.tsx +3 -7
  169. package/{plugins/design/dev-server → apps/studio}/use-annotations-visibility.tsx +2 -2
  170. package/{plugins/design/dev-server → apps/studio}/use-artboard-drag.tsx +2 -2
  171. package/{plugins/design/dev-server → apps/studio}/use-canvas-activity.tsx +2 -2
  172. package/apps/studio/use-canvas-media-drop.tsx +343 -0
  173. package/{plugins/design/dev-server → apps/studio}/use-collab.tsx +4 -5
  174. package/{plugins/design/dev-server → apps/studio}/use-cursor-modifiers.tsx +1 -1
  175. package/{plugins/design/dev-server → apps/studio}/use-keyboard-discipline.tsx +5 -2
  176. package/{plugins/design/dev-server → apps/studio}/use-selection-set.tsx +10 -2
  177. package/{plugins/design/dev-server → apps/studio}/use-snap-guides.tsx +1 -1
  178. package/{plugins/design/dev-server → apps/studio}/use-tool-mode.tsx +4 -2
  179. package/{plugins/design/dev-server → apps/studio}/use-undo-stack.tsx +5 -6
  180. package/apps/studio/whats-new.json +139 -0
  181. package/apps/studio/whats-new.schema.json +70 -0
  182. package/apps/studio/whats-new.ts +87 -0
  183. package/cli/bin/maude.mjs +10 -0
  184. package/cli/commands/design.mjs +84 -10
  185. package/cli/commands/design.test.mjs +133 -1
  186. package/cli/commands/help.mjs +8 -2
  187. package/cli/commands/hub.mjs +3 -3
  188. package/cli/commands/hub.test.mjs +1 -1
  189. package/cli/commands/scenario-report.mjs +2 -9
  190. package/cli/lib/cache.mjs +1 -1
  191. package/cli/lib/config-lint.mjs +1 -1
  192. package/cli/lib/copy-tree.mjs +1 -1
  193. package/cli/lib/design-link.mjs +1 -1
  194. package/cli/lib/flow-design-integration.test.mjs +2 -2
  195. package/cli/lib/gitignore-block.mjs +1 -0
  196. package/cli/lib/gitignore-block.test.mjs +2 -2
  197. package/cli/lib/plugin-cli-reachability.test.mjs +8 -7
  198. package/cli/lib/preflight.mjs +1 -1
  199. package/cli/lib/stack-detect.mjs +1 -1
  200. package/package.json +16 -16
  201. package/plugins/design/templates/_shell.html +3 -3
  202. package/plugins/design/templates/brief-board.tsx.template +61 -0
  203. package/plugins/design/templates/canvas.tsx.template +1 -1
  204. package/plugins/design/templates/design-system-inspiration/SUB-AGENT-PROMPTS.md +18 -3
  205. package/plugins/design/templates/design-system-inspiration/core/config.json.tpl +1 -1
  206. package/plugins/design/templates/design-system-inspiration/core/preview/_motion-readme.md.tpl +1 -1
  207. package/plugins/flow/.claude-plugin/config.schema.json +16 -0
  208. package/plugins/design/dev-server/bin/server-up.sh +0 -135
  209. package/plugins/design/dev-server/dist/client.bundle.js +0 -20692
  210. package/plugins/design/dev-server/dist/comment-mount.js +0 -1924
  211. package/plugins/design/dev-server/dist/runtime/lib0_decoding.js +0 -620
  212. package/plugins/design/dev-server/dist/runtime/lib0_encoding.js +0 -604
  213. package/plugins/design/dev-server/dist/runtime/motion.js +0 -4944
  214. package/plugins/design/dev-server/dist/runtime/motion_react.js +0 -10056
  215. package/plugins/design/dev-server/dist/runtime/pixi-js.js +0 -53104
  216. package/plugins/design/dev-server/dist/runtime/react-dom.js +0 -231
  217. package/plugins/design/dev-server/dist/runtime/react-dom_client.js +0 -10357
  218. package/plugins/design/dev-server/dist/runtime/react.js +0 -535
  219. package/plugins/design/dev-server/dist/runtime/react_jsx-dev-runtime.js +0 -60
  220. package/plugins/design/dev-server/dist/runtime/react_jsx-runtime.js +0 -85
  221. package/plugins/design/dev-server/dist/runtime/y-protocols_awareness.js +0 -376
  222. package/plugins/design/dev-server/dist/runtime/y-protocols_sync.js +0 -100
  223. package/plugins/design/dev-server/dist/runtime/yjs.js +0 -6687
  224. package/plugins/design/dev-server/dist/styles.css +0 -2710
  225. package/{plugins/design/dev-server → apps/studio}/activity.ts +0 -0
  226. package/{plugins/design/dev-server → apps/studio}/bin/_enumerate-artboards-playwright.mjs +0 -0
  227. package/{plugins/design/dev-server → apps/studio}/bin/_html-playwright.mjs +0 -0
  228. package/{plugins/design/dev-server → apps/studio}/bin/_pdf-playwright.mjs +0 -0
  229. package/{plugins/design/dev-server → apps/studio}/bin/_png-playwright.mjs +0 -0
  230. package/{plugins/design/dev-server → apps/studio}/bin/_pptx-playwright.mjs +0 -0
  231. package/{plugins/design/dev-server → apps/studio}/bin/_pw-launch.mjs +0 -0
  232. package/{plugins/design/dev-server → apps/studio}/bin/_screenshot-playwright.mjs +0 -0
  233. package/{plugins/design/dev-server → apps/studio}/bin/_svg-optimize.mjs +0 -0
  234. package/{plugins/design/dev-server → apps/studio}/bin/_svg-playwright.mjs +0 -0
  235. package/{plugins/design/dev-server → apps/studio}/bin/asset-sweep.sh +0 -0
  236. package/{plugins/design/dev-server → apps/studio}/bin/bootstrap-check.sh +0 -0
  237. package/{plugins/design/dev-server → apps/studio}/bin/check-runtime-bundles.sh +0 -0
  238. package/{plugins/design/dev-server → apps/studio}/bin/draw-build.sh +0 -0
  239. package/{plugins/design/dev-server → apps/studio}/bin/handoff.sh +0 -0
  240. package/{plugins/design/dev-server → apps/studio}/bin/prep.sh +0 -0
  241. package/{plugins/design/dev-server → apps/studio}/bin/slug.sh +0 -0
  242. package/{plugins/design/dev-server → apps/studio}/bin/smoke.sh +0 -0
  243. package/{plugins/design/dev-server → apps/studio}/bin/svg-optimize.sh +0 -0
  244. package/{plugins/design/dev-server → apps/studio}/boot-self-heal.ts +0 -0
  245. package/{plugins/design/dev-server → apps/studio}/canvas-build.ts +0 -0
  246. package/{plugins/design/dev-server → apps/studio}/canvas-edit.ts +0 -0
  247. package/{plugins/design/dev-server → apps/studio}/canvas-header.ts +0 -0
  248. package/{plugins/design/dev-server → apps/studio}/canvas-meta.schema.json +0 -0
  249. package/{plugins/design/dev-server → apps/studio}/canvas-pipeline.ts +0 -0
  250. package/{plugins/design/dev-server → apps/studio}/client/hmr.mjs +0 -0
  251. package/{plugins/design/dev-server → apps/studio}/client/iframe-lazy.mjs +0 -0
  252. package/{plugins/design/dev-server → apps/studio}/client/styles/0-reset.css +0 -0
  253. package/{plugins/design/dev-server → apps/studio}/client/styles/1-tokens.css +0 -0
  254. package/{plugins/design/dev-server → apps/studio}/client/styles/2-layout.css +0 -0
  255. package/{plugins/design/dev-server → apps/studio}/client/styles/5-utilities.css +0 -0
  256. package/{plugins/design/dev-server → apps/studio}/collab/ai-activity.ts +0 -0
  257. package/{plugins/design/dev-server → apps/studio}/collab/awareness-bridge.ts +1 -1
  258. package/{plugins/design/dev-server → apps/studio}/collab/git-lifecycle.ts +0 -0
  259. package/{plugins/design/dev-server → apps/studio}/collab/protocol.ts +0 -0
  260. package/{plugins/design/dev-server → apps/studio}/collab/registry.ts +0 -0
  261. package/{plugins/design/dev-server → apps/studio}/collab/room.ts +0 -0
  262. package/{plugins/design/dev-server → apps/studio}/config.schema.json +0 -0
  263. package/{plugins/design/dev-server → apps/studio}/context.ts +0 -0
  264. package/{plugins/design/dev-server → apps/studio}/dist/runtime/.min-sizes.json +0 -0
  265. package/{plugins/design/dev-server → apps/studio}/draw/test/brush.test.ts +0 -0
  266. package/{plugins/design/dev-server → apps/studio}/draw/test/composition.test.ts +0 -0
  267. package/{plugins/design/dev-server → apps/studio}/draw/test/geometry.test.ts +1 -1
  268. package/{plugins/design/dev-server → apps/studio}/draw/test/gradient.test.ts +0 -0
  269. package/{plugins/design/dev-server → apps/studio}/draw/test/optimize.test.ts +0 -0
  270. package/{plugins/design/dev-server → apps/studio}/draw/test/palette.test.ts +0 -0
  271. package/{plugins/design/dev-server → apps/studio}/draw/test/primitives.test.ts +1 -1
  272. package/{plugins/design/dev-server → apps/studio}/examples/README.md +0 -0
  273. package/{plugins/design/dev-server → apps/studio}/exporters/_browser-bundles.ts +0 -0
  274. package/{plugins/design/dev-server → apps/studio}/exporters/canva-handoff-prompt.ts +0 -0
  275. package/{plugins/design/dev-server → apps/studio}/exporters/canva.ts +0 -0
  276. package/{plugins/design/dev-server → apps/studio}/exporters/html.ts +1 -1
  277. package/{plugins/design/dev-server → apps/studio}/exporters/pdf.ts +1 -1
  278. package/{plugins/design/dev-server → apps/studio}/exporters/png.ts +1 -1
  279. package/{plugins/design/dev-server → apps/studio}/exporters/pptx.ts +1 -1
  280. package/{plugins/design/dev-server → apps/studio}/exporters/scope.ts +0 -0
  281. package/{plugins/design/dev-server → apps/studio}/exporters/svg.ts +1 -1
  282. package/{plugins/design/dev-server → apps/studio}/exporters/zip.ts +0 -0
  283. package/{plugins/design/dev-server → apps/studio}/fs-watch.ts +0 -0
  284. package/{plugins/design/dev-server → apps/studio}/handoff.ts +0 -0
  285. package/{plugins/design/dev-server → apps/studio}/history.ts +0 -0
  286. package/{plugins/design/dev-server → apps/studio}/hmr-broadcast.ts +0 -0
  287. package/{plugins/design/dev-server → apps/studio}/locator.ts +0 -0
  288. package/{plugins/design/dev-server → apps/studio}/mem.ts +0 -0
  289. package/{plugins/design/dev-server → apps/studio}/runtime-bundle.ts +0 -0
  290. package/{plugins/design/dev-server → apps/studio}/server.mjs +0 -0
  291. package/{plugins/design/dev-server → apps/studio}/sync/agent.ts +1 -1
  292. package/{plugins/design/dev-server → apps/studio}/sync/atomic-write.ts +0 -0
  293. package/{plugins/design/dev-server → apps/studio}/sync/codec.ts +0 -0
  294. package/{plugins/design/dev-server → apps/studio}/sync/connection-state.ts +0 -0
  295. package/{plugins/design/dev-server → apps/studio}/sync/echo-guard.ts +0 -0
  296. package/{plugins/design/dev-server → apps/studio}/sync/fs-mirror.ts +0 -0
  297. package/{plugins/design/dev-server → apps/studio}/sync/hubs-config.ts +0 -0
  298. package/{plugins/design/dev-server → apps/studio}/sync/migrate-seed.ts +1 -1
  299. package/{plugins/design/dev-server → apps/studio}/sync/origins.ts +0 -0
  300. package/{plugins/design/dev-server → apps/studio}/sync/projection.ts +3 -3
  301. package/{plugins/design/dev-server → apps/studio}/sync/status.ts +0 -0
  302. package/{plugins/design/dev-server → apps/studio}/sync/untrusted.ts +0 -0
  303. package/{plugins/design/dev-server → apps/studio}/test/_helpers.ts +0 -0
  304. package/{plugins/design/dev-server → apps/studio}/test/active-state.test.ts +0 -0
  305. package/{plugins/design/dev-server → apps/studio}/test/activity.test.ts +0 -0
  306. package/{plugins/design/dev-server → apps/studio}/test/annotation-strokes-command.test.ts +0 -0
  307. package/{plugins/design/dev-server → apps/studio}/test/annotations-draw-modifiers.test.ts +2 -2
  308. package/{plugins/design/dev-server → apps/studio}/test/artboard-activity-overlay.test.tsx +0 -0
  309. package/{plugins/design/dev-server → apps/studio}/test/binary-smoke.test.ts +0 -0
  310. package/{plugins/design/dev-server → apps/studio}/test/bundle-smoke.test.ts +0 -0
  311. package/{plugins/design/dev-server → apps/studio}/test/canvas-build.test.ts +0 -0
  312. package/{plugins/design/dev-server → apps/studio}/test/canvas-header.test.ts +1 -1
  313. package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-motion.test.ts +0 -0
  314. package/{plugins/design/dev-server → apps/studio}/test/canvas-pipeline.test.ts +0 -0
  315. package/{plugins/design/dev-server → apps/studio}/test/canvas-route.test.ts +0 -0
  316. package/{plugins/design/dev-server → apps/studio}/test/collab-awareness-bridge.test.ts +0 -0
  317. package/{plugins/design/dev-server → apps/studio}/test/collab-loopback.test.ts +0 -0
  318. package/{plugins/design/dev-server → apps/studio}/test/collab-protocol.test.ts +2 -2
  319. package/{plugins/design/dev-server → apps/studio}/test/collab-reseed-guard.test.ts +0 -0
  320. package/{plugins/design/dev-server → apps/studio}/test/comment-mount.test.ts +0 -0
  321. package/{plugins/design/dev-server → apps/studio}/test/context-resolve-tokens.test.ts +0 -0
  322. package/{plugins/design/dev-server → apps/studio}/test/csp-canvas-shell.test.ts +0 -0
  323. package/{plugins/design/dev-server → apps/studio}/test/equal-spacing-detector.test.ts +0 -0
  324. package/{plugins/design/dev-server → apps/studio}/test/exporters/endpoint.test.ts +0 -0
  325. package/{plugins/design/dev-server → apps/studio}/test/exporters/html.test.ts +0 -0
  326. package/{plugins/design/dev-server → apps/studio}/test/exporters/pdf.test.ts +0 -0
  327. package/{plugins/design/dev-server → apps/studio}/test/exporters/png.test.ts +0 -0
  328. package/{plugins/design/dev-server → apps/studio}/test/exporters/pptx-deck.test.ts +0 -0
  329. package/{plugins/design/dev-server → apps/studio}/test/exporters/pptx.test.ts +0 -0
  330. package/{plugins/design/dev-server → apps/studio}/test/exporters/svg.test.ts +0 -0
  331. package/{plugins/design/dev-server → apps/studio}/test/fixtures/phase-20-annotations.svg +0 -0
  332. package/{plugins/design/dev-server → apps/studio}/test/fixtures/phase-21-annotations.svg +0 -0
  333. package/{plugins/design/dev-server → apps/studio}/test/fs-watch.test.ts +0 -0
  334. package/{plugins/design/dev-server → apps/studio}/test/handoff.test.ts +1 -1
  335. package/{plugins/design/dev-server → apps/studio}/test/history-rollback.test.ts +0 -0
  336. package/{plugins/design/dev-server → apps/studio}/test/hmr-classify.test.ts +0 -0
  337. package/{plugins/design/dev-server → apps/studio}/test/input-router.test.ts +2 -2
  338. package/{plugins/design/dev-server → apps/studio}/test/locator.test.ts +1 -1
  339. package/{plugins/design/dev-server → apps/studio}/test/marquee-overlay.test.ts +0 -0
  340. package/{plugins/design/dev-server → apps/studio}/test/move-artboards-command.test.ts +0 -0
  341. package/{plugins/design/dev-server → apps/studio}/test/participants-chrome.test.ts +0 -0
  342. package/{plugins/design/dev-server → apps/studio}/test/paths.test.ts +0 -0
  343. package/{plugins/design/dev-server → apps/studio}/test/runtime-bundle-error-mapping.test.ts +0 -0
  344. package/{plugins/design/dev-server → apps/studio}/test/server-lifecycle.test.ts +0 -0
  345. package/{plugins/design/dev-server → apps/studio}/test/shared-doc-foundation.test.ts +0 -0
  346. package/{plugins/design/dev-server → apps/studio}/test/sync-codec.test.ts +1 -1
  347. package/{plugins/design/dev-server → apps/studio}/test/sync-meta-codec.test.ts +1 -1
  348. package/{plugins/design/dev-server → apps/studio}/test/system-endpoint.test.ts +0 -0
  349. package/{plugins/design/dev-server → apps/studio}/test/tool-palette.test.tsx +0 -0
  350. package/{plugins/design/dev-server → apps/studio}/test/undo-stack.test.ts +2 -2
  351. package/{plugins/design/dev-server → apps/studio}/test/use-annotation-selection.test.tsx +0 -0
  352. package/{plugins/design/dev-server → apps/studio}/test/use-artboard-drag.test.ts +3 -3
  353. package/{plugins/design/dev-server → apps/studio}/test/use-canvas-activity.test.tsx +2 -2
  354. package/{plugins/design/dev-server → apps/studio}/test/use-collab.test.ts +0 -0
  355. package/{plugins/design/dev-server → apps/studio}/test/use-cursor-modifiers.test.ts +0 -0
  356. package/{plugins/design/dev-server → apps/studio}/test/use-keyboard-discipline.test.ts +0 -0
  357. package/{plugins/design/dev-server → apps/studio}/test/use-selection-set.test.tsx +1 -1
  358. package/{plugins/design/dev-server → apps/studio}/test/use-undo-stack.test.tsx +2 -2
  359. /package/{plugins/design/dev-server → apps/studio}/test/ws-handshake.test.ts +0 -0
  360. /package/{plugins/design/dev-server → apps/studio}/tsconfig.json +0 -0
  361. /package/{plugins/design/dev-server → apps/studio}/ws.ts +0 -0
@@ -21,7 +21,7 @@
21
21
  //
22
22
  // Output: <run-dir>/report.md (or --out), zero external dependencies (node:fs only).
23
23
 
24
- import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
24
+ import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
25
25
  import { basename, join } from 'node:path';
26
26
 
27
27
  const PLATFORM_ORDER = ['web-desktop', 'web-mobile', 'ios-phone', 'ios-tablet', 'android-phone'];
@@ -213,6 +213,55 @@ capture() {
213
213
  fi
214
214
  }
215
215
 
216
+ # ---------- port-bounce recovery (P2.1 / DDR-094) ----------
217
+ # The dev server can respawn on a DIFFERENT port (the prior port got taken, a
218
+ # Tailscale/mDNS hiccup bounced it, a stale _server.json was cleared). A capture
219
+ # launched against the OLD port then fails with ERR_CONNECTION_REFUSED. The
220
+ # running server keeps _server.json current, so on any capture failure we re-read
221
+ # the LIVE port and, if it changed, rewrite $URL and retry once.
222
+ RELIVE_REPO="${ROOT:-${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}}"
223
+ RELIVE_STATE="$RELIVE_REPO/.design/_server.json"
224
+ RELIVED=0
225
+
226
+ read_state_port() {
227
+ [ -f "$RELIVE_STATE" ] || return 1
228
+ if command -v jq >/dev/null 2>&1; then
229
+ jq -r .port "$RELIVE_STATE" 2>/dev/null
230
+ else
231
+ sed -nE 's/.*"port"[[:space:]]*:[[:space:]]*([0-9]+).*/\1/p' "$RELIVE_STATE" 2>/dev/null | head -n1
232
+ fi
233
+ }
234
+
235
+ # Re-read the live port; if it differs from the one in $URL, rewrite $URL and
236
+ # return 0 (a retry is warranted). Returns 1 when nothing changed (don't retry).
237
+ # Only fires ONCE per run (RELIVED guard) so a genuinely-down server still fails.
238
+ relive_url() {
239
+ [ "$RELIVED" -eq 0 ] || return 1
240
+ local cur new
241
+ cur=$(printf '%s' "$URL" | sed -nE 's#https?://[^:/]+:([0-9]+).*#\1#p')
242
+ new=$(read_state_port)
243
+ [ -n "$new" ] || return 1
244
+ if [ -n "$cur" ] && [ "$cur" != "$new" ]; then
245
+ URL=$(printf '%s' "$URL" | sed -E "s#(://[^:/]+:)[0-9]+#\1${new}#")
246
+ RELIVED=1
247
+ echo "→ dev-server bounced ports ($cur → $new); re-reading _server.json and retrying at $URL" >&2
248
+ return 0
249
+ fi
250
+ return 1
251
+ }
252
+
253
+ # capture(), but on failure re-read the live port and retry once if it bounced.
254
+ capture_resilient() {
255
+ local css="$1"
256
+ local out="$2"
257
+ capture "$css" "$out" && return 0
258
+ if relive_url; then
259
+ navigate_once
260
+ capture "$css" "$out" && return 0
261
+ fi
262
+ return 1
263
+ }
264
+
216
265
  # ---------- --all-screens loop ----------
217
266
  if [ $ALL_SCREENS -eq 1 ]; then
218
267
  mkdir -p "$OUT_DIR"
@@ -227,6 +276,17 @@ if [ $ALL_SCREENS -eq 1 ]; then
227
276
  # Strip surrounding quotes, then split on comma.
228
277
  IDS=$(printf '%s' "$raw" | sed 's/^"//; s/"$//' | tr ',' '\n')
229
278
  fi
279
+ # No screens enumerated may mean the page never loaded (port bounce) — try a
280
+ # live-port re-read + one re-navigate before giving up.
281
+ if [ -z "$IDS" ] && relive_url; then
282
+ navigate_once
283
+ if [ "$ENGINE" = "agent-browser" ]; then
284
+ raw=$(agent-browser eval \
285
+ "Array.from(document.querySelectorAll('[data-dc-screen],[data-dc-slot]')).map(e => e.getAttribute('data-dc-screen') || e.getAttribute('data-dc-slot')).filter(Boolean).join(',')" \
286
+ 2>/dev/null)
287
+ IDS=$(printf '%s' "$raw" | sed 's/^"//; s/"$//' | tr ',' '\n')
288
+ fi
289
+ fi
230
290
  if [ -z "$IDS" ]; then
231
291
  echo "✗ no [data-dc-screen]/[data-dc-slot] elements found (or eval unavailable on this engine)" >&2
232
292
  exit 3
@@ -241,7 +301,7 @@ if [ $ALL_SCREENS -eq 1 ]; then
241
301
  agent-browser eval "document.querySelector('[data-dc-screen=\"$ID\"], [data-dc-slot=\"$ID\"]').scrollIntoView({block:'center'})" >/dev/null 2>&1
242
302
  sleep 0.6
243
303
  fi
244
- if capture "[data-dc-screen=\"$ID\"], [data-dc-slot=\"$ID\"]" "$OUT_FILE"; then
304
+ if capture_resilient "[data-dc-screen=\"$ID\"], [data-dc-slot=\"$ID\"]" "$OUT_FILE"; then
245
305
  echo "$OUT_FILE"
246
306
  else
247
307
  echo "✗ failed: $ID" >&2
@@ -254,7 +314,7 @@ fi
254
314
 
255
315
  # ---------- single-shot ----------
256
316
  navigate_once
257
- if capture "$CSS_SEL" "$OUT"; then
317
+ if capture_resilient "$CSS_SEL" "$OUT"; then
258
318
  echo "$OUT"
259
319
  exit 0
260
320
  fi
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env bash
2
+ # server-up.sh — ensure the design dev server is running for the given repo.
3
+ # Canonical recipe (was inline in `edit.md` step 2, `new.md` step 2, etc.).
4
+ #
5
+ # Usage:
6
+ # server-up.sh [--root <repo>] [--timeout 10] [--allow-legacy]
7
+ #
8
+ # Reads / writes:
9
+ # $DESIGN_ROOT/_server.json (PID + port the running server wrote)
10
+ # $DESIGN_ROOT/_server.log (stdout/stderr of the spawned server)
11
+ #
12
+ # Runtime selection (DDR-020 / DDR-009 / DDR-084), in priority order:
13
+ # - --allow-legacy: opt-in node + server.mjs (debug only; no TSX pipeline, no HMR).
14
+ # - compiled platform binary: the PRODUCTION runtime — embeds yjs + every dep, so
15
+ # it boots on a global @1agh/maude install where `bun server.ts` from source
16
+ # cannot. Path comes from MAUDE_DEV_SERVER_BIN (set by `maude design <verb>`) or
17
+ # the postinstall side-channel <pkgRoot>/cli/.platform-binary-path.
18
+ # - bun + server.ts: dev tree / fallback. MAUDE_FORCE_SOURCE=1 forces this.
19
+ #
20
+ # Output: prints the port on stdout. Diagnostic lines go to stderr.
21
+ # Exit: 0 = server ready / 1 = start timeout or missing runtime / 2 = bad args /
22
+ # 3 = dev-server runtime deps missing (yjs/y-protocols/lib0 — see preflight).
23
+
24
+ REPO=""
25
+ TIMEOUT=10
26
+ ALLOW_LEGACY=0
27
+ while [ $# -gt 0 ]; do
28
+ case "$1" in
29
+ --root) REPO="$2"; shift 2 ;;
30
+ --timeout) TIMEOUT="$2"; shift 2 ;;
31
+ --allow-legacy) ALLOW_LEGACY=1; shift ;;
32
+ --help|-h)
33
+ sed -n '2,21p' "$0" | sed 's/^# \?//'
34
+ exit 0
35
+ ;;
36
+ *)
37
+ echo "server-up.sh: unknown arg '$1' (try --help)" >&2
38
+ exit 2
39
+ ;;
40
+ esac
41
+ done
42
+
43
+ # Resolve repo root.
44
+ if [ -z "$REPO" ]; then
45
+ REPO="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
46
+ fi
47
+
48
+ # Resolve plugin root + pick a server runtime.
49
+ # --allow-legacy → node + server.mjs (debug-only — no TSX pipeline, no HMR).
50
+ # compiled platform binary → the PRODUCTION runtime (DDR-009/DDR-084). It embeds
51
+ # yjs + every dev-server dep, so it boots on a global `@1agh/maude` install
52
+ # where `bun server.ts` from source CANNOT (the deps live in a nested
53
+ # package.json the npm tarball excludes — the historic yjs-at-boot crash).
54
+ # `maude design <verb>` resolves it and passes MAUDE_DEV_SERVER_BIN; a direct
55
+ # `bash server-up.sh` falls back to the postinstall side-channel.
56
+ # bun + server.ts → dev tree / fallback (DDR-020 made bun authoritative for source).
57
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
58
+ # PLUGIN_ROOT is a 2-levels-under-pkgRoot anchor: plugins/design when `maude
59
+ # design <verb>` sets CLAUDE_PLUGIN_ROOT, else apps/studio ($SCRIPT_DIR/.. — the
60
+ # studio root, also 2-deep) for a direct `bash server-up.sh`. Both keep
61
+ # `$PLUGIN_ROOT/../../cli` = <pkgRoot>/cli. The dev-server tree itself is always
62
+ # $SCRIPT_DIR/.. (apps/studio) — DDR-095 moved it out of plugins/design.
63
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$SCRIPT_DIR/.." && pwd)}"
64
+ SERVER_TS="$PLUGIN_ROOT/dev-server/server.ts"
65
+ SERVER_MJS="$PLUGIN_ROOT/dev-server/server.mjs"
66
+ if [ ! -f "$SERVER_TS" ]; then SERVER_TS="$SCRIPT_DIR/../server.ts"; fi
67
+ if [ ! -f "$SERVER_MJS" ]; then SERVER_MJS="$SCRIPT_DIR/../server.mjs"; fi
68
+
69
+ # Resolve the compiled binary: env (set by `maude design <verb>`) wins; else the
70
+ # postinstall side-channel at <pkgRoot>/cli/.platform-binary-path (covers a direct
71
+ # `bash server-up.sh` on a production install). MAUDE_FORCE_SOURCE=1 forces source.
72
+ SERVER_BIN="${MAUDE_DEV_SERVER_BIN:-}"
73
+ if [ -z "$SERVER_BIN" ] && [ "${MAUDE_FORCE_SOURCE:-0}" != "1" ]; then
74
+ # PLUGIN_ROOT is 2-deep under pkgRoot (plugins/design or apps/studio), so the
75
+ # side-channel is ../../cli either way.
76
+ # `head -n1` (parity with the Node readers' `.trim()`) tolerates a trailing newline.
77
+ SC="$PLUGIN_ROOT/../../cli/.platform-binary-path"
78
+ if [ -f "$SC" ]; then
79
+ CAND="$(head -n1 "$SC" 2>/dev/null)"
80
+ [ -n "$CAND" ] && [ -x "$CAND" ] && SERVER_BIN="$CAND"
81
+ fi
82
+ fi
83
+ # Structural allowlist (DDR-084 hardening): only spawn a path that LOOKS like the
84
+ # compiled platform binary — basename `maude`/`maude.exe` inside a `maude-<slug>/`
85
+ # dir. A poisoned side-channel file or an injected MAUDE_DEV_SERVER_BIN pointing
86
+ # elsewhere is ignored (fall back to source), so the env/file can only DENY the
87
+ # binary, never redirect the spawn to an arbitrary executable. Mirrors
88
+ # isPlausiblePlatformBinary() in cli/commands/design.mjs.
89
+ if [ -n "$SERVER_BIN" ]; then
90
+ _sbase="$(basename "$SERVER_BIN")"
91
+ _sparent="$(basename "$(dirname "$SERVER_BIN")")"
92
+ case "$_sbase:$_sparent" in
93
+ maude:maude-* | maude.exe:maude-*) : ;;
94
+ *)
95
+ echo "server-up.sh: ignoring dev-server binary outside the expected maude-<slug>/ layout ($SERVER_BIN) — falling back to source" >&2
96
+ SERVER_BIN=""
97
+ ;;
98
+ esac
99
+ fi
100
+
101
+ RUNTIME=""
102
+ RUNTIME_CMD=""
103
+ if [ $ALLOW_LEGACY -eq 1 ]; then
104
+ if [ ! -f "$SERVER_MJS" ]; then
105
+ echo "server-up.sh: --allow-legacy requested but server.mjs not found at $SERVER_MJS" >&2
106
+ exit 1
107
+ fi
108
+ RUNTIME="node"
109
+ RUNTIME_CMD="node $SERVER_MJS"
110
+ echo "server-up.sh: WARNING — running legacy server.mjs (no TSX canvas pipeline, no HMR). DDR-020 sunsets this in Phase B." >&2
111
+ elif [ -n "$SERVER_BIN" ] && [ -x "$SERVER_BIN" ] && [ "${MAUDE_FORCE_SOURCE:-0}" != "1" ]; then
112
+ RUNTIME="binary"
113
+ RUNTIME_CMD="$SERVER_BIN"
114
+ echo "server-up.sh: using compiled dev-server binary ($SERVER_BIN)" >&2
115
+ elif command -v bun >/dev/null 2>&1 && [ -f "$SERVER_TS" ]; then
116
+ RUNTIME="bun"
117
+ RUNTIME_CMD="bun $SERVER_TS"
118
+ else
119
+ echo "server-up.sh: bun not on \$PATH — install via https://bun.sh/install" >&2
120
+ echo "server-up.sh: DDR-020 made bun authoritative; the node fallback is opt-in via --allow-legacy (debug only)." >&2
121
+ exit 1
122
+ fi
123
+
124
+ DESIGN_ROOT="$REPO/.design"
125
+ STATE="$DESIGN_ROOT/_server.json"
126
+
127
+ read_port() {
128
+ if command -v jq >/dev/null 2>&1; then
129
+ jq -r .port "$STATE" 2>/dev/null
130
+ else
131
+ # Best-effort grep — jq is in repo deps but be defensive.
132
+ sed -nE 's/.*"port"[[:space:]]*:[[:space:]]*([0-9]+).*/\1/p' "$STATE" 2>/dev/null | head -n1
133
+ fi
134
+ }
135
+ read_pid() {
136
+ if command -v jq >/dev/null 2>&1; then
137
+ jq -r .pid "$STATE" 2>/dev/null
138
+ else
139
+ sed -nE 's/.*"pid"[[:space:]]*:[[:space:]]*([0-9]+).*/\1/p' "$STATE" 2>/dev/null | head -n1
140
+ fi
141
+ }
142
+
143
+ # Step 1 — check existing.
144
+ NEEDS_START=1
145
+ if [ -f "$STATE" ]; then
146
+ PID=$(read_pid)
147
+ PORT=$(read_port)
148
+ if [ -n "$PID" ] && [ -n "$PORT" ] \
149
+ && kill -0 "$PID" 2>/dev/null \
150
+ && curl -fs "http://localhost:$PORT/_health" >/dev/null 2>&1; then
151
+ echo "✓ server alive pid=$PID port=$PORT" >&2
152
+ echo "$PORT"
153
+ exit 0
154
+ else
155
+ echo "→ stale _server.json — clearing and respawning" >&2
156
+ rm -f "$STATE"
157
+ fi
158
+ fi
159
+
160
+ # Step 1.5 — dependency preflight (source `bun server.ts` path ONLY; runs on cold
161
+ # start). The compiled binary embeds its deps, so this is skipped when RUNTIME=binary
162
+ # — it only guards the source fallback. The dev-server's runtime deps live in a
163
+ # NESTED package.json (apps/studio/) that a global `@1agh/maude` npm
164
+ # install or a fresh `git worktree` does NOT populate; a missing `yjs` (imported at
165
+ # boot by sync/index.ts) crashes `bun server.ts` AFTER spawn → without this guard we
166
+ # poll the full ${TIMEOUT}s and report a generic "start timeout", burying the cause
167
+ # in _server.log and silently degrading the mandatory visual-sanity gate. Fail loud
168
+ # NOW with a context-correct hint. No auto-install: boot-self-heal.ts (DDR-044)
169
+ # dropped that, and the durable production fix is booting the compiled binary
170
+ # (DDR-009/DDR-084), not a boot-time install. setup-ds Round-2 / DDR-083 + DDR-084.
171
+ if [ "$RUNTIME" = "bun" ]; then
172
+ DEV_SERVER_DIR="$(cd "$(dirname "$SERVER_TS")" && pwd)"
173
+ _resolve_dep() {
174
+ # Mirror node/bun bare-specifier resolution: walk node_modules up to /.
175
+ # Handles both the dev-server-local install and a workspace-hoisted one.
176
+ local dep="$1" d="$DEV_SERVER_DIR"
177
+ while [ -n "$d" ] && [ "$d" != "/" ]; do
178
+ [ -e "$d/node_modules/$dep/package.json" ] && return 0
179
+ d="$(dirname "$d")"
180
+ done
181
+ return 1
182
+ }
183
+ MISSING_DEPS=""
184
+ for dep in yjs y-protocols lib0; do
185
+ _resolve_dep "$dep" || MISSING_DEPS="$MISSING_DEPS $dep"
186
+ done
187
+ if [ -n "$MISSING_DEPS" ]; then
188
+ {
189
+ echo "✗ dev-server runtime deps not installed:$MISSING_DEPS"
190
+ if [ -f "$DEV_SERVER_DIR/package.json" ]; then
191
+ # A manifest is present (local dev tree / checkout) — install resolves it.
192
+ echo " → run: (cd \"$DEV_SERVER_DIR\" && bun install) # or: pnpm install at the repo root"
193
+ else
194
+ # No manifest beside server.ts AND no compiled binary resolved → the
195
+ # '@1agh/maude' install is incomplete. The platform binary (which embeds
196
+ # these deps) is the production runtime — reinstall to get it.
197
+ echo " (no dev-server package.json here and no compiled binary resolved — the"
198
+ echo " '@1agh/maude' install is incomplete; the platform binary embeds these deps)"
199
+ echo " → reinstall: npm i -g @1agh/maude (or: npm rebuild -g @1agh/maude)"
200
+ fi
201
+ } >&2
202
+ exit 3
203
+ fi
204
+ fi
205
+
206
+ # Step 2 — spawn.
207
+ mkdir -p "$DESIGN_ROOT"
208
+ echo "→ starting dev server: $RUNTIME_CMD --root $REPO" >&2
209
+ if [ "$RUNTIME" = "binary" ]; then
210
+ nohup "$SERVER_BIN" --root "$REPO" > "$DESIGN_ROOT/_server.log" 2>&1 &
211
+ elif [ "$RUNTIME" = "bun" ]; then
212
+ nohup bun "$SERVER_TS" --root "$REPO" > "$DESIGN_ROOT/_server.log" 2>&1 &
213
+ elif [ "$RUNTIME" = "node" ]; then
214
+ nohup node "$SERVER_MJS" --root "$REPO" > "$DESIGN_ROOT/_server.log" 2>&1 &
215
+ fi
216
+ disown 2>/dev/null || true
217
+
218
+ # Step 3 — poll.
219
+ i=0
220
+ while [ $i -lt "$TIMEOUT" ]; do
221
+ sleep 1
222
+ i=$((i + 1))
223
+ if [ -f "$STATE" ]; then
224
+ PORT=$(read_port)
225
+ if [ -n "$PORT" ] && curl -fs "http://localhost:$PORT/_health" >/dev/null 2>&1; then
226
+ echo "✓ server started port=$PORT after ${i}s" >&2
227
+ echo "$PORT"
228
+ exit 0
229
+ fi
230
+ fi
231
+ done
232
+
233
+ echo "✗ server start timeout after ${TIMEOUT}s; check $DESIGN_ROOT/_server.log" >&2
234
+ exit 1
@@ -0,0 +1,68 @@
1
+ <!doctype html>
2
+ <!-- to-lottie-verify.html — self-verify harness for `maude design to-lottie --verify`.
3
+ Renders ANY Lottie JSON through the REAL lottie-web runtime (NOT cairo — cairo
4
+ can't render masks; lottie-web must — DDR-094 rule 5). Generalized from the POC
5
+ verify.html: the Lottie source + the seek frame are query params.
6
+
7
+ Serve this dir (file:// blocks fetch): python3 -m http.server 8200
8
+ Usage: to-lottie-verify.html?src=<file.json>&f=<frame> (omit ?f to autoplay)
9
+ &bg=<css color> — backdrop (default dark) · &w=&h= — stage size px -->
10
+ <html>
11
+ <head>
12
+ <meta charset="utf8" />
13
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.12.2/lottie.min.js"></script>
14
+ <style>
15
+ html,
16
+ body {
17
+ margin: 0;
18
+ }
19
+ #stage {
20
+ margin: 20px auto;
21
+ }
22
+ </style>
23
+ </head>
24
+ <body>
25
+ <div id="stage"></div>
26
+ <script>
27
+ const p = new URLSearchParams(location.search);
28
+ const src = p.get('src');
29
+ const f = p.get('f');
30
+ const bg = p.get('bg') || '#0a0a14';
31
+ const w = p.get('w') || '400';
32
+ const h = p.get('h') || '400';
33
+ document.body.style.background = bg;
34
+ const stage = document.getElementById('stage');
35
+ stage.style.width = `${w}px`;
36
+ stage.style.height = `${h}px`;
37
+
38
+ if (!src) {
39
+ document.title = 'error-no-src';
40
+ } else {
41
+ fetch(`./${src}`)
42
+ .then((r) => {
43
+ if (!r.ok) throw new Error(`fetch ${src} → ${r.status}`);
44
+ return r.json();
45
+ })
46
+ .then((data) => {
47
+ const anim = lottie.loadAnimation({
48
+ container: stage,
49
+ renderer: 'svg',
50
+ loop: true,
51
+ autoplay: f === null,
52
+ animationData: data,
53
+ });
54
+ anim.addEventListener('DOMLoaded', () => {
55
+ if (f !== null) anim.goToAndStop(parseInt(f, 10), true);
56
+ document.title = `ready${f !== null ? `-${f}` : ''}`;
57
+ });
58
+ anim.addEventListener('error', () => {
59
+ document.title = 'error-render';
60
+ });
61
+ })
62
+ .catch((e) => {
63
+ document.title = `error-${String(e.message || e).slice(0, 40)}`;
64
+ });
65
+ }
66
+ </script>
67
+ </body>
68
+ </html>
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env bash
2
+ # to-lottie.sh — emit ONE Lottie from CODE (the maude motion handoff, DDR-094).
3
+ #
4
+ # This is the production-delivery counterpart to draw-build.sh: where draw-build
5
+ # runs an agent-authored *engine* script to emit static SVG/JSX, to-lottie runs an
6
+ # agent-authored *python-lottie generator* to emit ONE `.lottie`/`.json` that
7
+ # renders 1:1 on web (lottie-web / dotlottie-react) AND mobile
8
+ # (lottie-react-native) — same renderer family, 1:1 by construction. It is an
9
+ # EMITTER from the keyframe data, NOT a converter of rendered SVG/SMIL (no reliable
10
+ # one exists — DDR-094 research). The generator encodes the 8 conversion rules; see
11
+ # `plugins/design/commands/to-lottie.md` + `_draw-motion-rules.md`.
12
+ #
13
+ # Reached via `maude design to-lottie` (DDR-062), never a raw bin path.
14
+ #
15
+ # Usage:
16
+ # to-lottie.sh --script <gen.py> --out <mark.json>
17
+ # [--verify] [--frames "0,33,66"] [--root <repo>] [--timeout 12]
18
+ #
19
+ # The generator (gen.py) builds the Lottie via python-lottie and writes it to the
20
+ # path in $MAUDE_LOTTIE_OUT (= --out). python-lottie owns format correctness
21
+ # (beziers, keyframes, gradients, masks, parenting); the agent encodes the
22
+ # conversion rules (per-segment easing incl. overshoot, arc parsing via
23
+ # parse_svg_file, layers[0]=top + reverse, masks, baked sub-loops, coord offset,
24
+ # gradient opacity stops).
25
+ #
26
+ # --verify renders frames through HEADLESS lottie-web (cairo can't render masks —
27
+ # lottie-web must) using the shipped harness + the screenshot helper, so you can
28
+ # read the PNGs and compare to the web reference.
29
+ #
30
+ # Stdout (last line): the output .json path (capturable in $(...)).
31
+ # Exit: 0 ok / 1 missing input or runtime / 2 bad args / 3 generate failed
32
+ # / 4 verify render failed.
33
+
34
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
35
+ GEN=""
36
+ OUT=""
37
+ VERIFY=0
38
+ FRAMES="0,33,66"
39
+ REPO=""
40
+ TIMEOUT=12
41
+
42
+ while [ $# -gt 0 ]; do
43
+ case "$1" in
44
+ --script) GEN="$2"; shift 2 ;;
45
+ --out) OUT="$2"; shift 2 ;;
46
+ --verify) VERIFY=1; shift ;;
47
+ --frames) FRAMES="$2"; shift 2 ;;
48
+ --root) REPO="$2"; shift 2 ;;
49
+ --timeout) TIMEOUT="$2"; shift 2 ;;
50
+ --help|-h) sed -n '2,33p' "$0" | sed 's/^# \?//'; exit 0 ;;
51
+ *) echo "to-lottie.sh: unknown arg '$1' (try --help)" >&2; exit 2 ;;
52
+ esac
53
+ done
54
+
55
+ [ -n "$GEN" ] || { echo "to-lottie.sh: --script <gen.py> required" >&2; exit 2; }
56
+ [ -n "$OUT" ] || { echo "to-lottie.sh: --out <mark.json> required" >&2; exit 2; }
57
+ [ -f "$GEN" ] || { echo "to-lottie.sh: generator not found: $GEN" >&2; exit 1; }
58
+ command -v python3 >/dev/null 2>&1 || { echo "to-lottie.sh: python3 is required." >&2; exit 1; }
59
+
60
+ # ---------- python-lottie venv (cached, idempotent) ----------
61
+ VENV="${MAUDE_LOTTIE_VENV:-${XDG_CACHE_HOME:-$HOME/.cache}/maude/lottie-venv}"
62
+ PY="$VENV/bin/python"
63
+ if [ ! -x "$PY" ]; then
64
+ echo "→ bootstrapping python-lottie venv at $VENV (one-off) …" >&2
65
+ python3 -m venv "$VENV" || { echo "to-lottie.sh: venv create failed" >&2; exit 1; }
66
+ "$VENV/bin/pip" install --quiet --disable-pip-version-check lottie cairosvg pillow \
67
+ || { echo "to-lottie.sh: pip install lottie failed (needs network on first run)" >&2; exit 1; }
68
+ fi
69
+ # Sanity: the `lottie` module must import.
70
+ "$PY" -c 'import lottie' 2>/dev/null || {
71
+ echo "→ (re)installing python-lottie into $VENV …" >&2
72
+ "$VENV/bin/pip" install --quiet --disable-pip-version-check lottie cairosvg pillow \
73
+ || { echo "to-lottie.sh: python-lottie unavailable" >&2; exit 1; }
74
+ }
75
+
76
+ # ---------- generate ----------
77
+ mkdir -p "$(dirname "$OUT")"
78
+ echo "→ generating Lottie: $GEN → $OUT" >&2
79
+ MAUDE_LOTTIE_OUT="$OUT" "$PY" "$GEN" >&2
80
+ GRC=$?
81
+ if [ "$GRC" -ne 0 ] || [ ! -s "$OUT" ]; then
82
+ echo "to-lottie.sh: generator failed (rc=$GRC) or wrote no output to $OUT" >&2
83
+ exit 3
84
+ fi
85
+ # Validity gate: the output must be parseable JSON with the Lottie shape keys.
86
+ "$PY" - "$OUT" <<'PYEOF' >&2 || { echo "to-lottie.sh: output is not a valid Lottie JSON" >&2; exit 3; }
87
+ import json, sys
88
+ d = json.load(open(sys.argv[1]))
89
+ assert isinstance(d, dict) and 'layers' in d and 'op' in d, 'missing Lottie keys (layers/op)'
90
+ print(f" ✓ valid Lottie: {len(d.get('layers', []))} layers, {d.get('op')} frames @ {d.get('fr')}fps")
91
+ PYEOF
92
+
93
+ # ---------- self-verify through headless lottie-web ----------
94
+ if [ "$VERIFY" -eq 1 ]; then
95
+ HARNESS="$SCRIPT_DIR/to-lottie-verify.html"
96
+ [ -f "$HARNESS" ] || { echo "to-lottie.sh: verify harness missing at $HARNESS — reinstall maude." >&2; exit 1; }
97
+ OUT_DIR_ABS="$(cd "$(dirname "$OUT")" && pwd)"
98
+ OUT_BASE="$(basename "$OUT")"
99
+ cp "$HARNESS" "$OUT_DIR_ABS/_to-lottie-verify.html"
100
+ FRAMES_DIR="$OUT_DIR_ABS/_verify-frames"
101
+ mkdir -p "$FRAMES_DIR"
102
+
103
+ # Serve the dir (file:// blocks fetch of the JSON). Pick a free-ish port.
104
+ PORT=$(( ( RANDOM % 2000 ) + 8200 ))
105
+ ( cd "$OUT_DIR_ABS" && "$PY" -m http.server "$PORT" >/dev/null 2>&1 ) &
106
+ SRV_PID=$!
107
+ trap 'kill "$SRV_PID" 2>/dev/null; rm -f "$OUT_DIR_ABS/_to-lottie-verify.html"' EXIT
108
+ sleep 1
109
+
110
+ FAIL=0
111
+ IFS=',' read -r -a FRAME_ARR <<< "$FRAMES"
112
+ for F in "${FRAME_ARR[@]}"; do
113
+ F_TRIM="$(printf '%s' "$F" | tr -d '[:space:]')"
114
+ URL="http://localhost:$PORT/_to-lottie-verify.html?src=$OUT_BASE&f=$F_TRIM"
115
+ PNG="$FRAMES_DIR/frame-$F_TRIM.png"
116
+ echo "→ verify frame $F_TRIM ($URL)" >&2
117
+ bash "$SCRIPT_DIR/screenshot.sh" --url "$URL" --full --out "$PNG" --timeout "$TIMEOUT" >&2 \
118
+ || { echo "✗ verify frame $F_TRIM failed" >&2; FAIL=$((FAIL + 1)); }
119
+ done
120
+ if [ "$FAIL" -gt 0 ]; then
121
+ echo "to-lottie.sh: $FAIL verify frame(s) failed to render" >&2
122
+ exit 4
123
+ fi
124
+ echo "→ verify frames in $FRAMES_DIR — READ them and compare to the web reference (masks render on lottie-web, NOT cairo)" >&2
125
+ fi
126
+
127
+ # Last stdout line = the output path, for $(maude design to-lottie ...) capture.
128
+ printf '%s\n' "$OUT"
@@ -41,6 +41,9 @@
41
41
  # 2 bad args
42
42
  # 3 one or more specimen screenshots failed
43
43
  # 4 no specimens existed on disk (DS not scaffolded? typo?)
44
+ # 5 dev-server runtime deps missing (yjs/y-protocols/lib0) — recovery is
45
+ # `bun install`, NOT skip-or-retry; distinct from a generic boot failure
46
+ # so the caller routes to the right hint (server-up.sh exit 3). DDR-083.
44
47
 
45
48
  DS=""
46
49
  SPECIMENS=""
@@ -142,18 +145,31 @@ echo "→ booting dev-server (timeout ${BOOT_TIMEOUT}s)" >&2
142
145
  PORT=$(bash "$SCRIPT_DIR/server-up.sh" --root "$ROOT_ABS" --timeout "$BOOT_TIMEOUT")
143
146
  SERVER_RC=$?
144
147
  if [ $SERVER_RC -ne 0 ] || [ -z "$PORT" ]; then
145
- echo "✗ dev-server boot failed (server-up.sh exit $SERVER_RC); see $DESIGN_ROOT/_server.log" >&2
148
+ # server-up.sh exit 3 = the dev-server's runtime deps aren't installed. That's
149
+ # a distinct failure from a generic boot crash/timeout: the fix is `bun install`,
150
+ # not "skip or retry". Surface a dedicated status + exit code (5) so the caller
151
+ # routes to the right remediation instead of the boot-failed AskUserQuestion.
152
+ # The actionable hint already went to stderr from server-up.sh. DDR-083.
153
+ if [ $SERVER_RC -eq 3 ]; then
154
+ echo "✗ dev-server runtime deps missing — run \`bun install\` in the dev-server dir (see hint above)" >&2
155
+ VS_STATUS="server-deps-missing"
156
+ VS_EXIT=5
157
+ else
158
+ echo "✗ dev-server boot failed (server-up.sh exit $SERVER_RC); see $DESIGN_ROOT/_server.log" >&2
159
+ VS_STATUS="server-boot-failed"
160
+ VS_EXIT=1
161
+ fi
146
162
  cat > "$OUT_DIR/_manifest.json" <<EOF
147
163
  {
148
164
  "ds": "$DS",
149
165
  "ts": "$TS",
150
- "status": "server-boot-failed",
166
+ "status": "$VS_STATUS",
151
167
  "server_up_rc": $SERVER_RC,
152
168
  "specimens_requested": $(printf '%s\n' "${SPEC_ARR[@]}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | sed '/^$/d' | sed 's/.*/"&"/' | paste -sd, -),
153
169
  "specimens_captured": []
154
170
  }
155
171
  EOF
156
- exit 1
172
+ exit $VS_EXIT
157
173
  fi
158
174
  echo "✓ dev-server on port $PORT" >&2
159
175
 
@@ -66,8 +66,8 @@ function ensureDist() {
66
66
  }
67
67
 
68
68
  async function readPluginVersion(): Promise<{ version: string }> {
69
- // plugins/design/dev-server/ → plugins/design/.claude-plugin/plugin.json
70
- const manifest = join(ROOT, '..', '.claude-plugin', 'plugin.json');
69
+ // apps/studio/ → ../../plugins/design/.claude-plugin/plugin.json (DDR-095)
70
+ const manifest = join(ROOT, '..', '..', 'plugins', 'design', '.claude-plugin', 'plugin.json');
71
71
  try {
72
72
  const parsed = JSON.parse(await Bun.file(manifest).text()) as { version?: unknown };
73
73
  if (typeof parsed.version === 'string') return { version: parsed.version };
@@ -257,7 +257,9 @@ async function ensureBindingForTarget(oxcSlug: string): Promise<void> {
257
257
  let oxcVersion = '0.131.0';
258
258
  const candidates = [
259
259
  join(ROOT, 'node_modules', 'oxc-parser', 'package.json'),
260
- join(ROOT, '..', '..', '..', 'node_modules', 'oxc-parser', 'package.json'),
260
+ // apps/studio ../../ = repo root → node_modules (DDR-095: was ../../../ at
261
+ // the old plugins/design/dev-server depth).
262
+ join(ROOT, '..', '..', 'node_modules', 'oxc-parser', 'package.json'),
261
263
  ];
262
264
  for (const c of candidates) {
263
265
  if (existsSync(c)) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file canvas-arrowheads.ts — Phase 24 arrow shaft + head geometry
3
- * @scope plugins/design/dev-server/canvas-arrowheads.ts
3
+ * @scope apps/studio/canvas-arrowheads.ts
4
4
  * @purpose Single source of truth for arrow rendering. An ArrowStroke is
5
5
  * reduced to an ordered list of `SvgPrimitive`s (the shaft, then
6
6
  * the start head, then the end head). The serializer formats each
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file canvas-comment-mount.tsx — shell-owned comment layer + mountCanvas
3
- * @scope plugins/design/dev-server/canvas-comment-mount.tsx
3
+ * @scope apps/studio/canvas-comment-mount.tsx
4
4
  * @purpose The canvas mount harness (`_shell.html`) calls `mountCanvas`
5
5
  * instead of rendering the canvas default-export raw. mountCanvas
6
6
  * wraps ANY default export — a `DesignCanvas` UI canvas OR a bare
@@ -29,9 +29,9 @@
29
29
  import {
30
30
  Component,
31
31
  type ComponentType,
32
+ createElement,
32
33
  Fragment,
33
34
  type ReactNode,
34
- createElement,
35
35
  useCallback,
36
36
  useEffect,
37
37
  useMemo,