@dfosco/storyboard 0.5.0-alpha.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 (592) hide show
  1. package/commandpalette.config.json +152 -0
  2. package/dist/storyboard-ui.css +1 -0
  3. package/dist/storyboard-ui.js +21328 -0
  4. package/dist/storyboard-ui.js.map +1 -0
  5. package/dist/tailwind.css +2 -0
  6. package/dist/tiny-canvas.css +1 -0
  7. package/dist/tiny-canvas.js +389 -0
  8. package/package.json +121 -0
  9. package/paste.config.json +67 -0
  10. package/scaffold/AGENTS.md +432 -0
  11. package/scaffold/agents/prompt-agent.agent.md +181 -0
  12. package/scaffold/agents/terminal-agent.agent.md +351 -0
  13. package/scaffold/codex/config.toml +246 -0
  14. package/scaffold/deploy.yml +103 -0
  15. package/scaffold/githooks/pre-push +114 -0
  16. package/scaffold/gitignore +64 -0
  17. package/scaffold/manifest.json +56 -0
  18. package/scaffold/preview.yml +181 -0
  19. package/scaffold/scripts/link.sh +26 -0
  20. package/scaffold/scripts/unlink.sh +10 -0
  21. package/scaffold/skills/agent-browser/SKILL.md +260 -0
  22. package/scaffold/skills/canvas/SKILL.md +364 -0
  23. package/scaffold/skills/create/SKILL.md +501 -0
  24. package/scaffold/skills/ship/SKILL.md +237 -0
  25. package/scaffold/skills/storyboard/SKILL.md +360 -0
  26. package/scaffold/skills/update-storyboard/SKILL.md +16 -0
  27. package/scaffold/skills/update-storyboard/update-storyboard-packages.sh +26 -0
  28. package/scaffold/skills/vitest/GENERATION.md +5 -0
  29. package/scaffold/skills/vitest/SKILL.md +52 -0
  30. package/scaffold/skills/vitest/references/advanced-environments.md +264 -0
  31. package/scaffold/skills/vitest/references/advanced-projects.md +300 -0
  32. package/scaffold/skills/vitest/references/advanced-type-testing.md +237 -0
  33. package/scaffold/skills/vitest/references/advanced-vi.md +249 -0
  34. package/scaffold/skills/vitest/references/core-cli.md +166 -0
  35. package/scaffold/skills/vitest/references/core-config.md +174 -0
  36. package/scaffold/skills/vitest/references/core-describe.md +193 -0
  37. package/scaffold/skills/vitest/references/core-expect.md +219 -0
  38. package/scaffold/skills/vitest/references/core-hooks.md +244 -0
  39. package/scaffold/skills/vitest/references/core-test-api.md +233 -0
  40. package/scaffold/skills/vitest/references/features-concurrency.md +250 -0
  41. package/scaffold/skills/vitest/references/features-context.md +238 -0
  42. package/scaffold/skills/vitest/references/features-coverage.md +207 -0
  43. package/scaffold/skills/vitest/references/features-filtering.md +211 -0
  44. package/scaffold/skills/vitest/references/features-mocking.md +265 -0
  45. package/scaffold/skills/vitest/references/features-snapshots.md +207 -0
  46. package/scaffold/skills/worktree/SKILL.md +93 -0
  47. package/scaffold/storyboard.config.json +44 -0
  48. package/src/canvas/Canvas.jsx +78 -0
  49. package/src/canvas/Draggable.jsx +235 -0
  50. package/src/canvas/index.d.ts +41 -0
  51. package/src/canvas/index.js +6 -0
  52. package/src/canvas/style.css +118 -0
  53. package/src/canvas/useResetCanvas.js +17 -0
  54. package/src/canvas/utils.js +136 -0
  55. package/src/core/assets/fonts/IoskeleyMono-Bold.woff2 +0 -0
  56. package/src/core/assets/fonts/IoskeleyMono-Italic.woff2 +0 -0
  57. package/src/core/assets/fonts/IoskeleyMono-Medium.woff2 +0 -0
  58. package/src/core/assets/fonts/IoskeleyMono-Regular.woff2 +0 -0
  59. package/src/core/assets/fonts/IoskeleyMono-SemiBold.woff2 +0 -0
  60. package/src/core/autosync/server.js +714 -0
  61. package/src/core/autosync/server.test.js +158 -0
  62. package/src/core/canvas/__tests__/agent-integration.test.js +596 -0
  63. package/src/core/canvas/__tests__/helpers/browser.js +95 -0
  64. package/src/core/canvas/__tests__/helpers/canvas-api.js +129 -0
  65. package/src/core/canvas/__tests__/helpers/perf.js +118 -0
  66. package/src/core/canvas/__tests__/helpers/setup.js +176 -0
  67. package/src/core/canvas/__tests__/helpers/tmux.js +130 -0
  68. package/src/core/canvas/__tests__/helpers/transcript.js +132 -0
  69. package/src/core/canvas/__tests__/terminal-integration.test.js +177 -0
  70. package/src/core/canvas/collision.js +292 -0
  71. package/src/core/canvas/collision.test.js +371 -0
  72. package/src/core/canvas/compact.js +83 -0
  73. package/src/core/canvas/deriveCanvasId.test.js +40 -0
  74. package/src/core/canvas/githubEmbeds.js +527 -0
  75. package/src/core/canvas/githubEmbeds.test.js +302 -0
  76. package/src/core/canvas/hot-pool.js +766 -0
  77. package/src/core/canvas/identity.js +107 -0
  78. package/src/core/canvas/identity.test.js +100 -0
  79. package/src/core/canvas/materializer.js +259 -0
  80. package/src/core/canvas/materializer.test.js +356 -0
  81. package/src/core/canvas/selectedWidgets.js +270 -0
  82. package/src/core/canvas/selectedWidgets.test.js +321 -0
  83. package/src/core/canvas/server.js +3134 -0
  84. package/src/core/canvas/server.test.js +379 -0
  85. package/src/core/canvas/terminal-config.js +330 -0
  86. package/src/core/canvas/terminal-registry.js +465 -0
  87. package/src/core/canvas/terminal-server.js +1436 -0
  88. package/src/core/canvas/writeGuard.js +53 -0
  89. package/src/core/cli/agent.js +85 -0
  90. package/src/core/cli/branch.js +386 -0
  91. package/src/core/cli/canvasAdd.js +241 -0
  92. package/src/core/cli/canvasBatch.js +98 -0
  93. package/src/core/cli/canvasBounds.js +160 -0
  94. package/src/core/cli/canvasRead.js +236 -0
  95. package/src/core/cli/canvasUpdate.js +179 -0
  96. package/src/core/cli/code.js +67 -0
  97. package/src/core/cli/compact.js +62 -0
  98. package/src/core/cli/create.js +674 -0
  99. package/src/core/cli/dev-helpers.js +53 -0
  100. package/src/core/cli/dev-helpers.test.js +53 -0
  101. package/src/core/cli/dev.js +430 -0
  102. package/src/core/cli/exit.js +38 -0
  103. package/src/core/cli/flags.js +174 -0
  104. package/src/core/cli/flags.test.js +155 -0
  105. package/src/core/cli/index.js +233 -0
  106. package/src/core/cli/intro.js +37 -0
  107. package/src/core/cli/proxy.js +319 -0
  108. package/src/core/cli/proxy.test.js +63 -0
  109. package/src/core/cli/schemas.js +223 -0
  110. package/src/core/cli/server.js +192 -0
  111. package/src/core/cli/serverUrl.js +61 -0
  112. package/src/core/cli/sessions.js +459 -0
  113. package/src/core/cli/setup.js +404 -0
  114. package/src/core/cli/terminal-commands.js +287 -0
  115. package/src/core/cli/terminal-messaging.js +231 -0
  116. package/src/core/cli/terminal-welcome.js +515 -0
  117. package/src/core/cli/updateVersion.js +124 -0
  118. package/src/core/comments/api.js +284 -0
  119. package/src/core/comments/api.test.js +282 -0
  120. package/src/core/comments/auth.js +151 -0
  121. package/src/core/comments/auth.test.js +167 -0
  122. package/src/core/comments/commentCache.js +109 -0
  123. package/src/core/comments/commentCache.test.js +48 -0
  124. package/src/core/comments/commentDrafts.js +68 -0
  125. package/src/core/comments/commentMode.js +63 -0
  126. package/src/core/comments/commentMode.test.js +90 -0
  127. package/src/core/comments/config.js +47 -0
  128. package/src/core/comments/config.test.js +77 -0
  129. package/src/core/comments/graphql.js +65 -0
  130. package/src/core/comments/graphql.test.js +95 -0
  131. package/src/core/comments/index.js +42 -0
  132. package/src/core/comments/metadata.js +52 -0
  133. package/src/core/comments/metadata.test.js +110 -0
  134. package/src/core/comments/queries.js +245 -0
  135. package/src/core/comments/ui/AuthModal.jsx +114 -0
  136. package/src/core/comments/ui/CommentOverlay.js +52 -0
  137. package/src/core/comments/ui/CommentWindow.jsx +329 -0
  138. package/src/core/comments/ui/CommentsDrawer.jsx +102 -0
  139. package/src/core/comments/ui/Composer.jsx +64 -0
  140. package/src/core/comments/ui/authModal.js +66 -0
  141. package/src/core/comments/ui/authModal.test.js +76 -0
  142. package/src/core/comments/ui/comment-cursor-dark.svg +1 -0
  143. package/src/core/comments/ui/comment-cursor.svg +1 -0
  144. package/src/core/comments/ui/comment-layout.css +142 -0
  145. package/src/core/comments/ui/commentWindow.js +121 -0
  146. package/src/core/comments/ui/comments.css +242 -0
  147. package/src/core/comments/ui/commentsDrawer.js +84 -0
  148. package/src/core/comments/ui/composer.js +136 -0
  149. package/src/core/comments/ui/index.js +14 -0
  150. package/src/core/comments/ui/mount.js +687 -0
  151. package/src/core/comments/ui/mount.test.js +336 -0
  152. package/src/core/data/dotPath.js +53 -0
  153. package/src/core/data/dotPath.test.js +114 -0
  154. package/src/core/data/loader.js +409 -0
  155. package/src/core/data/loader.test.js +599 -0
  156. package/src/core/data/viewfinder.js +363 -0
  157. package/src/core/data/viewfinder.test.js +456 -0
  158. package/src/core/devtools/devtools-consumer.js +28 -0
  159. package/src/core/devtools/devtools.js +144 -0
  160. package/src/core/devtools/devtools.test.js +75 -0
  161. package/src/core/devtools/sceneDebug.js +112 -0
  162. package/src/core/devtools/sceneDebug.test.js +141 -0
  163. package/src/core/index.js +124 -0
  164. package/src/core/inspector/fiberWalker.js +239 -0
  165. package/src/core/inspector/highlighter.js +275 -0
  166. package/src/core/inspector/mouseMode.js +259 -0
  167. package/src/core/lib/components/ui/alert/alert-action.jsx +11 -0
  168. package/src/core/lib/components/ui/alert/alert-description.jsx +11 -0
  169. package/src/core/lib/components/ui/alert/alert-title.jsx +11 -0
  170. package/src/core/lib/components/ui/alert/alert.jsx +25 -0
  171. package/src/core/lib/components/ui/alert/index.js +17 -0
  172. package/src/core/lib/components/ui/avatar/avatar-badge.jsx +22 -0
  173. package/src/core/lib/components/ui/avatar/avatar-fallback.jsx +18 -0
  174. package/src/core/lib/components/ui/avatar/avatar-group-count.jsx +19 -0
  175. package/src/core/lib/components/ui/avatar/avatar-group.jsx +19 -0
  176. package/src/core/lib/components/ui/avatar/avatar-image.jsx +15 -0
  177. package/src/core/lib/components/ui/avatar/avatar.jsx +19 -0
  178. package/src/core/lib/components/ui/avatar/index.js +22 -0
  179. package/src/core/lib/components/ui/badge/badge.jsx +31 -0
  180. package/src/core/lib/components/ui/badge/index.js +2 -0
  181. package/src/core/lib/components/ui/button/button.jsx +100 -0
  182. package/src/core/lib/components/ui/button/index.js +12 -0
  183. package/src/core/lib/components/ui/card/card-action.jsx +11 -0
  184. package/src/core/lib/components/ui/card/card-content.jsx +11 -0
  185. package/src/core/lib/components/ui/card/card-description.jsx +11 -0
  186. package/src/core/lib/components/ui/card/card-footer.jsx +11 -0
  187. package/src/core/lib/components/ui/card/card-header.jsx +19 -0
  188. package/src/core/lib/components/ui/card/card-title.jsx +11 -0
  189. package/src/core/lib/components/ui/card/card.jsx +17 -0
  190. package/src/core/lib/components/ui/card/index.js +25 -0
  191. package/src/core/lib/components/ui/checkbox/checkbox.jsx +29 -0
  192. package/src/core/lib/components/ui/checkbox/index.js +6 -0
  193. package/src/core/lib/components/ui/collapsible/collapsible-content.jsx +7 -0
  194. package/src/core/lib/components/ui/collapsible/collapsible-trigger.jsx +7 -0
  195. package/src/core/lib/components/ui/collapsible/collapsible.jsx +7 -0
  196. package/src/core/lib/components/ui/collapsible/index.js +13 -0
  197. package/src/core/lib/components/ui/dialog/dialog-close.jsx +7 -0
  198. package/src/core/lib/components/ui/dialog/dialog-content.jsx +34 -0
  199. package/src/core/lib/components/ui/dialog/dialog-description.jsx +15 -0
  200. package/src/core/lib/components/ui/dialog/dialog-footer.jsx +23 -0
  201. package/src/core/lib/components/ui/dialog/dialog-header.jsx +11 -0
  202. package/src/core/lib/components/ui/dialog/dialog-overlay.jsx +15 -0
  203. package/src/core/lib/components/ui/dialog/dialog-portal.jsx +4 -0
  204. package/src/core/lib/components/ui/dialog/dialog-title.jsx +15 -0
  205. package/src/core/lib/components/ui/dialog/dialog-trigger.jsx +7 -0
  206. package/src/core/lib/components/ui/dialog/dialog.jsx +4 -0
  207. package/src/core/lib/components/ui/dialog/index.js +34 -0
  208. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +8 -0
  209. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +30 -0
  210. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +22 -0
  211. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +16 -0
  212. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +7 -0
  213. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +20 -0
  214. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-label.jsx +17 -0
  215. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +4 -0
  216. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +7 -0
  217. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +29 -0
  218. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +15 -0
  219. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.jsx +16 -0
  220. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +15 -0
  221. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +23 -0
  222. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +4 -0
  223. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +7 -0
  224. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu.jsx +4 -0
  225. package/src/core/lib/components/ui/dropdown-menu/index.js +54 -0
  226. package/src/core/lib/components/ui/input/index.js +7 -0
  227. package/src/core/lib/components/ui/input/input.jsx +19 -0
  228. package/src/core/lib/components/ui/label/index.js +7 -0
  229. package/src/core/lib/components/ui/label/label.jsx +19 -0
  230. package/src/core/lib/components/ui/panel/index.js +24 -0
  231. package/src/core/lib/components/ui/panel/panel-body.jsx +11 -0
  232. package/src/core/lib/components/ui/panel/panel-close.jsx +16 -0
  233. package/src/core/lib/components/ui/panel/panel-content.jsx +29 -0
  234. package/src/core/lib/components/ui/panel/panel-footer.jsx +11 -0
  235. package/src/core/lib/components/ui/panel/panel-header.jsx +11 -0
  236. package/src/core/lib/components/ui/panel/panel-title.jsx +12 -0
  237. package/src/core/lib/components/ui/panel/panel.jsx +4 -0
  238. package/src/core/lib/components/ui/popover/index.js +28 -0
  239. package/src/core/lib/components/ui/popover/popover-close.jsx +7 -0
  240. package/src/core/lib/components/ui/popover/popover-content.jsx +22 -0
  241. package/src/core/lib/components/ui/popover/popover-description.jsx +11 -0
  242. package/src/core/lib/components/ui/popover/popover-header.jsx +11 -0
  243. package/src/core/lib/components/ui/popover/popover-portal.jsx +4 -0
  244. package/src/core/lib/components/ui/popover/popover-title.jsx +11 -0
  245. package/src/core/lib/components/ui/popover/popover-trigger.jsx +8 -0
  246. package/src/core/lib/components/ui/popover/popover.jsx +4 -0
  247. package/src/core/lib/components/ui/searchable-list.jsx +160 -0
  248. package/src/core/lib/components/ui/select/index.js +37 -0
  249. package/src/core/lib/components/ui/select/select-content.jsx +30 -0
  250. package/src/core/lib/components/ui/select/select-group-heading.jsx +17 -0
  251. package/src/core/lib/components/ui/select/select-group.jsx +15 -0
  252. package/src/core/lib/components/ui/select/select-item.jsx +26 -0
  253. package/src/core/lib/components/ui/select/select-label.jsx +11 -0
  254. package/src/core/lib/components/ui/select/select-portal.jsx +4 -0
  255. package/src/core/lib/components/ui/select/select-scroll-down-button.jsx +18 -0
  256. package/src/core/lib/components/ui/select/select-scroll-up-button.jsx +18 -0
  257. package/src/core/lib/components/ui/select/select-separator.jsx +15 -0
  258. package/src/core/lib/components/ui/select/select-trigger.jsx +25 -0
  259. package/src/core/lib/components/ui/select/select.jsx +4 -0
  260. package/src/core/lib/components/ui/separator/index.js +7 -0
  261. package/src/core/lib/components/ui/separator/separator.jsx +22 -0
  262. package/src/core/lib/components/ui/sheet/index.js +34 -0
  263. package/src/core/lib/components/ui/sheet/sheet-close.jsx +7 -0
  264. package/src/core/lib/components/ui/sheet/sheet-content.jsx +35 -0
  265. package/src/core/lib/components/ui/sheet/sheet-description.jsx +15 -0
  266. package/src/core/lib/components/ui/sheet/sheet-footer.jsx +11 -0
  267. package/src/core/lib/components/ui/sheet/sheet-header.jsx +11 -0
  268. package/src/core/lib/components/ui/sheet/sheet-overlay.jsx +15 -0
  269. package/src/core/lib/components/ui/sheet/sheet-portal.jsx +4 -0
  270. package/src/core/lib/components/ui/sheet/sheet-title.jsx +15 -0
  271. package/src/core/lib/components/ui/sheet/sheet-trigger.jsx +7 -0
  272. package/src/core/lib/components/ui/sheet/sheet.jsx +4 -0
  273. package/src/core/lib/components/ui/textarea/index.js +7 -0
  274. package/src/core/lib/components/ui/textarea/textarea.jsx +18 -0
  275. package/src/core/lib/components/ui/toggle/index.js +8 -0
  276. package/src/core/lib/components/ui/toggle/toggle.jsx +36 -0
  277. package/src/core/lib/components/ui/toggle-group/index.js +10 -0
  278. package/src/core/lib/components/ui/toggle-group/toggle-group-item.jsx +29 -0
  279. package/src/core/lib/components/ui/toggle-group/toggle-group.jsx +43 -0
  280. package/src/core/lib/components/ui/tooltip/index.js +3 -0
  281. package/src/core/lib/components/ui/tooltip/tooltip-content.jsx +21 -0
  282. package/src/core/lib/components/ui/tooltip/tooltip-trigger.jsx +23 -0
  283. package/src/core/lib/components/ui/tooltip/tooltip.jsx +11 -0
  284. package/src/core/lib/components/ui/trigger-button/index.js +6 -0
  285. package/src/core/lib/components/ui/trigger-button/trigger-button.css +38 -0
  286. package/src/core/lib/components/ui/trigger-button/trigger-button.jsx +63 -0
  287. package/src/core/lib/utils/index.js +6 -0
  288. package/src/core/logger/devLogger.js +238 -0
  289. package/src/core/logger/devLogger.test.js +193 -0
  290. package/src/core/modes/modes.css +98 -0
  291. package/src/core/modes/modes.js +492 -0
  292. package/src/core/modes/modes.test.js +562 -0
  293. package/src/core/mountStoryboardCore.js +478 -0
  294. package/src/core/rename-watcher/config.json +23 -0
  295. package/src/core/rename-watcher/watcher.js +531 -0
  296. package/src/core/scaffold.js +100 -0
  297. package/src/core/server/index.js +391 -0
  298. package/src/core/session/bodyClasses.js +128 -0
  299. package/src/core/session/bodyClasses.test.js +192 -0
  300. package/src/core/session/hashSubscribe.js +19 -0
  301. package/src/core/session/hashSubscribe.test.js +62 -0
  302. package/src/core/session/hideMode.js +424 -0
  303. package/src/core/session/hideMode.test.js +268 -0
  304. package/src/core/session/interceptHideParams.js +35 -0
  305. package/src/core/session/interceptHideParams.test.js +90 -0
  306. package/src/core/session/localStorage.js +134 -0
  307. package/src/core/session/localStorage.test.js +148 -0
  308. package/src/core/session/session.js +76 -0
  309. package/src/core/session/session.test.js +91 -0
  310. package/src/core/stores/canvasConfig.js +134 -0
  311. package/src/core/stores/canvasConfig.test.js +120 -0
  312. package/src/core/stores/commandActions.js +284 -0
  313. package/src/core/stores/commandPaletteConfig.js +31 -0
  314. package/src/core/stores/configSchema.js +232 -0
  315. package/src/core/stores/configSchema.test.js +72 -0
  316. package/src/core/stores/configStore.js +161 -0
  317. package/src/core/stores/customerModeConfig.js +30 -0
  318. package/src/core/stores/featureFlags.js +127 -0
  319. package/src/core/stores/paletteProviders.js +360 -0
  320. package/src/core/stores/paletteProviders.test.js +186 -0
  321. package/src/core/stores/plugins.js +40 -0
  322. package/src/core/stores/plugins.test.js +68 -0
  323. package/src/core/stores/recentArtifacts.js +68 -0
  324. package/src/core/stores/recentArtifacts.test.js +71 -0
  325. package/src/core/stores/sidePanelStore.ts +143 -0
  326. package/src/core/stores/themeStore.ts +291 -0
  327. package/src/core/stores/toolRegistry.js +227 -0
  328. package/src/core/stores/toolStateStore.js +183 -0
  329. package/src/core/stores/toolStateStore.test.js +220 -0
  330. package/src/core/stores/toolbarConfigStore.js +165 -0
  331. package/src/core/stores/uiConfig.js +64 -0
  332. package/src/core/stores/uiConfig.test.js +63 -0
  333. package/src/core/styles/tailwind.css +204 -0
  334. package/src/core/tools/handlers/autosync.js +12 -0
  335. package/src/core/tools/handlers/canvasAddWidget.js +11 -0
  336. package/src/core/tools/handlers/canvasAgents.js +20 -0
  337. package/src/core/tools/handlers/canvasToolbar.js +56 -0
  338. package/src/core/tools/handlers/commandPalette.js +9 -0
  339. package/src/core/tools/handlers/comments.js +16 -0
  340. package/src/core/tools/handlers/create.js +39 -0
  341. package/src/core/tools/handlers/devtools.js +122 -0
  342. package/src/core/tools/handlers/devtools.test.js +87 -0
  343. package/src/core/tools/handlers/featureFlags.js +21 -0
  344. package/src/core/tools/handlers/flows.js +68 -0
  345. package/src/core/tools/handlers/hideChrome.js +9 -0
  346. package/src/core/tools/handlers/hideToolbars.js +25 -0
  347. package/src/core/tools/handlers/inspector.js +19 -0
  348. package/src/core/tools/handlers/paletteTheme.js +35 -0
  349. package/src/core/tools/handlers/theme.js +9 -0
  350. package/src/core/tools/registry.js +26 -0
  351. package/src/core/tools/surfaces/canvasToolbar.js +10 -0
  352. package/src/core/tools/surfaces/commandList.js +10 -0
  353. package/src/core/tools/surfaces/mainToolbar.js +11 -0
  354. package/src/core/tools/surfaces/registry.js +19 -0
  355. package/src/core/ui/ActionMenuButton.jsx +114 -0
  356. package/src/core/ui/AutosyncMenuButton.css +67 -0
  357. package/src/core/ui/AutosyncMenuButton.jsx +242 -0
  358. package/src/core/ui/BranchSelect.jsx +29 -0
  359. package/src/core/ui/BranchSelect.module.css +30 -0
  360. package/src/core/ui/CanvasAgentsMenu.jsx +89 -0
  361. package/src/core/ui/CanvasCreateMenu.jsx +611 -0
  362. package/src/core/ui/CanvasSnap.css +27 -0
  363. package/src/core/ui/CanvasSnap.jsx +51 -0
  364. package/src/core/ui/CanvasUndoRedo.css +36 -0
  365. package/src/core/ui/CanvasUndoRedo.jsx +62 -0
  366. package/src/core/ui/CanvasZoomControl.css +53 -0
  367. package/src/core/ui/CanvasZoomControl.jsx +49 -0
  368. package/src/core/ui/CanvasZoomToFit.css +18 -0
  369. package/src/core/ui/CanvasZoomToFit.jsx +26 -0
  370. package/src/core/ui/CommandMenu.css +8 -0
  371. package/src/core/ui/CommandMenu.jsx +287 -0
  372. package/src/core/ui/CommandPalette.jsx +35 -0
  373. package/src/core/ui/CommandPaletteTrigger.jsx +25 -0
  374. package/src/core/ui/CommentsMenuButton.jsx +40 -0
  375. package/src/core/ui/CoreUIBar.css +47 -0
  376. package/src/core/ui/CoreUIBar.jsx +905 -0
  377. package/src/core/ui/CreateMenuButton.jsx +117 -0
  378. package/src/core/ui/HideChromeTrigger.jsx +48 -0
  379. package/src/core/ui/Icon.jsx +279 -0
  380. package/src/core/ui/InspectorPanel.css +109 -0
  381. package/src/core/ui/InspectorPanel.jsx +632 -0
  382. package/src/core/ui/PwaInstallBanner.css +42 -0
  383. package/src/core/ui/PwaInstallBanner.jsx +124 -0
  384. package/src/core/ui/SidePanel.jsx +261 -0
  385. package/src/core/ui/ThemeMenuButton.jsx +139 -0
  386. package/src/core/ui/core-ui-colors.css +129 -0
  387. package/src/core/ui/design-modes.ts +7 -0
  388. package/src/core/ui/sidepanel.css +301 -0
  389. package/src/core/ui/viewfinder.ts +7 -0
  390. package/src/core/ui-entry.js +30 -0
  391. package/src/core/utils/fuzzySearch.js +117 -0
  392. package/src/core/utils/fuzzySearch.test.js +119 -0
  393. package/src/core/utils/mobileViewport.js +57 -0
  394. package/src/core/utils/mobileViewport.test.js +68 -0
  395. package/src/core/utils/prodMode.js +38 -0
  396. package/src/core/utils/smoothCorners.js +20 -0
  397. package/src/core/vite/docs-handler.js +155 -0
  398. package/src/core/vite/server-plugin.js +797 -0
  399. package/src/core/workshop/features/createCanvas/CreateCanvasForm.jsx +260 -0
  400. package/src/core/workshop/features/createCanvas/index.js +14 -0
  401. package/src/core/workshop/features/createFlow/CreateFlowForm.jsx +334 -0
  402. package/src/core/workshop/features/createFlow/index.js +19 -0
  403. package/src/core/workshop/features/createFlow/server.js +663 -0
  404. package/src/core/workshop/features/createPage/CreatePageForm.jsx +304 -0
  405. package/src/core/workshop/features/createPage/index.js +11 -0
  406. package/src/core/workshop/features/createPrototype/CreatePrototypeForm.jsx +289 -0
  407. package/src/core/workshop/features/createPrototype/index.js +19 -0
  408. package/src/core/workshop/features/createPrototype/server.js +433 -0
  409. package/src/core/workshop/features/createStory/CreateStoryForm.jsx +208 -0
  410. package/src/core/workshop/features/createStory/index.js +14 -0
  411. package/src/core/workshop/features/registry-server.js +22 -0
  412. package/src/core/workshop/features/registry.js +28 -0
  413. package/src/core/workshop/features/templateIndex.js +155 -0
  414. package/src/core/workshop/ui/WorkshopPanel.jsx +98 -0
  415. package/src/core/workshop/ui/mount.ts +6 -0
  416. package/src/core/worktree/port.js +268 -0
  417. package/src/core/worktree/port.test.js +222 -0
  418. package/src/core/worktree/serverRegistry.js +120 -0
  419. package/src/internals/AuthModal/AuthModal.jsx +132 -0
  420. package/src/internals/AuthModal/AuthModal.module.css +221 -0
  421. package/src/internals/BranchBar/BranchBar.jsx +87 -0
  422. package/src/internals/BranchBar/BranchBar.module.css +247 -0
  423. package/src/internals/BranchBar/useBranches.js +93 -0
  424. package/src/internals/BranchBar/useBranches.test.js +68 -0
  425. package/src/internals/CommandPalette/CommandPalette.jsx +1361 -0
  426. package/src/internals/CommandPalette/CreateDialog.jsx +219 -0
  427. package/src/internals/CommandPalette/command-palette.css +180 -0
  428. package/src/internals/FlowError.module.css +30 -0
  429. package/src/internals/Icon.jsx +279 -0
  430. package/src/internals/StoryboardContext.js +3 -0
  431. package/src/internals/Viewfinder.jsx +1479 -0
  432. package/src/internals/Viewfinder.module.css +1540 -0
  433. package/src/internals/Workspace.jsx +7 -0
  434. package/src/internals/__mocks__/virtual-storyboard-data-index.js +4 -0
  435. package/src/internals/canvas/CanvasControls.jsx +112 -0
  436. package/src/internals/canvas/CanvasControls.module.css +135 -0
  437. package/src/internals/canvas/CanvasPage.bridge.test.jsx +387 -0
  438. package/src/internals/canvas/CanvasPage.dragdrop.test.jsx +350 -0
  439. package/src/internals/canvas/CanvasPage.jsx +3092 -0
  440. package/src/internals/canvas/CanvasPage.module.css +187 -0
  441. package/src/internals/canvas/CanvasPage.multiselect.test.jsx +358 -0
  442. package/src/internals/canvas/CanvasToolbar.jsx +73 -0
  443. package/src/internals/canvas/CanvasToolbar.module.css +92 -0
  444. package/src/internals/canvas/ComponentErrorBoundary.jsx +50 -0
  445. package/src/internals/canvas/ConnectorLayer.jsx +208 -0
  446. package/src/internals/canvas/ConnectorLayer.module.css +129 -0
  447. package/src/internals/canvas/MarqueeOverlay.jsx +20 -0
  448. package/src/internals/canvas/PageSelector.jsx +587 -0
  449. package/src/internals/canvas/PageSelector.module.css +261 -0
  450. package/src/internals/canvas/PageSelector.test.jsx +113 -0
  451. package/src/internals/canvas/WebGLContextPool.jsx +292 -0
  452. package/src/internals/canvas/WebGLContextPool.test.jsx +165 -0
  453. package/src/internals/canvas/canvasApi.js +164 -0
  454. package/src/internals/canvas/canvasReloadGuard.js +37 -0
  455. package/src/internals/canvas/canvasReloadGuard.test.js +27 -0
  456. package/src/internals/canvas/canvasTheme.js +118 -0
  457. package/src/internals/canvas/componentIsolate.jsx +165 -0
  458. package/src/internals/canvas/componentSetIsolate.jsx +257 -0
  459. package/src/internals/canvas/computeCanvasBounds.test.js +121 -0
  460. package/src/internals/canvas/connectorGeometry.js +132 -0
  461. package/src/internals/canvas/hotPoolDevLogs.js +25 -0
  462. package/src/internals/canvas/textSelection.js +10 -0
  463. package/src/internals/canvas/textSelection.test.js +26 -0
  464. package/src/internals/canvas/useCanvas.js +126 -0
  465. package/src/internals/canvas/useCanvas.test.js +26 -0
  466. package/src/internals/canvas/useMarqueeSelect.js +213 -0
  467. package/src/internals/canvas/useMarqueeSelect.test.js +78 -0
  468. package/src/internals/canvas/useUndoRedo.js +86 -0
  469. package/src/internals/canvas/useUndoRedo.test.js +231 -0
  470. package/src/internals/canvas/widgets/CodePenEmbed.jsx +293 -0
  471. package/src/internals/canvas/widgets/CodePenEmbed.module.css +161 -0
  472. package/src/internals/canvas/widgets/ComponentSetWidget.jsx +2 -0
  473. package/src/internals/canvas/widgets/ComponentSetWidget.module.css +89 -0
  474. package/src/internals/canvas/widgets/ComponentWidget.jsx +14 -0
  475. package/src/internals/canvas/widgets/ComponentWidget.module.css +0 -0
  476. package/src/internals/canvas/widgets/CropOverlay.jsx +179 -0
  477. package/src/internals/canvas/widgets/CropOverlay.module.css +154 -0
  478. package/src/internals/canvas/widgets/ExpandedPane.jsx +474 -0
  479. package/src/internals/canvas/widgets/ExpandedPane.module.css +179 -0
  480. package/src/internals/canvas/widgets/ExpandedPane.test.jsx +240 -0
  481. package/src/internals/canvas/widgets/ExpandedPaneTopBar.jsx +111 -0
  482. package/src/internals/canvas/widgets/ExpandedPaneTopBar.module.css +59 -0
  483. package/src/internals/canvas/widgets/ExpandedPaneTopBar.test.jsx +45 -0
  484. package/src/internals/canvas/widgets/FigmaEmbed.jsx +296 -0
  485. package/src/internals/canvas/widgets/FigmaEmbed.module.css +222 -0
  486. package/src/internals/canvas/widgets/FrozenTerminalOverlay.jsx +151 -0
  487. package/src/internals/canvas/widgets/FrozenTerminalOverlay.module.css +83 -0
  488. package/src/internals/canvas/widgets/ImageWidget.jsx +287 -0
  489. package/src/internals/canvas/widgets/ImageWidget.module.css +81 -0
  490. package/src/internals/canvas/widgets/LinkPreview.jsx +439 -0
  491. package/src/internals/canvas/widgets/LinkPreview.module.css +585 -0
  492. package/src/internals/canvas/widgets/LinkPreview.test.jsx +193 -0
  493. package/src/internals/canvas/widgets/MarkdownBlock.jsx +354 -0
  494. package/src/internals/canvas/widgets/MarkdownBlock.module.css +377 -0
  495. package/src/internals/canvas/widgets/MarkdownBlock.test.jsx +92 -0
  496. package/src/internals/canvas/widgets/PromptWidget.jsx +428 -0
  497. package/src/internals/canvas/widgets/PromptWidget.module.css +273 -0
  498. package/src/internals/canvas/widgets/PrototypeEmbed.jsx +463 -0
  499. package/src/internals/canvas/widgets/PrototypeEmbed.module.css +579 -0
  500. package/src/internals/canvas/widgets/PrototypeEmbed.test.jsx +10 -0
  501. package/src/internals/canvas/widgets/ResizeHandle.jsx +67 -0
  502. package/src/internals/canvas/widgets/ResizeHandle.module.css +29 -0
  503. package/src/internals/canvas/widgets/StickyNote.jsx +92 -0
  504. package/src/internals/canvas/widgets/StickyNote.module.css +70 -0
  505. package/src/internals/canvas/widgets/StickyNote.test.jsx +116 -0
  506. package/src/internals/canvas/widgets/StorySetWidget.jsx +208 -0
  507. package/src/internals/canvas/widgets/StorySetWidget.module.css +89 -0
  508. package/src/internals/canvas/widgets/StoryWidget.jsx +334 -0
  509. package/src/internals/canvas/widgets/StoryWidget.module.css +211 -0
  510. package/src/internals/canvas/widgets/TerminalReadWidget.jsx +146 -0
  511. package/src/internals/canvas/widgets/TerminalReadWidget.module.css +94 -0
  512. package/src/internals/canvas/widgets/TerminalWidget.jsx +704 -0
  513. package/src/internals/canvas/widgets/TerminalWidget.module.css +444 -0
  514. package/src/internals/canvas/widgets/TilesWidget.jsx +300 -0
  515. package/src/internals/canvas/widgets/TilesWidget.module.css +133 -0
  516. package/src/internals/canvas/widgets/WidgetChrome.jsx +580 -0
  517. package/src/internals/canvas/widgets/WidgetChrome.module.css +421 -0
  518. package/src/internals/canvas/widgets/WidgetWrapper.jsx +15 -0
  519. package/src/internals/canvas/widgets/WidgetWrapper.module.css +25 -0
  520. package/src/internals/canvas/widgets/codepenUrl.js +75 -0
  521. package/src/internals/canvas/widgets/codepenUrl.test.js +76 -0
  522. package/src/internals/canvas/widgets/embedInteraction.test.jsx +173 -0
  523. package/src/internals/canvas/widgets/embedOverlay.module.css +35 -0
  524. package/src/internals/canvas/widgets/embedTheme.js +148 -0
  525. package/src/internals/canvas/widgets/expandUtils.js +559 -0
  526. package/src/internals/canvas/widgets/expandUtils.test.js +155 -0
  527. package/src/internals/canvas/widgets/figmaUrl.js +118 -0
  528. package/src/internals/canvas/widgets/figmaUrl.test.js +139 -0
  529. package/src/internals/canvas/widgets/githubUrl.js +82 -0
  530. package/src/internals/canvas/widgets/githubUrl.test.js +74 -0
  531. package/src/internals/canvas/widgets/iframeDevLogs.js +49 -0
  532. package/src/internals/canvas/widgets/iframeDevLogs.test.jsx +81 -0
  533. package/src/internals/canvas/widgets/index.js +42 -0
  534. package/src/internals/canvas/widgets/pasteRules.js +295 -0
  535. package/src/internals/canvas/widgets/pasteRules.test.js +474 -0
  536. package/src/internals/canvas/widgets/snapshotDisplay.test.jsx +211 -0
  537. package/src/internals/canvas/widgets/tilePool.js +23 -0
  538. package/src/internals/canvas/widgets/tiles/diagonal-bl.png +0 -0
  539. package/src/internals/canvas/widgets/tiles/diagonal-br.png +0 -0
  540. package/src/internals/canvas/widgets/tiles/diagonal-tl.png +0 -0
  541. package/src/internals/canvas/widgets/tiles/leaf.png +0 -0
  542. package/src/internals/canvas/widgets/tiles/quarter-tl.png +0 -0
  543. package/src/internals/canvas/widgets/tiles/quarter-tr.png +0 -0
  544. package/src/internals/canvas/widgets/tiles/solid-a.png +0 -0
  545. package/src/internals/canvas/widgets/tiles/solid-b.png +0 -0
  546. package/src/internals/canvas/widgets/widgetConfig.js +291 -0
  547. package/src/internals/canvas/widgets/widgetConfig.test.js +68 -0
  548. package/src/internals/canvas/widgets/widgetIcons.jsx +190 -0
  549. package/src/internals/canvas/widgets/widgetProps.js +133 -0
  550. package/src/internals/context/FormContext.js +13 -0
  551. package/src/internals/context/FormContext.test.js +48 -0
  552. package/src/internals/context.jsx +481 -0
  553. package/src/internals/context.test.jsx +296 -0
  554. package/src/internals/hashPreserver.js +73 -0
  555. package/src/internals/hashPreserver.test.js +107 -0
  556. package/src/internals/hooks/useConfig.js +14 -0
  557. package/src/internals/hooks/useFeatureFlag.js +14 -0
  558. package/src/internals/hooks/useFlows.js +50 -0
  559. package/src/internals/hooks/useFlows.test.js +134 -0
  560. package/src/internals/hooks/useHideMode.js +31 -0
  561. package/src/internals/hooks/useHideMode.test.js +43 -0
  562. package/src/internals/hooks/useLocalStorage.js +57 -0
  563. package/src/internals/hooks/useLocalStorage.test.js +75 -0
  564. package/src/internals/hooks/useMode.js +43 -0
  565. package/src/internals/hooks/useObject.js +101 -0
  566. package/src/internals/hooks/useObject.test.js +74 -0
  567. package/src/internals/hooks/useOverride.js +84 -0
  568. package/src/internals/hooks/useOverride.test.js +71 -0
  569. package/src/internals/hooks/usePrototypeReloadGuard.js +64 -0
  570. package/src/internals/hooks/useRecord.js +158 -0
  571. package/src/internals/hooks/useRecord.test.js +221 -0
  572. package/src/internals/hooks/useScene.js +38 -0
  573. package/src/internals/hooks/useScene.test.js +66 -0
  574. package/src/internals/hooks/useSceneData.js +108 -0
  575. package/src/internals/hooks/useSceneData.test.js +136 -0
  576. package/src/internals/hooks/useSession.js +4 -0
  577. package/src/internals/hooks/useSession.test.js +8 -0
  578. package/src/internals/hooks/useThemeState.js +61 -0
  579. package/src/internals/hooks/useThemeState.test.js +66 -0
  580. package/src/internals/hooks/useUndoRedo.js +28 -0
  581. package/src/internals/hooks/useUndoRedo.test.js +64 -0
  582. package/src/internals/index.js +58 -0
  583. package/src/internals/story/ComponentSetPage.jsx +198 -0
  584. package/src/internals/story/ComponentSetPage.module.css +129 -0
  585. package/src/internals/story/StoryPage.jsx +147 -0
  586. package/src/internals/story/StoryPage.module.css +18 -0
  587. package/src/internals/test-utils.js +45 -0
  588. package/src/internals/vite/data-plugin.js +1508 -0
  589. package/src/internals/vite/data-plugin.test.js +1223 -0
  590. package/src/test-utils.js +44 -0
  591. package/toolbar.config.json +271 -0
  592. package/widgets.config.json +1537 -0
@@ -0,0 +1,237 @@
1
+ ---
2
+ name: ship
3
+ description: End-to-end feature shipping workflow — worktree, plan, implement, simplification review, adversarial review, and push to a remote branch.
4
+ metadata:
5
+ author: Daniel Fosco
6
+ version: "2026.4.15"
7
+ ---
8
+
9
+ # Ship Skill
10
+
11
+ > Triggered by: "ship", "ship this", "ship a feature", "ship it", "ship a change"
12
+ >
13
+ > **⚠️ This skill MUST be invoked whenever the user says "ship". Do NOT implement changes directly — always go through this workflow. Every step is mandatory and sequential.**
14
+
15
+ ## What This Does
16
+
17
+ Runs an end-to-end feature shipping workflow: creates a worktree, plans the feature, implements it, validates with an adversarial rubber-duck review, and pushes to a remote branch. All work happens in an isolated worktree — never on `main`.
18
+
19
+ ---
20
+
21
+ ## Parameters
22
+
23
+ No optional parameters.
24
+
25
+ ---
26
+
27
+ ## How to Execute
28
+
29
+ ### Step 1: Create a worktree
30
+
31
+ Invoke the **worktree** skill to create a git worktree for the feature branch.
32
+
33
+ - Derive a kebab-case branch name from the user's feature description (e.g., "add dark mode toggle" → `add-dark-mode-toggle`), appended to the version number of the base branch if applicable (e.g., `4.0.0` -> `4.0.0--add-dark-mode-toggle`).
34
+ - If the user provided an explicit branch name, use that instead.
35
+ - Use `ask_user` to confirm the branch name before creating the worktree.
36
+
37
+ After the worktree is created, all subsequent work happens inside `worktrees/<branch-name>` **at the repository root** (use `git rev-parse --show-toplevel` to find the root). Never create worktrees nested inside other worktrees.
38
+
39
+ ### Step 2: Plan the feature
40
+
41
+ Generate an implementation plan for the requested feature:
42
+
43
+ 1. Explore the codebase to understand the relevant areas.
44
+ 2. **Define clear goals** — extract 1–3 concrete, measurable goals from the user's request. Each goal should be a single sentence stating what the change achieves from the user's perspective. These goals are the contract — everything in the plan must serve at least one goal.
45
+ 3. Write a structured plan to `.github/plans/<branch-name>.md` (inside the worktree).
46
+ 4. The plan must include:
47
+ - **Goals** — the clear goals defined in step 2 above, numbered
48
+ - **Problem statement** — what the feature does and why
49
+ - **Approach** — high-level strategy
50
+ - **Files to change** — list of files to create, modify, or delete
51
+ - **Steps** — ordered implementation steps with enough detail to execute without referring back to the user's prompt
52
+ - **Edge cases & risks** — anything that could go wrong
53
+ 5. Present a summary of the plan to the user.
54
+ 6. Use `ask_user` to confirm:
55
+ > Does this plan look good? Should I proceed with implementation?
56
+
57
+ Do NOT proceed to Step 3 until the user confirms.
58
+
59
+ ### Step 3: Create clips goal/tasks
60
+
61
+ **If the `clips` skill is available** (check for `.clips/` directory or `clips` CLI), create tracking issues before implementation begins:
62
+
63
+ 1. Run `clips view` to check for a relevant existing goal.
64
+ 2. If a matching goal exists, create tasks under it for the planned work.
65
+ 3. If no matching goal exists, create a new goal with tasks derived from the plan.
66
+ 4. Save the goal ID and issue number for closure tracking in Step 10.
67
+
68
+ If clips is not available, skip this step silently.
69
+
70
+ ### Step 4: Implement and commit
71
+
72
+ Execute the plan:
73
+
74
+ 1. Implement the changes following the plan.
75
+ 2. Run existing linters and tests (`npm run lint`, `npm run build`, `npm run test`) to validate the changes.
76
+ 3. Fix any issues that arise.
77
+ 4. Stage and commit with a descriptive message:
78
+
79
+ ```bash
80
+ git add -A
81
+ git commit -m "<type>: <description>
82
+
83
+ <body if needed>
84
+
85
+ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
86
+ ```
87
+
88
+ Use conventional commit types (`feat`, `fix`, `refactor`, `docs`, `chore`, etc.).
89
+
90
+ ### Step 5: Write tests
91
+
92
+ **Invoke the `vitest` skill** to write tests for the implementation:
93
+
94
+ 1. Identify all new or changed logic that is testable (utilities, data transformations, hooks, state management, etc.).
95
+ 2. Write tests using Vitest, following existing test patterns in the codebase.
96
+ 3. Run `npm run test` to verify all tests pass (new and existing).
97
+ 4. Fix any failures.
98
+ 5. Stage and commit tests separately:
99
+
100
+ ```bash
101
+ git add -A
102
+ git commit -m "test: add tests for <feature>
103
+
104
+ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
105
+ ```
106
+
107
+ **Skip this step only if** the change is purely documentation, configuration, or markup with no testable logic.
108
+
109
+ ### Step 6: Adversarial rubber-duck review
110
+
111
+ Launch a single `rubber-duck` agent with an adversarial framing. Include the plan from Step 2, the diff of all changes (`git diff HEAD~1`), and the feature requirements from the user's original prompt.
112
+
113
+ **For each changed file**, check if architecture documentation exists at `.agents/architecture/path/to/file/filename.ext.md` and include it as context in the review prompt. This gives the reviewer the documented intent, invariants, and patterns for that file.
114
+
115
+ The prompt must include:
116
+
117
+ > You are an adversarial code reviewer. Your job is to BREAK this implementation. Assume nothing works correctly until proven otherwise. Specifically:
118
+ >
119
+ > 1. **Find bugs** — race conditions, off-by-one errors, null/undefined access, missing error handling
120
+ > 2. **Find security issues** — injection, XSS, data leaks, unsafe defaults
121
+ > 3. **Find logic errors** — incorrect assumptions, missing edge cases, broken invariants
122
+ > 4. **Find integration issues** — does this break existing behavior? Are imports/exports correct? Are types consistent?
123
+ > 5. **Find missing tests** — what scenarios are NOT covered?
124
+ >
125
+ > For each finding, rate severity as CRITICAL (must fix), HIGH (should fix), or LOW (nice to fix).
126
+ > Only report CRITICAL and HIGH findings. Ignore style, formatting, and naming.
127
+
128
+ #### Process findings
129
+
130
+ 1. Apply all CRITICAL fixes immediately.
131
+ 2. Apply HIGH fixes unless they significantly complicate the implementation without clear benefit.
132
+ 3. Discard LOW findings.
133
+ 4. If any changes were made, run lint/build/test again and commit:
134
+
135
+ ```bash
136
+ git add -A
137
+ git commit -m "fix: address review findings
138
+
139
+ <summary of what was fixed>
140
+
141
+ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
142
+ ```
143
+
144
+ 5. If no findings required changes, skip the commit.
145
+
146
+ #### Process findings
147
+
148
+ 1. For each SIGNIFICANT finding, evaluate whether the simplification still achieves all stated goals.
149
+ 2. Apply simplifications that clearly reduce complexity without sacrificing goals.
150
+ 3. Discard suggestions that would compromise a goal or introduce fragility.
151
+ 4. If any changes were made, run lint/build/test again and commit:
152
+
153
+ ```bash
154
+ git add -A
155
+ git commit -m "refactor: simplify <area>
156
+
157
+ <summary of what was simplified>
158
+
159
+ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
160
+ ```
161
+
162
+ 5. If no findings required changes, skip the commit.
163
+
164
+ ### Step 7: Update documentation
165
+
166
+ 1. **Invoke the `architecture-scanner` skill** to scan and update architecture docs for any files changed in this feature.
167
+ 2. Review and update `README.md`, `DOCS.md`, and any other relevant documentation files to reflect the changes made.
168
+ 3. If any docs were updated, stage and commit:
169
+
170
+ ```bash
171
+ git add -A
172
+ git commit -m "docs: update documentation for <feature>
173
+
174
+ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
175
+ ```
176
+
177
+ **Skip this step only if** the change is trivial (typo fix, config tweak) with no user-facing or architectural impact.
178
+
179
+ ### Step 8: Push to remote
180
+
181
+ ```bash
182
+ git push -u origin <branch-name>
183
+ ```
184
+
185
+ If the push fails due to permissions or remote issues, inform the user and suggest manual steps.
186
+
187
+ After pushing, inform the user: "Branch pushed to `origin/<branch-name>`."
188
+
189
+ ### Step 9: Close clips tasks
190
+
191
+ After the branch is pushed, mark clips tasks as closed:
192
+
193
+ 1. Run `clips view` to find the goal/tasks created in Step 3.
194
+ 2. Mark them as closed (`clips task status ... closed` / `clips goal status ... closed`).
195
+
196
+ If clips was skipped in Step 3, skip this step too.
197
+
198
+ ### Step 10: Start dev server
199
+
200
+ Run the dev server in the worktree so the user can immediately preview changes:
201
+
202
+ ```bash
203
+ npx storyboard dev
204
+ ```
205
+
206
+ This is the **only** place the dev server starts during a ship workflow — the worktree skill skips its own dev server step when called from ship.
207
+
208
+ ---
209
+
210
+ ## Rules
211
+
212
+ - **Always create a worktree first** — invoke the worktree skill as Step 1, before any exploration or implementation. Never commit to `main`. Never create a branch from `main` after the fact. The worktree IS the branch.
213
+ - **Never skip the reviews** — both the simplification review and the adversarial rubber-duck review are mandatory quality gates.
214
+ - **Always run lint/build/test** before committing — at minimum `npm run lint && npm run build && npm run test`.
215
+ - **Always use `ask_user`** for confirmations — branch name and plan approval.
216
+ - **Conventional commits** — use `feat:`, `fix:`, `refactor:`, `docs:`, `chore:` prefixes.
217
+ - **Co-authored-by trailer** — every commit must include the Copilot co-author trailer.
218
+ - **If any step fails**, stop and inform the user with the error and suggested next steps. Do not silently continue.
219
+ - **Context inference** — if the user's prompt already provides the branch name, feature description, or other details, skip the corresponding `ask_user` question and use the provided value directly.
220
+
221
+ ---
222
+
223
+ ## Example Usage
224
+
225
+ User says: "ship a feature to add canvas grid snapping"
226
+
227
+ 1. Creates worktree `1.2.0--canvas-grid-snapping`
228
+ 2. Plans the implementation with clear goals (explores codebase, writes plan)
229
+ 3. Creates clips goal + tasks for the work
230
+ 4. Implements grid snapping, commits
231
+ 5. Writes tests using vitest skill, commits
232
+ 6. Runs adversarial rubber-duck review, fixes findings, commits
233
+ 7. Runs adversarial simplification review, simplifies if needed, commits
234
+ 8. Updates architecture docs, README, DOCS as needed, commits
235
+ 9. Pushes `1.2.0--canvas-grid-snapping` to origin
236
+ 10. Marks clips tasks as closed
237
+ 11. Starts dev server (`npx storyboard dev`) in the worktree
@@ -0,0 +1,360 @@
1
+ ---
2
+ name: storyboard
3
+ description: Storyboard data structuring and management system. Use when creating flow data, setting up storyboard data, creating data objects, or structuring data for a prototype page.
4
+ metadata:
5
+ author: Daniel Fosco
6
+ version: "2026.3.09"
7
+ ---
8
+
9
+ # Storyboard
10
+
11
+ > Triggered by: when building a new page or route in storyboard, "create flow data", "set up storyboard data", "create data objects", "create new page", "create new route", when structuring data for a prototype page
12
+
13
+ ## What This Does
14
+
15
+ Guides the creation of data objects, flow files, and record collections for pages being built. Determines what data should be externalized into the Storyboard data system vs. hardcoded in the component.
16
+
17
+ ## Data File Types
18
+
19
+ Storyboard uses **suffix-based naming** for data files. Files can live anywhere in the repo — a Vite plugin discovers them automatically at dev/build time.
20
+
21
+ | Suffix | Purpose | Example |
22
+ |--------|---------|---------|
23
+ | `.flow.json` | Page data context | `default.flow.json` |
24
+ | `.object.json` | Reusable data fragment | `jane-doe.object.json` |
25
+ | `.record.json` | Parameterized collection (array with `id` per entry) | `posts.record.json` |
26
+
27
+ **Rules:**
28
+ - Every name+suffix must be unique across the entire repo (build fails on duplicates)
29
+ - Files can be organized into any subdirectory structure
30
+ - JSONC (comments) is supported — use `.jsonc` extension if preferred
31
+ - `$ref` and `$global` use **name-based** references (not paths): `{ "$ref": "jane-doe" }` finds `jane-doe.object.json` anywhere
32
+
33
+ ## When This Applies
34
+
35
+ - After the primer-builder skill has identified the page structure and components (Steps 1–3)
36
+ - Replaces the primer-builder's Step 4 (Plan Data) with a more structured approach
37
+ - When refactoring an existing page to use flow data
38
+ - When creating dynamic route pages with records
39
+
40
+ ## Navigation Anti-Pattern
41
+
42
+ **DO NOT use React Router's `<Link>` component for internal navigation.** Use plain `<a href="...">` tags instead.
43
+
44
+ The storyboard hash preserver intercepts `<a>` clicks to preserve URL hash params and handle client-side routing. React Router `<Link>` bypasses this by calling `navigate()` directly, which creates a duplicate browser history entry (one from `<Link>`, one from the hash preserver's click handler). This causes a "double back" bug where the user must press back twice to actually navigate back.
45
+
46
+ ```jsx
47
+ // ❌ BAD — creates double history entries
48
+ <Link to="/Overview">Overview</Link>
49
+
50
+ // ✅ GOOD — intercepted by hash preserver for client-side navigation
51
+ <a href="/Overview">Overview</a>
52
+ ```
53
+
54
+ ## The Core Rule: What Goes in Data vs. What's Hardcoded
55
+
56
+ ### Externalize as data objects
57
+
58
+ **Content and business model data** — anything that represents "what" the page displays:
59
+
60
+ - User profiles (name, avatar, bio, role)
61
+ - Repository / project metadata (name, description, language, stars, forks)
62
+ - Issue / PR items (title, state, author, labels, timestamps)
63
+ - Organization info (name, avatar, member count)
64
+ - Lists of entities (repos, issues, teams, packages, people)
65
+
66
+ **Navigation** — always externalize because it has repeated elements with many labels that benefit from easy bulk adjustment:
67
+
68
+ - Top navigation tabs (label, icon, counter, url, current state)
69
+ - Sidebar filter lists
70
+ - Settings section navigation
71
+ - Breadcrumb paths
72
+
73
+ **Important**: This will more usually be slotted in existing Template components from the repository, not generated code.
74
+
75
+ ### Hardcode in the component
76
+
77
+ **UI chrome and microcopy** — anything that describes "how" the page works:
78
+
79
+ - Button labels: `"New repository"`, `"Save changes"`, `"Cancel"`
80
+ - Placeholder text: `"Find a repository..."`
81
+ - Section headings that are structural: `"Pinned repositories"`, `"Activity"`
82
+ - Empty state messages: `"No results found"`
83
+ - Filter dropdown labels: `"Type"`, `"Language"`, `"Sort"`
84
+ - Dropdown option labels: `"All"`, `"Public"`, `"Private"`
85
+ - Static instructional text
86
+
87
+ ### Gray area — use judgment
88
+
89
+ - **Counters on tabs** — externalize if they represent real data counts; hardcode if decorative
90
+ - **Metadata labels** (e.g., "Updated 3 days ago") — externalize the date, hardcode the label format
91
+ - **Card/list item structure** — externalize the items array, hardcode the card template
92
+
93
+ ## Workflow
94
+
95
+ ### Step 1: Inventory the data needs
96
+
97
+ From the page description (primer-builder Step 1), list every piece of dynamic content:
98
+
99
+ ```
100
+ Navigation:
101
+ - topnav: 9 tabs with icons, labels, counters, active state
102
+ - sidenav: 10 filter options with active state
103
+
104
+ Content:
105
+ - org name, avatar
106
+ - 6 repository items, each with: name, description, language, stars, updated date
107
+ - filter query string
108
+ ```
109
+
110
+ ### Step 2: Design the data objects
111
+
112
+ Create one object file per logical entity:
113
+
114
+ | Data type | File name pattern | Example |
115
+ |-----------|------------------|---------|
116
+ | User/person | `{name}.object.json` | `jane-doe.object.json` |
117
+ | Navigation | `{context}-navigation.object.json` | `org-navigation.object.json` |
118
+ | Entity list | `{entity-plural}.object.json` | `repositories.object.json` |
119
+ | Org/team | `{org-name}.object.json` | `primer-org.object.json` |
120
+
121
+ **Object structure rules:**
122
+ - **The object file's top-level structure IS the value that `$ref` resolves to.** If the flow has `"repositories": { "$ref": "repositories" }`, the object file should be a bare array `[...]`, not `{ "repositories": [...] }` — otherwise the data double-nests as `repositories.repositories`.
123
+ - Same rule for single-entity objects: if the flow has `"user": { "$ref": "jane-doe" }`, the object file should contain the user fields directly at root (`{ "name": "Jane", ... }`), not wrapped in `{ "user": { "name": "Jane", ... } }`.
124
+ - Keep objects flat where possible — avoid deep nesting
125
+ - Use arrays for lists of items
126
+ - Include all fields that the UI needs — don't make the component compute derived data
127
+ - Use realistic placeholder data (real GitHub avatar URLs, plausible repo names, etc.)
128
+
129
+ ### Step 3: Compose the flow
130
+
131
+ Create a flow file that composes the objects:
132
+
133
+ ```json
134
+ // default.flow.json
135
+ {
136
+ "$global": ["org-navigation"],
137
+ "user": { "$ref": "jane-doe" },
138
+ "org": {
139
+ "name": "my-org",
140
+ "avatar": "https://avatars.githubusercontent.com/u/9919?v=4"
141
+ },
142
+ "repositories": { "$ref": "repositories" }
143
+ }
144
+ ```
145
+
146
+ **flow composition rules:**
147
+ - Use `$global` for navigation — it merges at the root level, making nav data available at the top
148
+ - Use `$ref` for entity objects — keeps them reusable across flows
149
+ - `$ref` and `$global` use **names**, not paths: `"jane-doe"` not `"../objects/jane-doe"`
150
+ - Inline small, flow-specific data directly (org name, settings, filter state)
151
+ - Name the flow after the page/flow: `org-repos.flow.json`, `issue-detail.flow.json`
152
+ - Rule of thumb: a flow can be named after its corresponding page
153
+
154
+ ### Step 4: Wire up the component
155
+
156
+ In the page component, use `useflowData()` with dot-notation paths:
157
+
158
+ ```jsx
159
+ import { useflowData, useflowLoading } from '../storyboard'
160
+
161
+ function ReposPage() {
162
+ const topnav = useflowData('topnav') // from $global navigation
163
+ const sidenav = useflowData('sidenav') // from $global navigation
164
+ const org = useflowData('org')
165
+ const repos = useflowData('repositories')
166
+ const loading = useflowLoading()
167
+
168
+ if (loading) return <Spinner />
169
+
170
+ return (
171
+ <Application title={org.name} topnav={topnav} sidenav={sidenav}>
172
+ {/* Hardcoded UI chrome */}
173
+ <h2>All repositories</h2>
174
+ <Button variant="primary">New repository</Button>
175
+ <TextInput placeholder="Find a repository..." />
176
+
177
+ {/* Data-driven content */}
178
+ {repos.map(repo => (
179
+ <article key={repo.name}>
180
+ <h3><a href={repo.url}>{repo.name}</a></h3>
181
+ <p>{repo.description}</p>
182
+ </article>
183
+ ))}
184
+ </Application>
185
+ )
186
+ }
187
+ ```
188
+
189
+ ## Records & Dynamic Routes
190
+
191
+ Records power **parameterized pages** — the same page template renders different content based on the URL.
192
+
193
+ ### Creating a record
194
+
195
+ A record file is a **collection** — an array of entries, each with a unique `id`:
196
+
197
+ ```json
198
+ // posts.record.json
199
+ [
200
+ {
201
+ "id": "welcome-to-storyboard",
202
+ "title": "Welcome to Storyboard",
203
+ "date": "2026-02-14",
204
+ "author": "Jane Doe",
205
+ "body": "..."
206
+ },
207
+ {
208
+ "id": "another-post",
209
+ "title": "Another Post",
210
+ "date": "2026-02-13",
211
+ "author": "Jane Doe",
212
+ "body": "..."
213
+ }
214
+ ]
215
+ ```
216
+
217
+ ### Creating a dynamic route page
218
+
219
+ The filename convention `[field].jsx` determines which record field the route matches against:
220
+
221
+ - `pages/issues/[id].jsx` → `useRecord('issues')` matches `entry.id`
222
+ - `pages/posts/[permalink].jsx` → `useRecord('posts', 'permalink')` matches `entry.permalink`
223
+
224
+ The second argument to `useRecord` defaults to `'id'`, so `useRecord('issues')` is equivalent to `useRecord('issues', 'id')`.
225
+
226
+ In the component, use `useRecord()`:
227
+
228
+ ```jsx
229
+ import { useRecord } from '../../storyboard'
230
+
231
+ function BlogPost() {
232
+ // 'posts' = record file name, 'id' = route param matched against entry.id
233
+ const post = useRecord('posts', 'id')
234
+ // URL /posts/welcome-to-storyboard → entry with id "welcome-to-storyboard"
235
+
236
+ if (!post) return <p>Post not found</p>
237
+ return <h1>{post.title}</h1>
238
+ }
239
+ ```
240
+
241
+ ### Listing all records
242
+
243
+ Use `useRecords()` for index/listing pages:
244
+
245
+ ```jsx
246
+ import { useRecords } from '../../storyboard'
247
+
248
+ function PostsIndex() {
249
+ const posts = useRecords('posts')
250
+ return posts.map(post => (
251
+ <a key={post.id} href={`/posts/${post.id}`}>{post.title}</a>
252
+ ))
253
+ }
254
+ ```
255
+
256
+ ### Records + flows
257
+
258
+ A page can use both a flow (for page-level data like navigation) and a record (for parameterized content). Pass `recordName` and `recordParam` to `StoryboardProvider` to merge record data under the `record` key:
259
+
260
+ ```jsx
261
+ <StoryboardProvider recordName="posts" recordParam="slug">
262
+ {/* useflowData('record.title') works here */}
263
+ </StoryboardProvider>
264
+ ```
265
+
266
+ ### No `useState` in pages or components
267
+
268
+ All state management must happen through storyboard hooks. Storyboard state lives in the URL hash — not in React component state.
269
+
270
+ **Use these hooks instead:**
271
+
272
+ | Hook | Purpose |
273
+ |------|---------|
274
+ | `useflowData(path?)` | Read flow data by dot-notation path |
275
+ | `useOverride(path)` | Read/write hash-param overrides on flow or object data. Works with or without `<StoryboardProvider>`. |
276
+ | `useObject(name, path?)` | Load an object data file directly by name, without a flow. Supports dot-notation path and hash overrides (`object.{name}.{field}`). |
277
+ | `useRecord(name, param?)` | Load a single record entry matched by URL param (defaults to `'id'`) |
278
+ | `useRecords(name)` | Load all entries from a record collection |
279
+ | `useflowLoading()` | Returns true while flow is loading |
280
+
281
+ **Why:** Storyboard is a prototyping framework where all data flows through the URL hash. This makes every state change shareable via URL, inspectable in the address bar, and framework-portable. Using `useState` breaks this contract — the state becomes invisible, unshareable, and tied to React.
282
+
283
+ ## Common Pitfall: Double-Nesting with `$ref`
284
+
285
+ The most frequent data bug is double-nesting. This happens when an object file wraps its data in a key that matches the flow's `$ref` key:
286
+
287
+ ```
288
+ // ❌ WRONG — causes double-nesting (advisory.advisory)
289
+
290
+ // flow: { "advisory": { "$ref": "advisory" } }
291
+ // advisory.object.json:
292
+ { "advisory": { "title": "Bug", "severity": "High" } }
293
+ // Result: flow.advisory = { "advisory": { "title": "Bug", ... } }
294
+
295
+ // ✅ CORRECT — object file is the raw value
296
+
297
+ // flow: { "advisory": { "$ref": "advisory" } }
298
+ // advisory.object.json:
299
+ { "title": "Bug", "severity": "High" }
300
+ // Result: flow.advisory = { "title": "Bug", "severity": "High" }
301
+ ```
302
+
303
+ **Rule of thumb:** The `$ref` key in the flow IS the namespace. The object file provides the value.
304
+
305
+ ## Hash Param Preservation (CRITICAL)
306
+
307
+ URL hash params are the foundation of the override system. They carry user-set and session-set values across navigations. **Never write code that drops them.**
308
+
309
+ ### How it works
310
+
311
+ `installHashPreserver(router)` in `src/index.jsx` patches both `<a>` click interception and `router.navigate()` so that hash params automatically carry forward on every navigation — including programmatic `navigate('/SomePage')` calls.
312
+
313
+ ### Rules
314
+
315
+ 1. **Never manually strip or omit the hash.** The global preserver handles it. Plain `navigate('/Page')` works — the hash carries forward automatically.
316
+ 2. **Never bypass the router.** Using `window.location.href = '/Page'` or `window.location.assign()` will drop the hash. Always use React Router's `navigate()` or `<Link>`.
317
+ 3. **If a page reads overrides, it must use the hooks.** `useflowData(path)` automatically merges hash overrides. `useOverride(path)` gives read/write access.
318
+ 4. **If a page writes overrides, downstream pages get them for free.** The Signup→Dashboard flow works because Signup writes via `useOverride`, navigation carries the hash, and Dashboard reads via `useflowData` — no manual plumbing needed.
319
+ 5. **To intentionally clear overrides**, use `clearValue` from `useOverride` or `removeParam` from `session.js`. Never clear by navigating without the hash.
320
+
321
+ ## Checklist
322
+
323
+ Before finishing data structuring, verify:
324
+
325
+ - [ ] **No double-nesting:** Object files referenced via `$ref` contain raw values, not wrapped in a key
326
+ - [ ] Every navigation array is in a data object (not hardcoded in the component)
327
+ - [ ] Every list of content items is in a data object
328
+ - [ ] User/org profile data is in a data object
329
+ - [ ] Button labels, placeholder text, and section headings are hardcoded
330
+ - [ ] The flow file uses `$global` for navigation and `$ref` for entities
331
+ - [ ] `$ref` and `$global` use **names** (not relative paths)
332
+ - [ ] Data files use the correct suffix: `.flow.json`, `.object.json`, `.record.json`
333
+ - [ ] The component uses `useflowData()` for all externalized data
334
+ - [ ] Shared data objects use `useObject()` when not part of a flow
335
+ - [ ] Dynamic route pages use `useRecord()` for parameterized content
336
+ - [ ] Data objects use realistic placeholder values
337
+ - [ ] The flow name matches the page name or flow
338
+ - [ ] **Hash params are never dropped** — see "Hash Param Preservation" above
339
+
340
+ ## Final Step: Provide the URL
341
+
342
+ After creating the flow and wiring up the component, **always provide the full dev URL** so the user can immediately preview the page.
343
+
344
+ **Page-flow matching:** If the flow file name matches the page file name exactly (e.g. `Repositories.flow.json` for `pages/Repositories.jsx`), the flow loads automatically — no `?flow=` param needed:
345
+
346
+ ```
347
+ http://localhost:1234/Repositories
348
+ ```
349
+
350
+ If the flow name differs from the page name, add the `?flow=` parameter:
351
+
352
+ ```
353
+ http://localhost:1234/Repositories?flow=heron-silver
354
+ ```
355
+
356
+ For dynamic routes, use the record entry's `id` as the URL slug:
357
+
358
+ ```
359
+ http://localhost:1234/posts/welcome-to-storyboard
360
+ ```
@@ -0,0 +1,16 @@
1
+ # Update Storyboard Packages
2
+
3
+ Updates all `@dfosco/storyboard-*` packages together to the same version and runs the scaffold sync.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ npm run update # Update to latest stable
9
+ npm run update:beta # Update to latest beta
10
+ npm run update:alpha # Update to latest alpha
11
+ ```
12
+
13
+ ## What it does
14
+
15
+ 1. Updates all `@dfosco/storyboard-*` packages to the specified tag
16
+ 2. Runs `npx storyboard-scaffold` to sync skills and scripts from the latest version
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+ # Update all @dfosco/storyboard-* packages and sync scaffold files.
3
+ # Run from storyboard client root: npm run update
4
+ set -euo pipefail
5
+
6
+ TAG="${1:-latest}"
7
+
8
+ PACKAGES=(
9
+ "@dfosco/storyboard-core"
10
+ "@dfosco/storyboard-react"
11
+ "@dfosco/storyboard-react-primer"
12
+ "@dfosco/storyboard-react-reshaped"
13
+ "@dfosco/tiny-canvas"
14
+ )
15
+
16
+ echo "Updating @dfosco/* packages to @${TAG}..."
17
+ for pkg in "${PACKAGES[@]}"; do
18
+ npm install "${pkg}@${TAG}" --save
19
+ done
20
+
21
+ echo ""
22
+ echo "Running scaffold sync..."
23
+ npx storyboard-scaffold
24
+
25
+ echo ""
26
+ echo "✔ All packages updated to @${TAG} and scaffold synced."
@@ -0,0 +1,5 @@
1
+ # Generation Info
2
+
3
+ - **Source:** `sources/vitest`
4
+ - **Git SHA:** `4a7321e10672f00f0bb698823a381c2cc245b8f7`
5
+ - **Generated:** 2026-01-28