@dfosco/storyboard-core 4.2.0-beta.2 → 4.2.0-beta.21

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 (414) hide show
  1. package/commandpalette.config.json +109 -24
  2. package/dist/storyboard-ui.css +1 -1
  3. package/dist/storyboard-ui.js +17379 -28568
  4. package/dist/storyboard-ui.js.map +1 -1
  5. package/dist/tailwind.css +1 -1
  6. package/package.json +5 -2
  7. package/scaffold/agents/prompt-agent.agent.md +181 -0
  8. package/scaffold/agents/terminal-agent.agent.md +351 -0
  9. package/scaffold/codex/config.toml +246 -0
  10. package/scaffold/manifest.json +5 -0
  11. package/scaffold/skills/canvas/SKILL.md +5 -4
  12. package/scaffold/skills/ship/SKILL.md +1 -1
  13. package/scaffold/storyboard.config.json +14 -1
  14. package/scaffold/toolbar.config.json +1 -1
  15. package/src/ActionMenuButton.jsx +100 -0
  16. package/src/AutosyncMenuButton.css +67 -0
  17. package/src/AutosyncMenuButton.jsx +241 -0
  18. package/src/BranchSelect.jsx +29 -0
  19. package/src/BranchSelect.module.css +30 -0
  20. package/src/CanvasAgentsMenu.jsx +87 -0
  21. package/src/CanvasCreateMenu.jsx +609 -0
  22. package/src/CanvasSnap.css +27 -0
  23. package/src/CanvasSnap.jsx +51 -0
  24. package/src/CanvasUndoRedo.css +36 -0
  25. package/src/CanvasUndoRedo.jsx +62 -0
  26. package/src/CanvasZoomControl.css +53 -0
  27. package/src/CanvasZoomControl.jsx +49 -0
  28. package/src/CanvasZoomToFit.css +18 -0
  29. package/src/CanvasZoomToFit.jsx +26 -0
  30. package/src/CommandMenu.css +8 -0
  31. package/src/CommandMenu.jsx +286 -0
  32. package/src/CommandPalette.jsx +35 -0
  33. package/src/CommandPaletteTrigger.jsx +25 -0
  34. package/src/CommentsMenuButton.jsx +38 -0
  35. package/src/CoreUIBar.css +47 -0
  36. package/src/CoreUIBar.jsx +855 -0
  37. package/src/CreateMenuButton.jsx +116 -0
  38. package/src/HideChromeTrigger.jsx +40 -0
  39. package/src/InspectorPanel.css +109 -0
  40. package/src/InspectorPanel.jsx +629 -0
  41. package/src/PwaInstallBanner.css +42 -0
  42. package/src/PwaInstallBanner.jsx +124 -0
  43. package/src/SidePanel.jsx +260 -0
  44. package/src/ThemeMenuButton.jsx +136 -0
  45. package/src/autosync/server.js +202 -5
  46. package/src/autosync/server.test.js +112 -0
  47. package/src/canvas/__tests__/agent-integration.test.js +593 -0
  48. package/src/canvas/__tests__/helpers/browser.js +95 -0
  49. package/src/canvas/__tests__/helpers/canvas-api.js +129 -0
  50. package/src/canvas/__tests__/helpers/perf.js +118 -0
  51. package/src/canvas/__tests__/helpers/setup.js +176 -0
  52. package/src/canvas/__tests__/helpers/tmux.js +130 -0
  53. package/src/canvas/__tests__/helpers/transcript.js +129 -0
  54. package/src/canvas/__tests__/terminal-integration.test.js +175 -0
  55. package/src/canvas/hot-pool.js +757 -0
  56. package/src/canvas/materializer.js +31 -0
  57. package/src/canvas/materializer.test.js +56 -0
  58. package/src/canvas/selectedWidgets.js +65 -7
  59. package/src/canvas/server.js +1801 -22
  60. package/src/canvas/server.test.js +239 -0
  61. package/src/canvas/terminal-config.js +331 -0
  62. package/src/canvas/terminal-registry.js +38 -0
  63. package/src/canvas/terminal-server.js +1037 -29
  64. package/src/canvas/writeGuard.js +51 -3
  65. package/src/canvasConfig.js +67 -1
  66. package/src/canvasConfig.test.js +79 -1
  67. package/src/cli/agent.js +85 -0
  68. package/src/cli/branch.js +232 -0
  69. package/src/cli/canvasAdd.js +59 -12
  70. package/src/cli/canvasBatch.js +98 -0
  71. package/src/cli/canvasBounds.js +1 -1
  72. package/src/cli/canvasRead.js +1 -1
  73. package/src/cli/canvasUpdate.js +179 -0
  74. package/src/cli/create.js +38 -14
  75. package/src/cli/dev.js +157 -83
  76. package/src/cli/exit.js +23 -24
  77. package/src/cli/index.js +55 -2
  78. package/src/cli/proxy.js +96 -37
  79. package/src/cli/schemas.js +22 -4
  80. package/src/cli/server.js +148 -25
  81. package/src/cli/serverUrl.js +8 -3
  82. package/src/cli/sessions.js +131 -5
  83. package/src/cli/setup.js +109 -11
  84. package/src/cli/terminal-commands.js +16 -8
  85. package/src/cli/terminal-messaging.js +231 -0
  86. package/src/cli/terminal-welcome.js +365 -33
  87. package/src/commandActions.js +1 -0
  88. package/src/commandPaletteConfig.js +9 -0
  89. package/src/comments/auth.js +2 -1
  90. package/src/comments/ui/AuthModal.jsx +114 -0
  91. package/src/comments/ui/CommentWindow.jsx +329 -0
  92. package/src/comments/ui/CommentsDrawer.jsx +102 -0
  93. package/src/comments/ui/Composer.jsx +64 -0
  94. package/src/comments/ui/authModal.test.js +1 -1
  95. package/src/comments/ui/commentWindow.js +16 -17
  96. package/src/comments/ui/commentsDrawer.js +25 -26
  97. package/src/comments/ui/composer.js +23 -24
  98. package/src/comments/ui/index.js +2 -3
  99. package/src/configSchema.js +59 -1
  100. package/src/configStore.js +161 -0
  101. package/src/core-ui-colors.css +12 -0
  102. package/src/devtools.js +17 -19
  103. package/src/devtools.test.js +18 -9
  104. package/src/featureFlags.js +12 -5
  105. package/src/fuzzySearch.test.js +10 -0
  106. package/src/index.js +14 -2
  107. package/src/lib/components/ui/alert/alert-action.jsx +11 -0
  108. package/src/lib/components/ui/alert/alert-description.jsx +11 -0
  109. package/src/lib/components/ui/alert/alert-title.jsx +11 -0
  110. package/src/lib/components/ui/alert/alert.jsx +25 -0
  111. package/src/lib/components/ui/alert/index.js +15 -15
  112. package/src/lib/components/ui/avatar/avatar-badge.jsx +22 -0
  113. package/src/lib/components/ui/avatar/avatar-fallback.jsx +18 -0
  114. package/src/lib/components/ui/avatar/avatar-group-count.jsx +19 -0
  115. package/src/lib/components/ui/avatar/avatar-group.jsx +19 -0
  116. package/src/lib/components/ui/avatar/avatar-image.jsx +15 -0
  117. package/src/lib/components/ui/avatar/avatar.jsx +19 -0
  118. package/src/lib/components/ui/avatar/index.js +20 -20
  119. package/src/lib/components/ui/badge/badge.jsx +31 -0
  120. package/src/lib/components/ui/badge/index.js +2 -2
  121. package/src/lib/components/ui/button/button.jsx +100 -0
  122. package/src/lib/components/ui/button/index.js +9 -9
  123. package/src/lib/components/ui/card/card-action.jsx +11 -0
  124. package/src/lib/components/ui/card/card-content.jsx +11 -0
  125. package/src/lib/components/ui/card/card-description.jsx +11 -0
  126. package/src/lib/components/ui/card/card-footer.jsx +11 -0
  127. package/src/lib/components/ui/card/card-header.jsx +19 -0
  128. package/src/lib/components/ui/card/card-title.jsx +11 -0
  129. package/src/lib/components/ui/card/card.jsx +17 -0
  130. package/src/lib/components/ui/card/index.js +23 -23
  131. package/src/lib/components/ui/checkbox/checkbox.jsx +29 -0
  132. package/src/lib/components/ui/checkbox/index.js +5 -5
  133. package/src/lib/components/ui/collapsible/collapsible-content.jsx +7 -0
  134. package/src/lib/components/ui/collapsible/collapsible-trigger.jsx +7 -0
  135. package/src/lib/components/ui/collapsible/collapsible.jsx +7 -0
  136. package/src/lib/components/ui/collapsible/index.js +11 -11
  137. package/src/lib/components/ui/dialog/dialog-close.jsx +7 -0
  138. package/src/lib/components/ui/dialog/dialog-content.jsx +34 -0
  139. package/src/lib/components/ui/dialog/dialog-description.jsx +15 -0
  140. package/src/lib/components/ui/dialog/dialog-footer.jsx +23 -0
  141. package/src/lib/components/ui/dialog/dialog-header.jsx +11 -0
  142. package/src/lib/components/ui/dialog/dialog-overlay.jsx +15 -0
  143. package/src/lib/components/ui/dialog/dialog-portal.jsx +4 -0
  144. package/src/lib/components/ui/dialog/dialog-title.jsx +15 -0
  145. package/src/lib/components/ui/dialog/dialog-trigger.jsx +7 -0
  146. package/src/lib/components/ui/dialog/dialog.jsx +4 -0
  147. package/src/lib/components/ui/dialog/index.js +32 -32
  148. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +8 -0
  149. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +30 -0
  150. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +22 -0
  151. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +16 -0
  152. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +7 -0
  153. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +20 -0
  154. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.jsx +17 -0
  155. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +4 -0
  156. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +7 -0
  157. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +29 -0
  158. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +15 -0
  159. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.jsx +16 -0
  160. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +15 -0
  161. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +23 -0
  162. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +4 -0
  163. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +7 -0
  164. package/src/lib/components/ui/dropdown-menu/dropdown-menu.jsx +4 -0
  165. package/src/lib/components/ui/dropdown-menu/index.js +52 -52
  166. package/src/lib/components/ui/input/index.js +5 -5
  167. package/src/lib/components/ui/input/input.jsx +19 -0
  168. package/src/lib/components/ui/label/index.js +5 -5
  169. package/src/lib/components/ui/label/label.jsx +19 -0
  170. package/src/lib/components/ui/panel/index.js +21 -21
  171. package/src/lib/components/ui/panel/panel-body.jsx +11 -0
  172. package/src/lib/components/ui/panel/panel-close.jsx +16 -0
  173. package/src/lib/components/ui/panel/panel-content.jsx +29 -0
  174. package/src/lib/components/ui/panel/panel-footer.jsx +11 -0
  175. package/src/lib/components/ui/panel/panel-header.jsx +11 -0
  176. package/src/lib/components/ui/panel/panel-title.jsx +12 -0
  177. package/src/lib/components/ui/panel/panel.jsx +4 -0
  178. package/src/lib/components/ui/popover/index.js +26 -26
  179. package/src/lib/components/ui/popover/popover-close.jsx +7 -0
  180. package/src/lib/components/ui/popover/popover-content.jsx +22 -0
  181. package/src/lib/components/ui/popover/popover-description.jsx +11 -0
  182. package/src/lib/components/ui/popover/popover-header.jsx +11 -0
  183. package/src/lib/components/ui/popover/popover-portal.jsx +4 -0
  184. package/src/lib/components/ui/popover/popover-title.jsx +11 -0
  185. package/src/lib/components/ui/popover/popover-trigger.jsx +8 -0
  186. package/src/lib/components/ui/popover/popover.jsx +4 -0
  187. package/src/lib/components/ui/searchable-list.jsx +159 -0
  188. package/src/lib/components/ui/select/index.js +35 -35
  189. package/src/lib/components/ui/select/select-content.jsx +30 -0
  190. package/src/lib/components/ui/select/select-group-heading.jsx +17 -0
  191. package/src/lib/components/ui/select/select-group.jsx +15 -0
  192. package/src/lib/components/ui/select/select-item.jsx +26 -0
  193. package/src/lib/components/ui/select/select-label.jsx +11 -0
  194. package/src/lib/components/ui/select/select-portal.jsx +4 -0
  195. package/src/lib/components/ui/select/select-scroll-down-button.jsx +18 -0
  196. package/src/lib/components/ui/select/select-scroll-up-button.jsx +18 -0
  197. package/src/lib/components/ui/select/select-separator.jsx +15 -0
  198. package/src/lib/components/ui/select/select-trigger.jsx +25 -0
  199. package/src/lib/components/ui/select/select.jsx +4 -0
  200. package/src/lib/components/ui/separator/index.js +5 -5
  201. package/src/lib/components/ui/separator/separator.jsx +22 -0
  202. package/src/lib/components/ui/sheet/index.js +32 -32
  203. package/src/lib/components/ui/sheet/sheet-close.jsx +7 -0
  204. package/src/lib/components/ui/sheet/sheet-content.jsx +35 -0
  205. package/src/lib/components/ui/sheet/sheet-description.jsx +15 -0
  206. package/src/lib/components/ui/sheet/sheet-footer.jsx +11 -0
  207. package/src/lib/components/ui/sheet/sheet-header.jsx +11 -0
  208. package/src/lib/components/ui/sheet/sheet-overlay.jsx +15 -0
  209. package/src/lib/components/ui/sheet/sheet-portal.jsx +4 -0
  210. package/src/lib/components/ui/sheet/sheet-title.jsx +15 -0
  211. package/src/lib/components/ui/sheet/sheet-trigger.jsx +7 -0
  212. package/src/lib/components/ui/sheet/sheet.jsx +4 -0
  213. package/src/lib/components/ui/textarea/index.js +5 -5
  214. package/src/lib/components/ui/textarea/textarea.jsx +18 -0
  215. package/src/lib/components/ui/toggle/index.js +6 -9
  216. package/src/lib/components/ui/toggle/toggle.jsx +36 -0
  217. package/src/lib/components/ui/toggle-group/index.js +8 -8
  218. package/src/lib/components/ui/toggle-group/toggle-group-item.jsx +29 -0
  219. package/src/lib/components/ui/toggle-group/toggle-group.jsx +43 -0
  220. package/src/lib/components/ui/tooltip/index.js +3 -3
  221. package/src/lib/components/ui/tooltip/tooltip-content.jsx +21 -0
  222. package/src/lib/components/ui/tooltip/tooltip-trigger.jsx +23 -0
  223. package/src/lib/components/ui/tooltip/tooltip.jsx +11 -0
  224. package/src/lib/components/ui/trigger-button/index.js +3 -3
  225. package/src/lib/components/ui/trigger-button/trigger-button.css +38 -0
  226. package/src/lib/components/ui/trigger-button/trigger-button.jsx +63 -0
  227. package/src/logger/devLogger.js +238 -0
  228. package/src/logger/devLogger.test.js +193 -0
  229. package/src/modes.test.js +4 -4
  230. package/src/mountStoryboardCore.js +123 -27
  231. package/src/paletteProviders.js +3 -0
  232. package/src/paletteProviders.test.js +2 -2
  233. package/src/server/index.js +98 -36
  234. package/src/sidepanel.css +214 -0
  235. package/src/styles/tailwind.css +1 -1
  236. package/src/svelte-plugin-ui/__tests__/ModeSwitch.test.ts +8 -8
  237. package/src/svelte-plugin-ui/__tests__/ToolbarShell.test.ts +11 -10
  238. package/src/svelte-plugin-ui/components/Icon.css +11 -0
  239. package/src/svelte-plugin-ui/components/Icon.jsx +281 -0
  240. package/src/svelte-plugin-ui/components/ModeSwitch.css +90 -0
  241. package/src/svelte-plugin-ui/components/ModeSwitch.jsx +47 -0
  242. package/src/svelte-plugin-ui/components/ToolbarShell.css +80 -0
  243. package/src/svelte-plugin-ui/components/ToolbarShell.jsx +84 -0
  244. package/src/svelte-plugin-ui/components/Viewfinder.css +412 -0
  245. package/src/svelte-plugin-ui/components/Viewfinder.jsx +512 -0
  246. package/src/svelte-plugin-ui/mount.ts +12 -16
  247. package/src/toolRegistry.js +4 -4
  248. package/src/toolbarConfigStore.js +30 -0
  249. package/src/tools/handlers/autosync.js +1 -1
  250. package/src/tools/handlers/canvasAddWidget.js +1 -1
  251. package/src/tools/handlers/canvasAgents.js +19 -0
  252. package/src/tools/handlers/canvasToolbar.js +8 -8
  253. package/src/tools/handlers/commandPalette.js +9 -0
  254. package/src/tools/handlers/comments.js +1 -1
  255. package/src/tools/handlers/create.js +1 -1
  256. package/src/tools/handlers/devtools.js +16 -0
  257. package/src/tools/handlers/devtools.test.js +38 -0
  258. package/src/tools/handlers/flows.js +1 -1
  259. package/src/tools/handlers/hideChrome.js +9 -0
  260. package/src/tools/handlers/paletteTheme.js +35 -0
  261. package/src/tools/handlers/theme.js +1 -1
  262. package/src/tools/registry.js +4 -1
  263. package/src/tools/surfaces/commandList.js +3 -3
  264. package/src/tools/surfaces/mainToolbar.js +3 -3
  265. package/src/tools/surfaces/registry.js +4 -4
  266. package/src/ui/design-modes.ts +2 -2
  267. package/src/ui/viewfinder.ts +1 -1
  268. package/src/vite/server-plugin.js +242 -60
  269. package/src/workshop/features/createCanvas/CreateCanvasForm.jsx +260 -0
  270. package/src/workshop/features/createCanvas/index.js +1 -1
  271. package/src/workshop/features/createFlow/CreateFlowForm.jsx +334 -0
  272. package/src/workshop/features/createFlow/index.js +1 -1
  273. package/src/workshop/features/createPage/CreatePageForm.jsx +304 -0
  274. package/src/workshop/features/createPage/index.js +1 -1
  275. package/src/workshop/features/createPrototype/CreatePrototypeForm.jsx +289 -0
  276. package/src/workshop/features/createPrototype/index.js +1 -1
  277. package/src/workshop/features/createPrototype/server.js +98 -0
  278. package/src/workshop/features/createStory/CreateStoryForm.jsx +208 -0
  279. package/src/workshop/features/createStory/index.js +1 -1
  280. package/src/workshop/ui/WorkshopPanel.jsx +98 -0
  281. package/src/workshop/ui/mount.ts +1 -1
  282. package/src/worktree/port.js +48 -0
  283. package/src/worktree/serverRegistry.js +120 -0
  284. package/toolbar.config.json +93 -42
  285. package/widgets.config.json +580 -12
  286. package/src/ActionMenuButton.svelte +0 -119
  287. package/src/AutosyncMenuButton.svelte +0 -397
  288. package/src/CanvasCreateMenu.svelte +0 -295
  289. package/src/CanvasSnap.svelte +0 -87
  290. package/src/CanvasUndoRedo.svelte +0 -108
  291. package/src/CanvasZoomControl.svelte +0 -111
  292. package/src/CanvasZoomToFit.svelte +0 -52
  293. package/src/CommandMenu.svelte +0 -249
  294. package/src/CommandPalette.svelte +0 -33
  295. package/src/CommentsMenuButton.svelte +0 -53
  296. package/src/CoreUIBar.svelte +0 -847
  297. package/src/CreateMenuButton.svelte +0 -133
  298. package/src/DocPanel.svelte +0 -299
  299. package/src/InspectorPanel.svelte +0 -745
  300. package/src/PwaInstallBanner.svelte +0 -124
  301. package/src/SidePanel.svelte +0 -480
  302. package/src/ThemeMenuButton.svelte +0 -132
  303. package/src/comments/ui/AuthModal.svelte +0 -108
  304. package/src/comments/ui/CommentWindow.svelte +0 -333
  305. package/src/comments/ui/CommentsDrawer.svelte +0 -96
  306. package/src/comments/ui/Composer.svelte +0 -65
  307. package/src/lib/components/ui/alert/alert-action.svelte +0 -19
  308. package/src/lib/components/ui/alert/alert-description.svelte +0 -22
  309. package/src/lib/components/ui/alert/alert-title.svelte +0 -22
  310. package/src/lib/components/ui/alert/alert.svelte +0 -38
  311. package/src/lib/components/ui/avatar/avatar-badge.svelte +0 -25
  312. package/src/lib/components/ui/avatar/avatar-fallback.svelte +0 -20
  313. package/src/lib/components/ui/avatar/avatar-group-count.svelte +0 -22
  314. package/src/lib/components/ui/avatar/avatar-group.svelte +0 -22
  315. package/src/lib/components/ui/avatar/avatar-image.svelte +0 -17
  316. package/src/lib/components/ui/avatar/avatar.svelte +0 -24
  317. package/src/lib/components/ui/badge/badge.svelte +0 -44
  318. package/src/lib/components/ui/button/button.svelte +0 -108
  319. package/src/lib/components/ui/card/card-action.svelte +0 -21
  320. package/src/lib/components/ui/card/card-content.svelte +0 -19
  321. package/src/lib/components/ui/card/card-description.svelte +0 -19
  322. package/src/lib/components/ui/card/card-footer.svelte +0 -18
  323. package/src/lib/components/ui/card/card-header.svelte +0 -21
  324. package/src/lib/components/ui/card/card-title.svelte +0 -14
  325. package/src/lib/components/ui/card/card.svelte +0 -21
  326. package/src/lib/components/ui/checkbox/checkbox.svelte +0 -39
  327. package/src/lib/components/ui/collapsible/collapsible-content.svelte +0 -7
  328. package/src/lib/components/ui/collapsible/collapsible-trigger.svelte +0 -7
  329. package/src/lib/components/ui/collapsible/collapsible.svelte +0 -11
  330. package/src/lib/components/ui/dialog/dialog-close.svelte +0 -11
  331. package/src/lib/components/ui/dialog/dialog-content.svelte +0 -42
  332. package/src/lib/components/ui/dialog/dialog-description.svelte +0 -17
  333. package/src/lib/components/ui/dialog/dialog-footer.svelte +0 -29
  334. package/src/lib/components/ui/dialog/dialog-header.svelte +0 -19
  335. package/src/lib/components/ui/dialog/dialog-overlay.svelte +0 -17
  336. package/src/lib/components/ui/dialog/dialog-portal.svelte +0 -7
  337. package/src/lib/components/ui/dialog/dialog-title.svelte +0 -17
  338. package/src/lib/components/ui/dialog/dialog-trigger.svelte +0 -11
  339. package/src/lib/components/ui/dialog/dialog.svelte +0 -7
  340. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +0 -16
  341. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -40
  342. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +0 -27
  343. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +0 -18
  344. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte +0 -7
  345. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte +0 -24
  346. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte +0 -20
  347. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte +0 -7
  348. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +0 -16
  349. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +0 -34
  350. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte +0 -17
  351. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +0 -19
  352. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +0 -17
  353. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +0 -27
  354. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte +0 -7
  355. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +0 -7
  356. package/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte +0 -7
  357. package/src/lib/components/ui/input/input.svelte +0 -40
  358. package/src/lib/components/ui/label/label.svelte +0 -20
  359. package/src/lib/components/ui/panel/panel-body.svelte +0 -13
  360. package/src/lib/components/ui/panel/panel-close.svelte +0 -16
  361. package/src/lib/components/ui/panel/panel-content.svelte +0 -33
  362. package/src/lib/components/ui/panel/panel-footer.svelte +0 -13
  363. package/src/lib/components/ui/panel/panel-header.svelte +0 -16
  364. package/src/lib/components/ui/panel/panel-title.svelte +0 -14
  365. package/src/lib/components/ui/panel/panel.svelte +0 -15
  366. package/src/lib/components/ui/popover/popover-close.svelte +0 -7
  367. package/src/lib/components/ui/popover/popover-content.svelte +0 -27
  368. package/src/lib/components/ui/popover/popover-description.svelte +0 -19
  369. package/src/lib/components/ui/popover/popover-header.svelte +0 -19
  370. package/src/lib/components/ui/popover/popover-portal.svelte +0 -7
  371. package/src/lib/components/ui/popover/popover-title.svelte +0 -19
  372. package/src/lib/components/ui/popover/popover-trigger.svelte +0 -17
  373. package/src/lib/components/ui/popover/popover.svelte +0 -7
  374. package/src/lib/components/ui/select/select-content.svelte +0 -40
  375. package/src/lib/components/ui/select/select-group-heading.svelte +0 -19
  376. package/src/lib/components/ui/select/select-group.svelte +0 -17
  377. package/src/lib/components/ui/select/select-item.svelte +0 -38
  378. package/src/lib/components/ui/select/select-label.svelte +0 -18
  379. package/src/lib/components/ui/select/select-portal.svelte +0 -7
  380. package/src/lib/components/ui/select/select-scroll-down-button.svelte +0 -20
  381. package/src/lib/components/ui/select/select-scroll-up-button.svelte +0 -20
  382. package/src/lib/components/ui/select/select-separator.svelte +0 -17
  383. package/src/lib/components/ui/select/select-trigger.svelte +0 -27
  384. package/src/lib/components/ui/select/select.svelte +0 -11
  385. package/src/lib/components/ui/separator/separator.svelte +0 -23
  386. package/src/lib/components/ui/sheet/sheet-close.svelte +0 -7
  387. package/src/lib/components/ui/sheet/sheet-content.svelte +0 -43
  388. package/src/lib/components/ui/sheet/sheet-description.svelte +0 -17
  389. package/src/lib/components/ui/sheet/sheet-footer.svelte +0 -18
  390. package/src/lib/components/ui/sheet/sheet-header.svelte +0 -19
  391. package/src/lib/components/ui/sheet/sheet-overlay.svelte +0 -17
  392. package/src/lib/components/ui/sheet/sheet-portal.svelte +0 -7
  393. package/src/lib/components/ui/sheet/sheet-title.svelte +0 -17
  394. package/src/lib/components/ui/sheet/sheet-trigger.svelte +0 -7
  395. package/src/lib/components/ui/sheet/sheet.svelte +0 -7
  396. package/src/lib/components/ui/textarea/textarea.svelte +0 -21
  397. package/src/lib/components/ui/toggle/toggle.svelte +0 -45
  398. package/src/lib/components/ui/toggle-group/toggle-group-item.svelte +0 -35
  399. package/src/lib/components/ui/toggle-group/toggle-group.svelte +0 -63
  400. package/src/lib/components/ui/tooltip/tooltip-content.svelte +0 -24
  401. package/src/lib/components/ui/tooltip/tooltip-trigger.svelte +0 -27
  402. package/src/lib/components/ui/tooltip/tooltip.svelte +0 -9
  403. package/src/lib/components/ui/trigger-button/trigger-button.svelte +0 -106
  404. package/src/svelte-plugin-ui/components/Icon.svelte +0 -181
  405. package/src/svelte-plugin-ui/components/ModeSwitch.svelte +0 -121
  406. package/src/svelte-plugin-ui/components/ToolbarShell.svelte +0 -150
  407. package/src/svelte-plugin-ui/components/Viewfinder.svelte +0 -1001
  408. package/src/tools/handlers/docs.js +0 -11
  409. package/src/workshop/features/createCanvas/CreateCanvasForm.svelte +0 -139
  410. package/src/workshop/features/createFlow/CreateFlowForm.svelte +0 -314
  411. package/src/workshop/features/createPage/CreatePageForm.svelte +0 -249
  412. package/src/workshop/features/createPrototype/CreatePrototypeForm.svelte +0 -287
  413. package/src/workshop/features/createStory/CreateStoryForm.svelte +0 -161
  414. package/src/workshop/ui/WorkshopPanel.svelte +0 -97
@@ -0,0 +1,63 @@
1
+ import './trigger-button.css';
2
+ import { useMemo, forwardRef } from "react";
3
+ import { cn } from "../../../utils/index.js";
4
+ import { registerSmoothCorners } from '../../../../smoothCorners.js';
5
+ import { Button } from '../../../components/ui/button/index.js';
6
+
7
+ registerSmoothCorners();
8
+
9
+ const TriggerButton = forwardRef(function TriggerButton({
10
+ className,
11
+ wrapperClass = "",
12
+ active = false,
13
+ inactive = false,
14
+ dimmed = false,
15
+ localOnly = false,
16
+ size = "icon-2xl",
17
+ children,
18
+ // Separate Radix trigger props from button props
19
+ 'aria-expanded': ariaExpanded,
20
+ 'data-state': dataState,
21
+ 'aria-haspopup': ariaHaspopup,
22
+ ...props
23
+ }, ref) {
24
+ const borderWidth = useMemo(
25
+ () => ['icon-2xl', 'icon-xl', '2xl', 'xl'].includes(size) ? '3px' : '2px',
26
+ [size]
27
+ );
28
+
29
+ return (
30
+ <span
31
+ ref={ref}
32
+ data-trigger-button=""
33
+ data-active={active || undefined}
34
+ data-inactive={inactive || undefined}
35
+ data-dimmed={dimmed || undefined}
36
+ data-local-only={localOnly || undefined}
37
+ style={{ '--sb--trigger-border-width': borderWidth }}
38
+ aria-expanded={ariaExpanded}
39
+ data-state={dataState}
40
+ aria-haspopup={ariaHaspopup}
41
+ >
42
+ <Button
43
+ variant="trigger"
44
+ size={size}
45
+ disabled={inactive}
46
+ wrapperClass={cn(
47
+ "smooth-corners [--sb--smooth-corners:4] hover:rotate-2 focus-visible:rotate-2 transition-transform",
48
+ active && !inactive && "rotate-2",
49
+ wrapperClass
50
+ )}
51
+ className={cn(
52
+ "smooth-corners leading-none font-semibold",
53
+ className
54
+ )}
55
+ {...props}
56
+ >
57
+ {children}
58
+ </Button>
59
+ </span>
60
+ );
61
+ });
62
+
63
+ export default TriggerButton;
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Dev Logger — structured JSONL logging for storyboard dev server errors.
3
+ *
4
+ * Writes one JSONL file per day to `.storyboard/logs/{YYYY-MM-DD}.jsonl`.
5
+ * Automatically enriches log entries with context extracted from request URLs
6
+ * (canvas name, prototype, page, etc.).
7
+ *
8
+ * Usage:
9
+ * import { createDevLogger } from './logger/devLogger.js'
10
+ * const logger = createDevLogger({ root, devDomain, branch })
11
+ * logger.logResponse({ status: 404, method: 'GET', url: '/...', route: 'canvas', error: '...' })
12
+ * logger.logEvent('warn', 'Something happened', { extra: 'context' })
13
+ */
14
+
15
+ import fs from 'node:fs'
16
+ import path from 'node:path'
17
+
18
+ const LOGS_DIR_NAME = 'logs'
19
+ const STORYBOARD_DIR = '.storyboard'
20
+ const MAX_AGE_DAYS = 7
21
+
22
+ /**
23
+ * Format a Date as YYYY-MM-DD.
24
+ */
25
+ function dateStamp(date = new Date()) {
26
+ return date.toISOString().slice(0, 10)
27
+ }
28
+
29
+ /**
30
+ * Extract contextual metadata from a request URL.
31
+ * Parses query params and path segments to find canvas, prototype, and page.
32
+ */
33
+ function extractContext(url) {
34
+ const ctx = { canvas: null, prototype: null, page: null }
35
+ if (!url) return ctx
36
+
37
+ try {
38
+ const parsed = new URL(url, 'http://localhost')
39
+ const params = parsed.searchParams
40
+
41
+ // Canvas name from ?name= query param (used by canvas CRUD routes)
42
+ if (params.has('name')) ctx.canvas = params.get('name')
43
+
44
+ // Prototype from path: /PrototypeName/... or ?prototype=
45
+ if (params.has('prototype')) ctx.prototype = params.get('prototype')
46
+
47
+ // Page from path segments or ?page=
48
+ if (params.has('page')) ctx.page = params.get('page')
49
+
50
+ // Infer from path: /_storyboard/canvas/... → canvas route
51
+ const pathname = parsed.pathname
52
+ if (!ctx.canvas && pathname.includes('/canvas/')) {
53
+ const segments = pathname.split('/').filter(Boolean)
54
+ const canvasIdx = segments.indexOf('canvas')
55
+ if (canvasIdx >= 0 && segments[canvasIdx + 1]) {
56
+ const sub = segments[canvasIdx + 1]
57
+ // Skip known sub-routes
58
+ if (!['read', 'list', 'update', 'widget', 'create', 'folders',
59
+ 'connector', 'stories', 'create-story', 'github', 'image',
60
+ 'images', 'terminal-buffer', 'terminal-snapshot',
61
+ 'rename-page', 'reorder-pages', 'page-order',
62
+ 'update-folder-meta', 'duplicate', 'image-proxy'].includes(sub)) {
63
+ ctx.canvas = sub
64
+ }
65
+ }
66
+ }
67
+ } catch {
68
+ // URL parsing failed — return empty context
69
+ }
70
+
71
+ return ctx
72
+ }
73
+
74
+ /**
75
+ * Prune log files older than MAX_AGE_DAYS.
76
+ */
77
+ function pruneOldLogs(logsDir) {
78
+ try {
79
+ const files = fs.readdirSync(logsDir)
80
+ const cutoff = Date.now() - MAX_AGE_DAYS * 24 * 60 * 60 * 1000
81
+
82
+ for (const file of files) {
83
+ if (!file.endsWith('.jsonl')) continue
84
+ const dateStr = file.replace('.jsonl', '')
85
+ const fileDate = new Date(dateStr + 'T00:00:00Z')
86
+ if (isNaN(fileDate.getTime())) continue
87
+ if (fileDate.getTime() < cutoff) {
88
+ try {
89
+ fs.unlinkSync(path.join(logsDir, file))
90
+ } catch { /* best-effort */ }
91
+ }
92
+ }
93
+ } catch {
94
+ // Directory might not exist yet — that's fine
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Create a dev logger instance.
100
+ *
101
+ * @param {object} opts
102
+ * @param {string} opts.root — project root directory
103
+ * @param {string} [opts.devDomain] — dev domain from config (e.g. "storyboard-core")
104
+ * @param {string} [opts.branch] — current git branch
105
+ * @param {boolean} [opts.verbose] — also log to console (controlled by dev-logs flag)
106
+ * @returns {{ logResponse: Function, logEvent: Function, logsDir: string }}
107
+ */
108
+ export function createDevLogger({ root, devDomain = null, branch = null, verbose = false } = {}) {
109
+ const logsDir = path.join(root, STORYBOARD_DIR, LOGS_DIR_NAME)
110
+ let dirEnsured = false
111
+
112
+ function ensureDir() {
113
+ if (dirEnsured) return true
114
+ try {
115
+ fs.mkdirSync(logsDir, { recursive: true })
116
+ dirEnsured = true
117
+ return true
118
+ } catch {
119
+ return false
120
+ }
121
+ }
122
+
123
+ // Prune old logs on startup (non-blocking, best-effort)
124
+ try { pruneOldLogs(logsDir) } catch { /* ignore */ }
125
+
126
+ function writeEntry(entry) {
127
+ if (!ensureDir()) return
128
+ const filename = `${dateStamp()}.jsonl`
129
+ const filepath = path.join(logsDir, filename)
130
+ const line = JSON.stringify(entry) + '\n'
131
+
132
+ try {
133
+ fs.appendFileSync(filepath, line, 'utf-8')
134
+ } catch {
135
+ // If we can't write logs, fail silently — never crash the server
136
+ }
137
+
138
+ if (verbose) {
139
+ const tag = entry.status ? `[${entry.status}]` : `[${entry.level}]`
140
+ const msg = entry.error || entry.message || ''
141
+ console.warn(`[storyboard-logs] ${tag} ${entry.method || ''} ${entry.url || ''} — ${msg}`)
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Log an HTTP error response (4xx/5xx).
147
+ *
148
+ * @param {object} opts
149
+ * @param {number} opts.status — HTTP status code
150
+ * @param {string} opts.method — HTTP method (GET, POST, etc.)
151
+ * @param {string} opts.url — full request URL
152
+ * @param {string} [opts.route] — top-level route prefix (e.g. "canvas", "workshop")
153
+ * @param {string} [opts.subRoute] — sub-route path after prefix
154
+ * @param {string} [opts.error] — error message from the response body
155
+ * @param {object} [opts.context] — additional context (overrides auto-extracted)
156
+ */
157
+ function logResponse({ status, method, url, route = null, subRoute = null, error = null, context = {} }) {
158
+ if (status < 400) return
159
+
160
+ const autoContext = extractContext(url)
161
+ const mergedContext = { ...autoContext, ...context }
162
+
163
+ // Strip null values from context
164
+ for (const key of Object.keys(mergedContext)) {
165
+ if (mergedContext[key] == null) delete mergedContext[key]
166
+ }
167
+
168
+ const entry = {
169
+ ts: new Date().toISOString(),
170
+ level: status >= 500 ? 'error' : 'warn',
171
+ status,
172
+ method: method || 'UNKNOWN',
173
+ url: url || '',
174
+ route: route || null,
175
+ subRoute: subRoute || null,
176
+ error: error || null,
177
+ devDomain: devDomain || null,
178
+ branch: branch || null,
179
+ }
180
+
181
+ if (Object.keys(mergedContext).length > 0) {
182
+ entry.context = mergedContext
183
+ }
184
+
185
+ writeEntry(entry)
186
+ }
187
+
188
+ /**
189
+ * Log a general event (not tied to an HTTP response).
190
+ *
191
+ * @param {'info'|'warn'|'error'} level
192
+ * @param {string} message
193
+ * @param {object} [context] — arbitrary context data
194
+ */
195
+ function logEvent(level, message, context = {}) {
196
+ const entry = {
197
+ ts: new Date().toISOString(),
198
+ level,
199
+ message,
200
+ devDomain: devDomain || null,
201
+ branch: branch || null,
202
+ }
203
+ if (Object.keys(context).length > 0) {
204
+ entry.context = context
205
+ }
206
+ writeEntry(entry)
207
+ }
208
+
209
+ return { logResponse, logEvent, logsDir, _extractContext: extractContext }
210
+ }
211
+
212
+ // ─── Module-level singleton ───
213
+ // Set once by server-plugin.js, then any server-side module can call devLog().
214
+
215
+ let _instance = null
216
+
217
+ /**
218
+ * Register the global dev logger instance.
219
+ * Called once during server startup (server-plugin.js configureServer).
220
+ */
221
+ export function setDevLogger(logger) {
222
+ _instance = logger
223
+ }
224
+
225
+ /**
226
+ * Get the global dev logger. Returns a no-op logger if not yet initialized.
227
+ * Safe to call from any server-side module without constructor plumbing.
228
+ */
229
+ export function devLog() {
230
+ return _instance || _noop
231
+ }
232
+
233
+ const _noop = {
234
+ logResponse() {},
235
+ logEvent() {},
236
+ }
237
+
238
+ export { extractContext, pruneOldLogs, dateStamp }
@@ -0,0 +1,193 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2
+ import fs from 'node:fs'
3
+ import path from 'node:path'
4
+ import os from 'node:os'
5
+ import { createDevLogger, extractContext, pruneOldLogs, dateStamp } from './devLogger.js'
6
+
7
+ function makeTmpDir() {
8
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'devlogger-test-'))
9
+ }
10
+
11
+ describe('devLogger', () => {
12
+ let tmpRoot
13
+
14
+ beforeEach(() => {
15
+ tmpRoot = makeTmpDir()
16
+ })
17
+
18
+ afterEach(() => {
19
+ fs.rmSync(tmpRoot, { recursive: true, force: true })
20
+ })
21
+
22
+ describe('createDevLogger', () => {
23
+ it('creates the logs directory on first write', () => {
24
+ const logger = createDevLogger({ root: tmpRoot, devDomain: 'test', branch: 'main' })
25
+ const logsDir = path.join(tmpRoot, '.storyboard', 'logs')
26
+
27
+ // Not created yet (lazy)
28
+ expect(fs.existsSync(logsDir)).toBe(false)
29
+
30
+ logger.logResponse({ status: 404, method: 'GET', url: '/_storyboard/canvas/read?name=missing', error: 'Not found' })
31
+
32
+ expect(fs.existsSync(logsDir)).toBe(true)
33
+ })
34
+
35
+ it('writes JSONL entries with correct format', () => {
36
+ const logger = createDevLogger({ root: tmpRoot, devDomain: 'test-domain', branch: 'feat-x' })
37
+
38
+ logger.logResponse({
39
+ status: 404,
40
+ method: 'GET',
41
+ url: '/_storyboard/canvas/read?name=my-canvas',
42
+ route: 'canvas',
43
+ subRoute: '/read',
44
+ error: 'Canvas "my-canvas" not found',
45
+ })
46
+
47
+ const logsDir = path.join(tmpRoot, '.storyboard', 'logs')
48
+ const files = fs.readdirSync(logsDir)
49
+ expect(files).toHaveLength(1)
50
+ expect(files[0]).toMatch(/^\d{4}-\d{2}-\d{2}\.jsonl$/)
51
+
52
+ const content = fs.readFileSync(path.join(logsDir, files[0]), 'utf-8')
53
+ const lines = content.trim().split('\n')
54
+ expect(lines).toHaveLength(1)
55
+
56
+ const entry = JSON.parse(lines[0])
57
+ expect(entry.ts).toMatch(/^\d{4}-\d{2}-\d{2}T/)
58
+ expect(entry.level).toBe('warn')
59
+ expect(entry.status).toBe(404)
60
+ expect(entry.method).toBe('GET')
61
+ expect(entry.route).toBe('canvas')
62
+ expect(entry.subRoute).toBe('/read')
63
+ expect(entry.error).toBe('Canvas "my-canvas" not found')
64
+ expect(entry.devDomain).toBe('test-domain')
65
+ expect(entry.branch).toBe('feat-x')
66
+ expect(entry.context.canvas).toBe('my-canvas')
67
+ })
68
+
69
+ it('uses level "error" for 5xx status codes', () => {
70
+ const logger = createDevLogger({ root: tmpRoot })
71
+ logger.logResponse({ status: 500, method: 'POST', url: '/test', error: 'Internal error' })
72
+
73
+ const logsDir = path.join(tmpRoot, '.storyboard', 'logs')
74
+ const files = fs.readdirSync(logsDir)
75
+ const entry = JSON.parse(fs.readFileSync(path.join(logsDir, files[0]), 'utf-8').trim())
76
+ expect(entry.level).toBe('error')
77
+ })
78
+
79
+ it('does not log 2xx responses', () => {
80
+ const logger = createDevLogger({ root: tmpRoot })
81
+ logger.logResponse({ status: 200, method: 'GET', url: '/ok' })
82
+ logger.logResponse({ status: 201, method: 'POST', url: '/created' })
83
+
84
+ const logsDir = path.join(tmpRoot, '.storyboard', 'logs')
85
+ expect(fs.existsSync(logsDir)).toBe(false) // never written, dir never created
86
+ })
87
+
88
+ it('appends multiple entries to the same day file', () => {
89
+ const logger = createDevLogger({ root: tmpRoot })
90
+ logger.logResponse({ status: 404, method: 'GET', url: '/a', error: 'A' })
91
+ logger.logResponse({ status: 400, method: 'POST', url: '/b', error: 'B' })
92
+ logger.logResponse({ status: 502, method: 'GET', url: '/c', error: 'C' })
93
+
94
+ const logsDir = path.join(tmpRoot, '.storyboard', 'logs')
95
+ const files = fs.readdirSync(logsDir)
96
+ expect(files).toHaveLength(1)
97
+
98
+ const lines = fs.readFileSync(path.join(logsDir, files[0]), 'utf-8').trim().split('\n')
99
+ expect(lines).toHaveLength(3)
100
+ expect(JSON.parse(lines[0]).error).toBe('A')
101
+ expect(JSON.parse(lines[1]).error).toBe('B')
102
+ expect(JSON.parse(lines[2]).error).toBe('C')
103
+ })
104
+ })
105
+
106
+ describe('logEvent', () => {
107
+ it('logs general events with level and message', () => {
108
+ const logger = createDevLogger({ root: tmpRoot, devDomain: 'test' })
109
+ logger.logEvent('warn', 'Hot pool failed to start', { poolId: 'copilot' })
110
+
111
+ const logsDir = path.join(tmpRoot, '.storyboard', 'logs')
112
+ const files = fs.readdirSync(logsDir)
113
+ const entry = JSON.parse(fs.readFileSync(path.join(logsDir, files[0]), 'utf-8').trim())
114
+
115
+ expect(entry.level).toBe('warn')
116
+ expect(entry.message).toBe('Hot pool failed to start')
117
+ expect(entry.context.poolId).toBe('copilot')
118
+ expect(entry.devDomain).toBe('test')
119
+ })
120
+ })
121
+
122
+ describe('extractContext', () => {
123
+ it('extracts canvas name from ?name= query param', () => {
124
+ const ctx = extractContext('/_storyboard/canvas/read?name=design-system')
125
+ expect(ctx.canvas).toBe('design-system')
126
+ })
127
+
128
+ it('extracts prototype from ?prototype= query param', () => {
129
+ const ctx = extractContext('/_storyboard/workshop/create?prototype=Dashboard')
130
+ expect(ctx.prototype).toBe('Dashboard')
131
+ })
132
+
133
+ it('extracts page from ?page= query param', () => {
134
+ const ctx = extractContext('/_storyboard/something?page=settings')
135
+ expect(ctx.page).toBe('settings')
136
+ })
137
+
138
+ it('returns empty context for non-parseable URLs', () => {
139
+ const ctx = extractContext('')
140
+ expect(ctx.canvas).toBeNull()
141
+ expect(ctx.prototype).toBeNull()
142
+ expect(ctx.page).toBeNull()
143
+ })
144
+
145
+ it('returns empty context for null input', () => {
146
+ const ctx = extractContext(null)
147
+ expect(ctx.canvas).toBeNull()
148
+ })
149
+ })
150
+
151
+ describe('dateStamp', () => {
152
+ it('returns YYYY-MM-DD format', () => {
153
+ const stamp = dateStamp(new Date('2026-04-25T12:00:00Z'))
154
+ expect(stamp).toBe('2026-04-25')
155
+ })
156
+ })
157
+
158
+ describe('pruneOldLogs', () => {
159
+ it('removes log files older than 7 days', () => {
160
+ const logsDir = path.join(tmpRoot, 'logs')
161
+ fs.mkdirSync(logsDir, { recursive: true })
162
+
163
+ // Create old file (10 days ago)
164
+ const old = new Date(Date.now() - 10 * 24 * 60 * 60 * 1000)
165
+ const oldFile = `${dateStamp(old)}.jsonl`
166
+ fs.writeFileSync(path.join(logsDir, oldFile), '{"test":true}\n')
167
+
168
+ // Create recent file (today)
169
+ const todayFile = `${dateStamp()}.jsonl`
170
+ fs.writeFileSync(path.join(logsDir, todayFile), '{"test":true}\n')
171
+
172
+ pruneOldLogs(logsDir)
173
+
174
+ const remaining = fs.readdirSync(logsDir)
175
+ expect(remaining).toContain(todayFile)
176
+ expect(remaining).not.toContain(oldFile)
177
+ })
178
+
179
+ it('ignores non-jsonl files', () => {
180
+ const logsDir = path.join(tmpRoot, 'logs')
181
+ fs.mkdirSync(logsDir, { recursive: true })
182
+ fs.writeFileSync(path.join(logsDir, 'readme.txt'), 'keep me')
183
+
184
+ pruneOldLogs(logsDir)
185
+
186
+ expect(fs.existsSync(path.join(logsDir, 'readme.txt'))).toBe(true)
187
+ })
188
+
189
+ it('handles non-existent directory gracefully', () => {
190
+ expect(() => pruneOldLogs(path.join(tmpRoot, 'nonexistent'))).not.toThrow()
191
+ })
192
+ })
193
+ })
package/src/modes.test.js CHANGED
@@ -359,7 +359,7 @@ describe('locked mode', () => {
359
359
  describe('tool registry', () => {
360
360
  const SAMPLE_TOOLS = {
361
361
  '*': [
362
- { id: 'viewfinder', label: 'Viewfinder', group: 'dev' },
362
+ { id: 'workspace', label: 'Workspace', group: 'dev' },
363
363
  { id: 'reset-params', label: 'Reset all params', group: 'dev' },
364
364
  ],
365
365
  'present': [
@@ -372,14 +372,14 @@ describe('tool registry', () => {
372
372
  initTools(SAMPLE_TOOLS)
373
373
  const tools = getToolsForMode('present')
374
374
  const ids = tools.map(t => t.id)
375
- expect(ids).toContain('viewfinder')
375
+ expect(ids).toContain('workspace')
376
376
  expect(ids).toContain('comments-toggle')
377
377
  })
378
378
 
379
379
  it('wildcard tools appear in all modes', () => {
380
380
  initTools(SAMPLE_TOOLS)
381
381
  const protoTools = getToolsForMode('prototype')
382
- expect(protoTools.map(t => t.id)).toContain('viewfinder')
382
+ expect(protoTools.map(t => t.id)).toContain('workspace')
383
383
  })
384
384
 
385
385
  it('mode-specific tools only appear in their mode', () => {
@@ -390,7 +390,7 @@ describe('tool registry', () => {
390
390
 
391
391
  it('tools start with default state', () => {
392
392
  initTools(SAMPLE_TOOLS)
393
- const state = getToolState('viewfinder')
393
+ const state = getToolState('workspace')
394
394
  expect(state).toEqual({
395
395
  enabled: true,
396
396
  active: false,