@webship.co/workspace 1.0.0-beta1 → 1.0.0-rc1

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 (632) hide show
  1. package/LICENSE +339 -0
  2. package/README.md +28 -364
  3. package/core/bin/workspace.js +135 -0
  4. package/core/config/settings.labels.yml +514 -0
  5. package/core/config/settings.template.yml +292 -0
  6. package/core/config/style.yml +53 -0
  7. package/core/config/theme.default.yml +161 -0
  8. package/core/config/theme.dispatch.yml +166 -0
  9. package/core/config/theme.drupal.yml +175 -0
  10. package/core/config/theme.ember.yml +160 -0
  11. package/core/config/theme.github.yml +172 -0
  12. package/core/config/theme.gitlab.yml +168 -0
  13. package/core/config/theme.press.yml +161 -0
  14. package/core/config/theme.slate.yml +160 -0
  15. package/core/config/theme.upsun.yml +174 -0
  16. package/core/docs/architecture.svg +65 -0
  17. package/core/docs/getting-started.md +51 -0
  18. package/core/docs/plugins.md +27 -0
  19. package/core/docs/releases.md +23 -0
  20. package/core/docs/testing.md +15 -0
  21. package/core/docs/workspaces.md +25 -0
  22. package/core/scripts/args/arg-ai-items.sh +65 -0
  23. package/core/scripts/args/arg-autostart.sh +31 -0
  24. package/core/scripts/args/arg-avatar-agent.sh +28 -0
  25. package/core/scripts/args/arg-avatar-catalog.sh +12 -0
  26. package/core/scripts/args/arg-avatar-character.sh +68 -0
  27. package/core/scripts/args/arg-avatar-voice.sh +24 -0
  28. package/core/scripts/args/arg-avatar.sh +22 -0
  29. package/core/scripts/args/arg-checks.sh +36 -0
  30. package/core/scripts/args/arg-clone.sh +42 -0
  31. package/core/scripts/args/arg-commands.sh +51 -0
  32. package/core/scripts/args/arg-cucumber.sh +34 -0
  33. package/core/scripts/args/arg-distribution.sh +30 -0
  34. package/core/scripts/args/arg-drupal.sh +39 -0
  35. package/core/scripts/args/arg-drupal_cms.sh +18 -0
  36. package/core/scripts/args/arg-gitlab-ci-local.sh +25 -0
  37. package/core/scripts/args/arg-graphify.sh +36 -0
  38. package/core/scripts/args/arg-graphs.sh +12 -0
  39. package/core/scripts/args/arg-hostnames.sh +23 -0
  40. package/core/scripts/args/arg-milvus-backup.sh +8 -0
  41. package/core/scripts/args/arg-milvus-mcp.sh +12 -0
  42. package/core/scripts/args/arg-milvus.sh +32 -0
  43. package/core/scripts/args/arg-obsidian.sh +17 -0
  44. package/core/scripts/args/arg-odoo.sh +18 -0
  45. package/core/scripts/args/arg-penpot-backup.sh +8 -0
  46. package/core/scripts/args/arg-penpot-mcp.sh +15 -0
  47. package/core/scripts/args/arg-penpot-token.sh +17 -0
  48. package/core/scripts/args/arg-penpot.sh +44 -0
  49. package/core/scripts/args/arg-rag.sh +21 -0
  50. package/core/scripts/args/arg-ragify.sh +35 -0
  51. package/core/scripts/args/arg-reclaim.sh +18 -0
  52. package/core/scripts/args/arg-release.sh +21 -0
  53. package/core/scripts/args/arg-screen.sh +28 -0
  54. package/core/scripts/args/arg-site-template.sh +13 -0
  55. package/core/scripts/args/arg-spdd.sh +16 -0
  56. package/core/scripts/args/arg-specs.sh +22 -0
  57. package/core/scripts/args/arg-storage.sh +36 -0
  58. package/core/scripts/args/arg-testing.sh +36 -0
  59. package/core/scripts/args/arg-webship.sh +34 -0
  60. package/core/scripts/args/arg-webships-project.sh +22 -0
  61. package/core/scripts/args/arg-webships-site-template.sh +17 -0
  62. package/core/scripts/args/arg-webships.sh +34 -0
  63. package/core/scripts/args/arg-website-site-template.sh +17 -0
  64. package/core/scripts/args/arg-website.sh +25 -0
  65. package/core/scripts/args/arg-wordpress.sh +18 -0
  66. package/core/scripts/autostart-run.sh +162 -0
  67. package/core/scripts/autostart-stop.sh +30 -0
  68. package/core/scripts/autostart-watch.sh +43 -0
  69. package/core/scripts/autostart.sh +26 -0
  70. package/core/scripts/bootstrap-functions.sh +117 -0
  71. package/core/scripts/bootstrap-libraries.sh +10 -0
  72. package/core/scripts/bootstrap.sh +71 -0
  73. package/core/scripts/ddev-shim/ddev +122 -0
  74. package/core/scripts/docker-gid.sh +119 -0
  75. package/core/scripts/functions/arg-site-template.sh +28 -0
  76. package/core/scripts/functions/fun-ai-items-lock.sh +175 -0
  77. package/core/scripts/functions/fun-ai-items-sources.sh +298 -0
  78. package/core/scripts/functions/fun-ai-items.sh +621 -0
  79. package/core/scripts/functions/fun-ai-providers.sh +72 -0
  80. package/core/scripts/functions/fun-autostart.sh +429 -0
  81. package/core/scripts/functions/fun-avatar.sh +441 -0
  82. package/core/scripts/functions/fun-backup-item.sh +50 -0
  83. package/core/scripts/functions/fun-build-distribution.sh +226 -0
  84. package/core/scripts/functions/fun-build-site-template.sh +104 -0
  85. package/core/scripts/functions/fun-build-webships.sh +161 -0
  86. package/core/scripts/functions/fun-build-website.sh +199 -0
  87. package/core/scripts/functions/fun-checks.sh +243 -0
  88. package/core/scripts/functions/fun-clone-project.sh +289 -0
  89. package/core/scripts/functions/fun-commands.sh +521 -0
  90. package/core/scripts/functions/fun-database.sh +63 -0
  91. package/core/scripts/functions/fun-ddev-hostnames.sh +213 -0
  92. package/core/scripts/functions/fun-ddev-nodejs.sh +15 -0
  93. package/core/scripts/functions/fun-ddev-telemetry.sh +15 -0
  94. package/core/scripts/functions/fun-default-settings.sh +28 -0
  95. package/core/scripts/functions/fun-distribution-cucumber.sh +45 -0
  96. package/core/scripts/functions/fun-distribution-drupal.sh +25 -0
  97. package/core/scripts/functions/fun-distribution-drupal_cms.sh +35 -0
  98. package/core/scripts/functions/fun-distribution-webship.sh +28 -0
  99. package/core/scripts/functions/fun-distribution-webships.sh +33 -0
  100. package/core/scripts/functions/fun-distribution-website.sh +19 -0
  101. package/core/scripts/functions/fun-drush.sh +48 -0
  102. package/core/scripts/functions/fun-elevenlabs.sh +179 -0
  103. package/core/scripts/functions/fun-files.sh +19 -0
  104. package/core/scripts/functions/fun-git-worktrees.sh +142 -0
  105. package/core/scripts/functions/fun-gitlab-ci.sh +156 -0
  106. package/core/scripts/functions/fun-hostnames-cli.sh +88 -0
  107. package/core/scripts/functions/fun-milvus.sh +584 -0
  108. package/core/scripts/functions/fun-odoo.sh +121 -0
  109. package/core/scripts/functions/fun-penpot.sh +724 -0
  110. package/core/scripts/functions/fun-project-name.sh +20 -0
  111. package/core/scripts/functions/fun-rag.sh +253 -0
  112. package/core/scripts/functions/fun-ragify.sh +165 -0
  113. package/core/scripts/functions/fun-reclaim.sh +297 -0
  114. package/core/scripts/functions/fun-release.sh +159 -0
  115. package/core/scripts/functions/fun-remove-project.sh +319 -0
  116. package/core/scripts/functions/fun-screen.sh +96 -0
  117. package/core/scripts/functions/fun-spdd.sh +676 -0
  118. package/core/scripts/functions/fun-specs-share.sh +237 -0
  119. package/core/scripts/functions/fun-storage.sh +347 -0
  120. package/core/scripts/functions/fun-testing.sh +329 -0
  121. package/core/scripts/functions/fun-users.sh +87 -0
  122. package/core/scripts/functions/fun-version.sh +72 -0
  123. package/core/scripts/functions/fun-video-edit.sh +48 -0
  124. package/core/scripts/functions/fun-voice.sh +45 -0
  125. package/core/scripts/functions/fun-wordpress.sh +59 -0
  126. package/core/scripts/host-mounts.sh +161 -0
  127. package/core/scripts/install.sh +602 -0
  128. package/core/scripts/libs/__pycache__/video_edit.cpython-312.pyc +0 -0
  129. package/core/scripts/libs/argparse.sh +93 -0
  130. package/core/scripts/libs/bash-yaml.sh +52 -0
  131. package/core/scripts/libs/checks_plan.js +312 -0
  132. package/core/scripts/libs/elevenlabs.py +627 -0
  133. package/core/scripts/libs/progress-bar.sh +19 -0
  134. package/core/scripts/libs/rag_index.py +446 -0
  135. package/core/scripts/libs/video_edit.py +636 -0
  136. package/core/scripts/libs/voice.py +430 -0
  137. package/core/scripts/plugins/jira/host-install.sh +119 -0
  138. package/core/scripts/plugins/jira/host-mounts.txt +2 -0
  139. package/core/scripts/plugins/upsun/args/arg-upsun.sh +51 -0
  140. package/core/scripts/plugins/upsun/functions/fun-upsun.sh +304 -0
  141. package/core/scripts/plugins/upsun/host-install.sh +99 -0
  142. package/core/scripts/plugins/upsun/host-mounts.txt +1 -0
  143. package/core/scripts/plugins/upsun/upsun-ai.sh +133 -0
  144. package/core/scripts/plugins.sh +152 -0
  145. package/core/scripts/release.sh +69 -0
  146. package/core/scripts/storage.sh +39 -0
  147. package/core/scripts/sync-tooling.sh +246 -0
  148. package/core/scripts/tests/cmd-smoke-test.sh +109 -0
  149. package/core/scripts/trust-https.sh +257 -0
  150. package/core/workspace-app/.ddev/commands/web/test-dashboard +49 -0
  151. package/core/workspace-app/.ddev/config.yaml +400 -0
  152. package/core/workspace-app/.ddev/docker-compose.dood.yaml +45 -0
  153. package/core/workspace-app/.ddev/docker-compose.plugin-jira-twg.yaml +26 -0
  154. package/core/workspace-app/.ddev/docker-compose.plugin-upsun-upsun-cli.yaml +8 -0
  155. package/core/workspace-app/.ddev/docker-compose.screens.yaml +15 -0
  156. package/core/workspace-app/.ddev/nginx_full/nginx-site.conf +114 -0
  157. package/core/workspace-app/.ddev/web-build/Dockerfile.workspace-app +203 -0
  158. package/core/workspace-app/.ddev/web-build/ddev-shim-ddev +122 -0
  159. package/{PLUGINS.md → core/workspace-app/PLUGINS.md} +9 -1
  160. package/core/workspace-app/README.md +380 -0
  161. package/{actions → core/workspace-app/actions}/ddev.js +0 -1
  162. package/{actions → core/workspace-app/actions}/rag.js +0 -1
  163. package/{actions → core/workspace-app/actions}/testing.js +0 -1
  164. package/{assistant.js → core/workspace-app/assistant.js} +1 -10
  165. package/{git-info.js → core/workspace-app/git-info.js} +17 -1
  166. package/core/workspace-app/package.json +29 -0
  167. package/core/workspace-app/plugin-catalog.js +50 -0
  168. package/{plugins-page.js → core/workspace-app/plugins-page.js} +28 -2
  169. package/{server.js → core/workspace-app/server.js} +18 -0
  170. package/core/workspace-app/tests/features/actions-rail.feature +44 -0
  171. package/core/workspace-app/tests/features/ai-items.feature +23 -0
  172. package/core/workspace-app/tests/features/assistant-speech.feature +63 -0
  173. package/core/workspace-app/tests/features/checks.feature +40 -0
  174. package/core/workspace-app/tests/features/clone-project.feature +30 -0
  175. package/core/workspace-app/tests/features/command-authoring.feature +58 -0
  176. package/core/workspace-app/tests/features/dashboard.feature +57 -0
  177. package/core/workspace-app/tests/features/menus.feature +29 -0
  178. package/core/workspace-app/tests/features/plugins/jira/jira.feature +47 -0
  179. package/core/workspace-app/tests/features/plugins.feature +20 -0
  180. package/core/workspace-app/tests/features/project-actions.feature +41 -0
  181. package/core/workspace-app/tests/features/screens.feature +29 -0
  182. package/core/workspace-app/tests/features/settings.feature +46 -0
  183. package/core/workspace-app/tests/features/test-reports.feature +32 -0
  184. package/core/workspace-app/tests/features/theme.feature +40 -0
  185. package/core/workspace-app/tests/step-definitions/actions-post.steps.js +25 -0
  186. package/core/workspace-app/tests/step-definitions/assistant-speech.steps.js +157 -0
  187. package/core/workspace-app/tests/step-definitions/clone-project.steps.js +47 -0
  188. package/core/workspace-app/tests/step-definitions/preconditions.steps.js +168 -0
  189. package/core/workspace-app/tests/unit/_isolated-config.js +31 -0
  190. package/core/workspace-app/tests/unit/accessibility.test.js +124 -0
  191. package/core/workspace-app/tests/unit/actions-rail-ux.test.js +56 -0
  192. package/core/workspace-app/tests/unit/actions-rail.test.js +51 -0
  193. package/core/workspace-app/tests/unit/ai-inventory.test.js +64 -0
  194. package/core/workspace-app/tests/unit/app-docs.test.js +64 -0
  195. package/core/workspace-app/tests/unit/assistant-avatar.test.js +110 -0
  196. package/core/workspace-app/tests/unit/assistant-cast.test.js +105 -0
  197. package/core/workspace-app/tests/unit/assistant-send-animation.test.js +15 -0
  198. package/core/workspace-app/tests/unit/assistant-suggestions.test.js +112 -0
  199. package/core/workspace-app/tests/unit/assistant-switches.test.js +53 -0
  200. package/core/workspace-app/tests/unit/assistant-views.test.js +146 -0
  201. package/core/workspace-app/tests/unit/assistant-working-indicator.test.js +49 -0
  202. package/core/workspace-app/tests/unit/assistant.test.js +61 -0
  203. package/core/workspace-app/tests/unit/audio-player.test.js +147 -0
  204. package/core/workspace-app/tests/unit/audio-voice.test.js +634 -0
  205. package/core/workspace-app/tests/unit/auth-google.test.js +180 -0
  206. package/core/workspace-app/tests/unit/autostart-watch.test.js +76 -0
  207. package/core/workspace-app/tests/unit/browsers.test.js +76 -0
  208. package/core/workspace-app/tests/unit/build-distribution.test.js +125 -0
  209. package/core/workspace-app/tests/unit/build-order.test.js +153 -0
  210. package/core/workspace-app/tests/unit/builder-args.test.js +113 -0
  211. package/core/workspace-app/tests/unit/builders.test.js +158 -0
  212. package/core/workspace-app/tests/unit/card-state-toggle.test.js +29 -0
  213. package/core/workspace-app/tests/unit/changelog.test.js +223 -0
  214. package/core/workspace-app/tests/unit/chat-thread.test.js +92 -0
  215. package/core/workspace-app/tests/unit/checks-plan.test.js +205 -0
  216. package/core/workspace-app/tests/unit/claude-args.test.js +182 -0
  217. package/core/workspace-app/tests/unit/claude-code-here.test.js +15 -0
  218. package/core/workspace-app/tests/unit/claude-resume.test.js +147 -0
  219. package/core/workspace-app/tests/unit/claude-screen-options.test.js +84 -0
  220. package/core/workspace-app/tests/unit/claude-session.test.js +41 -0
  221. package/core/workspace-app/tests/unit/command-flags.test.js +45 -0
  222. package/core/workspace-app/tests/unit/command-palette.test.js +105 -0
  223. package/core/workspace-app/tests/unit/commands-center.test.js +338 -0
  224. package/core/workspace-app/tests/unit/composer-menu.test.js +187 -0
  225. package/core/workspace-app/tests/unit/config-yaml.test.js +116 -0
  226. package/core/workspace-app/tests/unit/confirm-dialog.test.js +69 -0
  227. package/core/workspace-app/tests/unit/create-card.test.js +85 -0
  228. package/core/workspace-app/tests/unit/ddev-addons.test.js +144 -0
  229. package/core/workspace-app/tests/unit/ddev-auth-ssh.test.js +40 -0
  230. package/core/workspace-app/tests/unit/ddev-custom-commands.test.js +56 -0
  231. package/core/workspace-app/tests/unit/ddev-diagnose.test.js +57 -0
  232. package/core/workspace-app/tests/unit/ddev-domains.test.js +179 -0
  233. package/core/workspace-app/tests/unit/ddev-hostnames.test.js +143 -0
  234. package/core/workspace-app/tests/unit/ddev-import.test.js +82 -0
  235. package/core/workspace-app/tests/unit/ddev-mail.test.js +135 -0
  236. package/core/workspace-app/tests/unit/ddev-menu-and-create.test.js +28 -0
  237. package/core/workspace-app/tests/unit/ddev-mutagen.test.js +37 -0
  238. package/core/workspace-app/tests/unit/ddev-options.test.js +51 -0
  239. package/core/workspace-app/tests/unit/ddev-share.test.js +40 -0
  240. package/core/workspace-app/tests/unit/ddev-shim.test.js +57 -0
  241. package/core/workspace-app/tests/unit/ddev-snapshots.test.js +142 -0
  242. package/core/workspace-app/tests/unit/ddev-start-daemons.test.js +62 -0
  243. package/core/workspace-app/tests/unit/ddev-xdebug.test.js +41 -0
  244. package/core/workspace-app/tests/unit/deep-chat-origin.test.js +38 -0
  245. package/core/workspace-app/tests/unit/density.test.js +52 -0
  246. package/core/workspace-app/tests/unit/elevenlabs.test.js +453 -0
  247. package/core/workspace-app/tests/unit/event-log.test.js +102 -0
  248. package/core/workspace-app/tests/unit/favicon.test.js +68 -0
  249. package/core/workspace-app/tests/unit/files-browser.test.js +224 -0
  250. package/core/workspace-app/tests/unit/git-info.test.js +26 -0
  251. package/core/workspace-app/tests/unit/grid-and-list.test.js +103 -0
  252. package/core/workspace-app/tests/unit/host-tool-wrapper.test.js +18 -0
  253. package/core/workspace-app/tests/unit/html-patterns.test.js +51 -0
  254. package/core/workspace-app/tests/unit/ide-infra.test.js +28 -0
  255. package/core/workspace-app/tests/unit/images-ai.test.js +201 -0
  256. package/core/workspace-app/tests/unit/images-create.test.js +59 -0
  257. package/core/workspace-app/tests/unit/images-providers.test.js +248 -0
  258. package/core/workspace-app/tests/unit/images-svg.test.js +213 -0
  259. package/core/workspace-app/tests/unit/images-workspace.test.js +144 -0
  260. package/core/workspace-app/tests/unit/jobs-fragment.test.js +66 -0
  261. package/core/workspace-app/tests/unit/media-ux.test.js +164 -0
  262. package/core/workspace-app/tests/unit/modal-fit.test.js +87 -0
  263. package/core/workspace-app/tests/unit/modules-load.test.js +23 -0
  264. package/core/workspace-app/tests/unit/narration.test.js +186 -0
  265. package/core/workspace-app/tests/unit/navigation-editor.test.js +260 -0
  266. package/core/workspace-app/tests/unit/navigation.test.js +254 -0
  267. package/core/workspace-app/tests/unit/new-folder.test.js +121 -0
  268. package/core/workspace-app/tests/unit/new-screen-form.test.js +149 -0
  269. package/core/workspace-app/tests/unit/node-menu.test.js +161 -0
  270. package/core/workspace-app/tests/unit/notes.test.js +128 -0
  271. package/core/workspace-app/tests/unit/page-structure.test.js +40 -0
  272. package/core/workspace-app/tests/unit/page-width.test.js +59 -0
  273. package/core/workspace-app/tests/unit/php-version.test.js +90 -0
  274. package/core/workspace-app/tests/unit/plan-card.test.js +44 -0
  275. package/core/workspace-app/tests/unit/plugin-catalog.test.js +31 -0
  276. package/core/workspace-app/tests/unit/plugin-system.test.js +251 -0
  277. package/core/workspace-app/tests/unit/plugins-page.test.js +28 -0
  278. package/core/workspace-app/tests/unit/plugins.test.js +58 -0
  279. package/core/workspace-app/tests/unit/preconditions.test.js +21 -0
  280. package/core/workspace-app/tests/unit/project-activity-filter.test.js +180 -0
  281. package/core/workspace-app/tests/unit/project-make.test.js +143 -0
  282. package/core/workspace-app/tests/unit/project-name.test.js +202 -0
  283. package/core/workspace-app/tests/unit/reader.test.js +62 -0
  284. package/core/workspace-app/tests/unit/release.test.js +92 -0
  285. package/core/workspace-app/tests/unit/remove-confirm.test.js +37 -0
  286. package/core/workspace-app/tests/unit/report-pdf.test.js +171 -0
  287. package/core/workspace-app/tests/unit/round-11.test.js +31 -0
  288. package/core/workspace-app/tests/unit/round-12.test.js +37 -0
  289. package/core/workspace-app/tests/unit/row-layout.test.js +585 -0
  290. package/core/workspace-app/tests/unit/row-menus-fold.test.js +29 -0
  291. package/core/workspace-app/tests/unit/rows-add-modal.test.js +68 -0
  292. package/core/workspace-app/tests/unit/screen-runner-queue.test.js +41 -0
  293. package/core/workspace-app/tests/unit/screen-window.test.js +116 -0
  294. package/core/workspace-app/tests/unit/screens-beside-running.test.js +19 -0
  295. package/core/workspace-app/tests/unit/screens-columns.test.js +79 -0
  296. package/core/workspace-app/tests/unit/screens-menu.test.js +84 -0
  297. package/core/workspace-app/tests/unit/screens-modal-overlay.test.js +14 -0
  298. package/core/workspace-app/tests/unit/screens-waiting.test.js +129 -0
  299. package/core/workspace-app/tests/unit/screens.test.js +93 -0
  300. package/core/workspace-app/tests/unit/second-storage.test.js +218 -0
  301. package/core/workspace-app/tests/unit/session-name.test.js +64 -0
  302. package/core/workspace-app/tests/unit/settings-file.test.js +173 -0
  303. package/core/workspace-app/tests/unit/settings-nested-list.test.js +54 -0
  304. package/core/workspace-app/tests/unit/settings-raw.test.js +177 -0
  305. package/core/workspace-app/tests/unit/shared-prefs.test.js +49 -0
  306. package/core/workspace-app/tests/unit/speech.test.js +290 -0
  307. package/core/workspace-app/tests/unit/static-caching.test.js +39 -0
  308. package/core/workspace-app/tests/unit/status-language.test.js +47 -0
  309. package/core/workspace-app/tests/unit/tab-modal.test.js +69 -0
  310. package/core/workspace-app/tests/unit/tab-title.test.js +37 -0
  311. package/core/workspace-app/tests/unit/template-literals.test.js +52 -0
  312. package/core/workspace-app/tests/unit/terminal-scrollback.test.js +61 -0
  313. package/core/workspace-app/tests/unit/terminal-size.test.js +103 -0
  314. package/core/workspace-app/tests/unit/terminal-style.test.js +84 -0
  315. package/core/workspace-app/tests/unit/terminal-windows.test.js +154 -0
  316. package/core/workspace-app/tests/unit/themes.test.js +453 -0
  317. package/core/workspace-app/tests/unit/tool-labels.test.js +34 -0
  318. package/core/workspace-app/tests/unit/topbar-icons.test.js +47 -0
  319. package/core/workspace-app/tests/unit/update-docker-gid.test.js +51 -0
  320. package/core/workspace-app/tests/unit/user-guide.test.js +60 -0
  321. package/core/workspace-app/tests/unit/version-check.test.js +98 -0
  322. package/core/workspace-app/tests/unit/version-link.test.js +50 -0
  323. package/core/workspace-app/tests/unit/video-borrow.test.js +220 -0
  324. package/core/workspace-app/tests/unit/video-edit-ask.test.js +93 -0
  325. package/core/workspace-app/tests/unit/video-edit-short.test.js +42 -0
  326. package/core/workspace-app/tests/unit/video-edit.test.js +436 -0
  327. package/core/workspace-app/tests/unit/video-transcript.test.js +237 -0
  328. package/core/workspace-app/tests/unit/waiting.test.js +48 -0
  329. package/core/workspace-app/tests/unit/wordpress-odoo-builders.test.js +38 -0
  330. package/core/workspace-app/tests/unit/workspace-bin.test.js +48 -0
  331. package/core/workspace-app/tests/unit/workspace-card-tools.test.js +30 -0
  332. package/core/workspace-app/tests/unit/workspace-delete.test.js +77 -0
  333. package/core/workspace-app/tests/unit/workspace-types.test.js +68 -0
  334. package/core/workspace-app/tests/unit/worktree-clone.test.js +250 -0
  335. package/package.json +38 -36
  336. /package/{WORKSPACES.md → core/workspace-app/WORKSPACES.md} +0 -0
  337. /package/{actions → core/workspace-app/actions}/ai-items.js +0 -0
  338. /package/{actions → core/workspace-app/actions}/audio.js +0 -0
  339. /package/{actions → core/workspace-app/actions}/build-order.js +0 -0
  340. /package/{actions → core/workspace-app/actions}/checks.js +0 -0
  341. /package/{actions → core/workspace-app/actions}/claude-session.js +0 -0
  342. /package/{actions → core/workspace-app/actions}/commands-center.js +0 -0
  343. /package/{actions → core/workspace-app/actions}/composer.js +0 -0
  344. /package/{actions → core/workspace-app/actions}/ddev-addons.js +0 -0
  345. /package/{actions → core/workspace-app/actions}/ddev-mail.js +0 -0
  346. /package/{actions → core/workspace-app/actions}/folders.js +0 -0
  347. /package/{actions → core/workspace-app/actions}/images-svg.js +0 -0
  348. /package/{actions → core/workspace-app/actions}/images.js +0 -0
  349. /package/{actions → core/workspace-app/actions}/navigation.js +0 -0
  350. /package/{actions → core/workspace-app/actions}/node.js +0 -0
  351. /package/{actions → core/workspace-app/actions}/notes.js +0 -0
  352. /package/{actions → core/workspace-app/actions}/plugins.js +0 -0
  353. /package/{actions → core/workspace-app/actions}/project-make.js +0 -0
  354. /package/{actions → core/workspace-app/actions}/row-actions.js +0 -0
  355. /package/{actions → core/workspace-app/actions}/screens.js +0 -0
  356. /package/{actions → core/workspace-app/actions}/video-edit.js +0 -0
  357. /package/{ai-inventory.js → core/workspace-app/ai-inventory.js} +0 -0
  358. /package/{ai-items.js → core/workspace-app/ai-items.js} +0 -0
  359. /package/{assistant-cast.js → core/workspace-app/assistant-cast.js} +0 -0
  360. /package/{assistant-suggestions.js → core/workspace-app/assistant-suggestions.js} +0 -0
  361. /package/{audio-voice.js → core/workspace-app/audio-voice.js} +0 -0
  362. /package/{auth-google.js → core/workspace-app/auth-google.js} +0 -0
  363. /package/{build-ai.js → core/workspace-app/build-ai.js} +0 -0
  364. /package/{build-order-page.js → core/workspace-app/build-order-page.js} +0 -0
  365. /package/{build-order.js → core/workspace-app/build-order.js} +0 -0
  366. /package/{builder-args.js → core/workspace-app/builder-args.js} +0 -0
  367. /package/{changelog.js → core/workspace-app/changelog.js} +0 -0
  368. /package/{chat-threads.js → core/workspace-app/chat-threads.js} +0 -0
  369. /package/{checks.js → core/workspace-app/checks.js} +0 -0
  370. /package/{claude-args.js → core/workspace-app/claude-args.js} +0 -0
  371. /package/{claude-sessions.js → core/workspace-app/claude-sessions.js} +0 -0
  372. /package/{command-author.js → core/workspace-app/command-author.js} +0 -0
  373. /package/{command-block.js → core/workspace-app/command-block.js} +0 -0
  374. /package/{commands → core/workspace-app/commands}/defaults.yml +0 -0
  375. /package/{commands-page.js → core/workspace-app/commands-page.js} +0 -0
  376. /package/{commands.js → core/workspace-app/commands.js} +0 -0
  377. /package/{cucumber.js → core/workspace-app/cucumber.js} +0 -0
  378. /package/{ddev-addons-page.js → core/workspace-app/ddev-addons-page.js} +0 -0
  379. /package/{ddev-addons.js → core/workspace-app/ddev-addons.js} +0 -0
  380. /package/{ddev-custom-commands.js → core/workspace-app/ddev-custom-commands.js} +0 -0
  381. /package/{ddev-domains.js → core/workspace-app/ddev-domains.js} +0 -0
  382. /package/{ddev-import.js → core/workspace-app/ddev-import.js} +0 -0
  383. /package/{ddev-mail-page.js → core/workspace-app/ddev-mail-page.js} +0 -0
  384. /package/{ddev-mail.js → core/workspace-app/ddev-mail.js} +0 -0
  385. /package/{ddev-options.js → core/workspace-app/ddev-options.js} +0 -0
  386. /package/{ddev-snapshots.js → core/workspace-app/ddev-snapshots.js} +0 -0
  387. /package/{ddev.js → core/workspace-app/ddev.js} +0 -0
  388. /package/{docs → core/workspace-app/docs}/DEVELOPER-GUIDE.md +0 -0
  389. /package/{docs → core/workspace-app/docs}/README.md +0 -0
  390. /package/{docs → core/workspace-app/docs}/REFERENCE.md +0 -0
  391. /package/{docs → core/workspace-app/docs}/USER-GUIDE.md +0 -0
  392. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-board.png +0 -0
  393. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-coffee.png +0 -0
  394. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-colours.png +0 -0
  395. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-icons.png +0 -0
  396. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-moves.png +0 -0
  397. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-pick-cookieman.png +0 -0
  398. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-settings-voices.png +0 -0
  399. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-status.png +0 -0
  400. /package/{docs → core/workspace-app/docs}/screenshots/create-card/create-card.png +0 -0
  401. /package/{docs → core/workspace-app/docs}/screenshots/create-card/start-ai.png +0 -0
  402. /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-address.png +0 -0
  403. /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-worktree-off.png +0 -0
  404. /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-worktree-on.png +0 -0
  405. /package/{docs → core/workspace-app/docs}/screenshots/guide-ddev-menu.png +0 -0
  406. /package/{docs → core/workspace-app/docs}/screenshots/guide-domains.png +0 -0
  407. /package/{docs → core/workspace-app/docs}/screenshots/guide-home.png +0 -0
  408. /package/{docs → core/workspace-app/docs}/screenshots/guide-ide-menu.png +0 -0
  409. /package/{docs → core/workspace-app/docs}/screenshots/guide-remove-refusal.png +0 -0
  410. /package/{docs → core/workspace-app/docs}/screenshots/guide-rows-worktree.png +0 -0
  411. /package/{docs → core/workspace-app/docs}/screenshots/guide-screens.png +0 -0
  412. /package/{docs → core/workspace-app/docs}/screenshots/guide-settings.png +0 -0
  413. /package/{docs → core/workspace-app/docs}/screenshots/guide-workspace-page.png +0 -0
  414. /package/{docs → core/workspace-app/docs}/screenshots/home/card-settings.png +0 -0
  415. /package/{docs → core/workspace-app/docs}/screenshots/home/drag-reorder.png +0 -0
  416. /package/{docs → core/workspace-app/docs}/screenshots/home/edit-card.png +0 -0
  417. /package/{docs → core/workspace-app/docs}/screenshots/images/claude-code-image.png +0 -0
  418. /package/{docs → core/workspace-app/docs}/screenshots/images/edit-with-ai.png +0 -0
  419. /package/{docs → core/workspace-app/docs}/screenshots/images/gallery.png +0 -0
  420. /package/{docs → core/workspace-app/docs}/screenshots/images/generate-description.png +0 -0
  421. /package/{docs → core/workspace-app/docs}/screenshots/images/generate-plan.png +0 -0
  422. /package/{docs → core/workspace-app/docs}/screenshots/images/providers.png +0 -0
  423. /package/{docs → core/workspace-app/docs}/screenshots/images/svg-form.png +0 -0
  424. /package/{docs → core/workspace-app/docs}/screenshots/images/svg-result.png +0 -0
  425. /package/{docs → core/workspace-app/docs}/screenshots/images/upload.png +0 -0
  426. /package/{docs → core/workspace-app/docs}/screenshots/new-folder/2-form.png +0 -0
  427. /package/{docs → core/workspace-app/docs}/screenshots/new-folder/8-ddev-options.png +0 -0
  428. /package/{docs → core/workspace-app/docs}/screenshots/new-folder/files-folder.png +0 -0
  429. /package/{docs → core/workspace-app/docs}/screenshots/projects/ddev-custom-commands.png +0 -0
  430. /package/{docs → core/workspace-app/docs}/screenshots/projects/state-chip-stop.png +0 -0
  431. /package/{docs → core/workspace-app/docs}/screenshots/readme/dashboard-dark.png +0 -0
  432. /package/{docs → core/workspace-app/docs}/screenshots/readme/dashboard-light.png +0 -0
  433. /package/{docs → core/workspace-app/docs}/screenshots/readme/dev-dark.png +0 -0
  434. /package/{docs → core/workspace-app/docs}/screenshots/readme/dev-light.png +0 -0
  435. /package/{docs → core/workspace-app/docs}/screenshots/readme/docs-dark.png +0 -0
  436. /package/{docs → core/workspace-app/docs}/screenshots/readme/docs-light.png +0 -0
  437. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/ai.svg +0 -0
  438. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/code.svg +0 -0
  439. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/docs.svg +0 -0
  440. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/services.svg +0 -0
  441. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/sites.svg +0 -0
  442. /package/{docs → core/workspace-app/docs}/screenshots/readme/test-report-dark.png +0 -0
  443. /package/{docs → core/workspace-app/docs}/screenshots/readme/test-report-light.png +0 -0
  444. /package/{docs → core/workspace-app/docs}/screenshots/readme/test-scenarios.png +0 -0
  445. /package/{docs → core/workspace-app/docs}/screenshots/readme/test-steps.png +0 -0
  446. /package/{docs → core/workspace-app/docs}/screenshots/readme/videos-dark.png +0 -0
  447. /package/{docs → core/workspace-app/docs}/screenshots/readme/videos-light.png +0 -0
  448. /package/{docs → core/workspace-app/docs}/screenshots/screens-menu.png +0 -0
  449. /package/{docs → core/workspace-app/docs}/screenshots/screens-new.png +0 -0
  450. /package/{docs → core/workspace-app/docs}/screenshots/settings/auth-google-lists.png +0 -0
  451. /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-1-row.png +0 -0
  452. /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-2-confirm.png +0 -0
  453. /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-3-type-name.png +0 -0
  454. /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-4-type-yes.png +0 -0
  455. /package/{event-log.js → core/workspace-app/event-log.js} +0 -0
  456. /package/{files-browser.js → core/workspace-app/files-browser.js} +0 -0
  457. /package/{folders.js → core/workspace-app/folders.js} +0 -0
  458. /package/{format.js → core/workspace-app/format.js} +0 -0
  459. /package/{github-auth.js → core/workspace-app/github-auth.js} +0 -0
  460. /package/{html.js → core/workspace-app/html.js} +0 -0
  461. /package/{icons.js → core/workspace-app/icons.js} +0 -0
  462. /package/{images-ai.js → core/workspace-app/images-ai.js} +0 -0
  463. /package/{images-create.js → core/workspace-app/images-create.js} +0 -0
  464. /package/{images-page.js → core/workspace-app/images-page.js} +0 -0
  465. /package/{images-records.js → core/workspace-app/images-records.js} +0 -0
  466. /package/{images-render.js → core/workspace-app/images-render.js} +0 -0
  467. /package/{images-svg-core.js → core/workspace-app/images-svg-core.js} +0 -0
  468. /package/{images-svg-sanitize.js → core/workspace-app/images-svg-sanitize.js} +0 -0
  469. /package/{images-svg.js → core/workspace-app/images-svg.js} +0 -0
  470. /package/{images.js → core/workspace-app/images.js} +0 -0
  471. /package/{jobs.js → core/workspace-app/jobs.js} +0 -0
  472. /package/{linger.js → core/workspace-app/linger.js} +0 -0
  473. /package/{lists.js → core/workspace-app/lists.js} +0 -0
  474. /package/{media-info.js → core/workspace-app/media-info.js} +0 -0
  475. /package/{navigation-page.js → core/workspace-app/navigation-page.js} +0 -0
  476. /package/{navigation.js → core/workspace-app/navigation.js} +0 -0
  477. /package/{notes.js → core/workspace-app/notes.js} +0 -0
  478. /package/{palette-index.js → core/workspace-app/palette-index.js} +0 -0
  479. /package/{playwright.config.js → core/workspace-app/playwright.config.js} +0 -0
  480. /package/{plugin-install.js → core/workspace-app/plugin-install.js} +0 -0
  481. /package/{plugin-loader.js → core/workspace-app/plugin-loader.js} +0 -0
  482. /package/{plugin-manifest.js → core/workspace-app/plugin-manifest.js} +0 -0
  483. /package/{plugin-settings.js → core/workspace-app/plugin-settings.js} +0 -0
  484. /package/{plugins → core/workspace-app/plugins}/workspace-notes/index.js +0 -0
  485. /package/{project-make.js → core/workspace-app/project-make.js} +0 -0
  486. /package/{project-name.js → core/workspace-app/project-name.js} +0 -0
  487. /package/{public → core/workspace-app/public}/assistant-avatar-moves.js +0 -0
  488. /package/{public → core/workspace-app/public}/assistant-avatar-ui.js +0 -0
  489. /package/{public → core/workspace-app/public}/assistant-avatar.js +0 -0
  490. /package/{public → core/workspace-app/public}/avatar/druplicon.vrm +0 -0
  491. /package/{public → core/workspace-app/public}/css/base.css +0 -0
  492. /package/{public → core/workspace-app/public}/css/components/ai-assistant.css +0 -0
  493. /package/{public → core/workspace-app/public}/css/components/assistant-avatar.css +0 -0
  494. /package/{public → core/workspace-app/public}/css/components/assistant-views.css +0 -0
  495. /package/{public → core/workspace-app/public}/css/components/build-order.css +0 -0
  496. /package/{public → core/workspace-app/public}/css/components/clone-as-a-git-worktree.css +0 -0
  497. /package/{public → core/workspace-app/public}/css/components/command-palette.css +0 -0
  498. /package/{public → core/workspace-app/public}/css/components/commands-center.css +0 -0
  499. /package/{public → core/workspace-app/public}/css/components/confirm-dialog.css +0 -0
  500. /package/{public → core/workspace-app/public}/css/components/create-card.css +0 -0
  501. /package/{public → core/workspace-app/public}/css/components/ddev-menu.css +0 -0
  502. /package/{public → core/workspace-app/public}/css/components/deep-chat.css +0 -0
  503. /package/{public → core/workspace-app/public}/css/components/density.css +0 -0
  504. /package/{public → core/workspace-app/public}/css/components/floating-assistant-workspace-pages.css +0 -0
  505. /package/{public → core/workspace-app/public}/css/components/folders.css +0 -0
  506. /package/{public → core/workspace-app/public}/css/components/full-height-left-assistant-sidebar-all-pages.css +0 -0
  507. /package/{public → core/workspace-app/public}/css/components/full-height-right-actions-rail-pages-that-have-actions.css +0 -0
  508. /package/{public → core/workspace-app/public}/css/components/grid-and-list.css +0 -0
  509. /package/{public → core/workspace-app/public}/css/components/help-page.css +0 -0
  510. /package/{public → core/workspace-app/public}/css/components/hero.css +0 -0
  511. /package/{public → core/workspace-app/public}/css/components/images.css +0 -0
  512. /package/{public → core/workspace-app/public}/css/components/layout-rhythm-and-spacing-polish.css +0 -0
  513. /package/{public → core/workspace-app/public}/css/components/mic-on-any-field-that-wants-typing.css +0 -0
  514. /package/{public → core/workspace-app/public}/css/components/modal-fit.css +0 -0
  515. /package/{public → core/workspace-app/public}/css/components/page-width.css +0 -0
  516. /package/{public → core/workspace-app/public}/css/components/plugins-page.css +0 -0
  517. /package/{public → core/workspace-app/public}/css/components/project-cards.css +0 -0
  518. /package/{public → core/workspace-app/public}/css/components/project-rows.css +0 -0
  519. /package/{public → core/workspace-app/public}/css/components/reordering-the-workspace-cards.css +0 -0
  520. /package/{public → core/workspace-app/public}/css/components/responsive-home-and-the-workspace-pages.css +0 -0
  521. /package/{public → core/workspace-app/public}/css/components/running-commands-as-toasts.css +0 -0
  522. /package/{public → core/workspace-app/public}/css/components/settings-editor-core-config-yml.css +0 -0
  523. /package/{public → core/workspace-app/public}/css/components/short-results-as-a-toast-at-the-top.css +0 -0
  524. /package/{public → core/workspace-app/public}/css/components/sound-player.css +0 -0
  525. /package/{public → core/workspace-app/public}/css/components/suggest-agents-skills-commands.css +0 -0
  526. /package/{public → core/workspace-app/public}/css/components/tab-modal.css +0 -0
  527. /package/{public → core/workspace-app/public}/css/components/terminals.css +0 -0
  528. /package/{public → core/workspace-app/public}/css/components/test-report-media-one-file-per-row-paged.css +0 -0
  529. /package/{public → core/workspace-app/public}/css/components/top-toolbar-logo-breadcrumb.css +0 -0
  530. /package/{public → core/workspace-app/public}/css/components/video-edit.css +0 -0
  531. /package/{public → core/workspace-app/public}/css/components/web-ide-open-with.css +0 -0
  532. /package/{public → core/workspace-app/public}/css/components/working-indicators.css +0 -0
  533. /package/{public → core/workspace-app/public}/css/components/workspace-cards.css +0 -0
  534. /package/{public → core/workspace-app/public}/favicon.ico +0 -0
  535. /package/{public → core/workspace-app/public}/favicon.png +0 -0
  536. /package/{public → core/workspace-app/public}/htmx.min.js +0 -0
  537. /package/{public → core/workspace-app/public}/logo.png +0 -0
  538. /package/{public → core/workspace-app/public}/media-player.js +0 -0
  539. /package/{public → core/workspace-app/public}/mic.js +0 -0
  540. /package/{public → core/workspace-app/public}/narration.js +0 -0
  541. /package/{public → core/workspace-app/public}/palette.js +0 -0
  542. /package/{public → core/workspace-app/public}/sortable.js +0 -0
  543. /package/{public → core/workspace-app/public}/suggest.js +0 -0
  544. /package/{public → core/workspace-app/public}/terminal.js +0 -0
  545. /package/{public → core/workspace-app/public}/themes/default/theme.css +0 -0
  546. /package/{public → core/workspace-app/public}/themes/ember/theme.css +0 -0
  547. /package/{public → core/workspace-app/public}/themes/press/theme.css +0 -0
  548. /package/{public → core/workspace-app/public}/themes/slate/theme.css +0 -0
  549. /package/{public → core/workspace-app/public}/touch-icon.png +0 -0
  550. /package/{public → core/workspace-app/public}/ui.js +0 -0
  551. /package/{public → core/workspace-app/public}/vendor/ace/LICENSE.txt +0 -0
  552. /package/{public → core/workspace-app/public}/vendor/ace/ace.js +0 -0
  553. /package/{public → core/workspace-app/public}/vendor/ace/ext-language_tools.js +0 -0
  554. /package/{public → core/workspace-app/public}/vendor/ace/ext-searchbox.js +0 -0
  555. /package/{public → core/workspace-app/public}/vendor/ace/mode-css.js +0 -0
  556. /package/{public → core/workspace-app/public}/vendor/ace/mode-html.js +0 -0
  557. /package/{public → core/workspace-app/public}/vendor/ace/mode-javascript.js +0 -0
  558. /package/{public → core/workspace-app/public}/vendor/ace/mode-markdown.js +0 -0
  559. /package/{public → core/workspace-app/public}/vendor/ace/mode-sh.js +0 -0
  560. /package/{public → core/workspace-app/public}/vendor/ace/mode-yaml.js +0 -0
  561. /package/{public → core/workspace-app/public}/vendor/ace/theme-textmate.js +0 -0
  562. /package/{public → core/workspace-app/public}/vendor/ace/theme-tomorrow_night.js +0 -0
  563. /package/{public → core/workspace-app/public}/vendor/ace/worker-yaml.js +0 -0
  564. /package/{public → core/workspace-app/public}/vendor/deep-chat.LICENSE +0 -0
  565. /package/{public → core/workspace-app/public}/vendor/deep-chat.bundle.js +0 -0
  566. /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-LICENSE.txt +0 -0
  567. /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-latin-400-italic.woff2 +0 -0
  568. /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-latin-400-normal.woff2 +0 -0
  569. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-LICENSE.txt +0 -0
  570. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-400-italic.woff2 +0 -0
  571. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-400-normal.woff2 +0 -0
  572. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-600-italic.woff2 +0 -0
  573. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-600-normal.woff2 +0 -0
  574. /package/{public → core/workspace-app/public}/vendor/fonts/jetbrains-mono-LICENSE.txt +0 -0
  575. /package/{public → core/workspace-app/public}/vendor/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
  576. /package/{public → core/workspace-app/public}/vendor/fonts/ubuntu-mono-LICENSE.txt +0 -0
  577. /package/{public → core/workspace-app/public}/vendor/fonts/ubuntu-mono-latin-wght-normal.woff2 +0 -0
  578. /package/{public → core/workspace-app/public}/vendor/tabler-LICENSE.txt +0 -0
  579. /package/{public → core/workspace-app/public}/vendor/tabler-sprite.svg +0 -0
  580. /package/{public → core/workspace-app/public}/vendor/three/LICENSE +0 -0
  581. /package/{public → core/workspace-app/public}/vendor/three/addons/loaders/GLTFLoader.js +0 -0
  582. /package/{public → core/workspace-app/public}/vendor/three/addons/utils/BufferGeometryUtils.js +0 -0
  583. /package/{public → core/workspace-app/public}/vendor/three/addons/utils/SkeletonUtils.js +0 -0
  584. /package/{public → core/workspace-app/public}/vendor/three/three.core.min.js +0 -0
  585. /package/{public → core/workspace-app/public}/vendor/three/three.module.min.js +0 -0
  586. /package/{public → core/workspace-app/public}/vendor/three-vrm/LICENSE +0 -0
  587. /package/{public → core/workspace-app/public}/vendor/three-vrm/three-vrm.module.min.js +0 -0
  588. /package/{public → core/workspace-app/public}/vendor/uikit-icons.min.js +0 -0
  589. /package/{public → core/workspace-app/public}/vendor/uikit.min.css +0 -0
  590. /package/{public → core/workspace-app/public}/vendor/uikit.min.js +0 -0
  591. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/bookmark-outlined.svg +0 -0
  592. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/headset.svg +0 -0
  593. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/menu.svg +0 -0
  594. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/pause.svg +0 -0
  595. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/play.svg +0 -0
  596. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/share.svg +0 -0
  597. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/sound-off.svg +0 -0
  598. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/sound-on.svg +0 -0
  599. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/stop.svg +0 -0
  600. /package/{public → core/workspace-app/public}/vendor/xterm/addon-fit.js +0 -0
  601. /package/{public → core/workspace-app/public}/vendor/xterm/addon-unicode11.js +0 -0
  602. /package/{public → core/workspace-app/public}/vendor/xterm/addon-web-links.js +0 -0
  603. /package/{public → core/workspace-app/public}/vendor/xterm/xterm.css +0 -0
  604. /package/{public → core/workspace-app/public}/vendor/xterm/xterm.js +0 -0
  605. /package/{rag.js → core/workspace-app/rag.js} +0 -0
  606. /package/{reader.js → core/workspace-app/reader.js} +0 -0
  607. /package/{repo-blobs.js → core/workspace-app/repo-blobs.js} +0 -0
  608. /package/{report-pdf.js → core/workspace-app/report-pdf.js} +0 -0
  609. /package/{row-layout.js → core/workspace-app/row-layout.js} +0 -0
  610. /package/{screenrc → core/workspace-app/screenrc} +0 -0
  611. /package/{screens.js → core/workspace-app/screens.js} +0 -0
  612. /package/{scripts → core/workspace-app/scripts}/code-server-start.sh +0 -0
  613. /package/{scripts → core/workspace-app/scripts}/images-claude-finish.js +0 -0
  614. /package/{scripts → core/workspace-app/scripts}/screen-host.sh +0 -0
  615. /package/{scripts → core/workspace-app/scripts}/screen-runner.js +0 -0
  616. /package/{scripts → core/workspace-app/scripts}/screen-then.js +0 -0
  617. /package/{scripts → core/workspace-app/scripts}/update.sh +0 -0
  618. /package/{settings-file.js → core/workspace-app/settings-file.js} +0 -0
  619. /package/{speech.js → core/workspace-app/speech.js} +0 -0
  620. /package/{tab-modal.js → core/workspace-app/tab-modal.js} +0 -0
  621. /package/{test-reports.js → core/workspace-app/test-reports.js} +0 -0
  622. /package/{themes.js → core/workspace-app/themes.js} +0 -0
  623. /package/{transcripts.js → core/workspace-app/transcripts.js} +0 -0
  624. /package/{urls.js → core/workspace-app/urls.js} +0 -0
  625. /package/{validate.js → core/workspace-app/validate.js} +0 -0
  626. /package/{version-check.js → core/workspace-app/version-check.js} +0 -0
  627. /package/{video-edit.js → core/workspace-app/video-edit.js} +0 -0
  628. /package/{waiting.js → core/workspace-app/waiting.js} +0 -0
  629. /package/{workspace-card-tools.js → core/workspace-app/workspace-card-tools.js} +0 -0
  630. /package/{workspace-delete.js → core/workspace-app/workspace-delete.js} +0 -0
  631. /package/{workspace-types.js → core/workspace-app/workspace-types.js} +0 -0
  632. /package/{workspaces.js → core/workspace-app/workspaces.js} +0 -0
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env bash
2
+ ## Plugins of the Webship Workspace dashboard: require, activate, install, configure.
3
+ ##
4
+ ## bash core/scripts/plugins.sh --list what is installed, activated, placed
5
+ ## bash core/scripts/plugins.sh --require <npm spec> npm install into the dashboard
6
+ ## (github:webship/workspace-upsun, a tarball, a path)
7
+ ## bash core/scripts/plugins.sh --activate <name> plugins.<name>.enabled: true in settings.yml
8
+ ## bash core/scripts/plugins.sh --install <name> place what its manifest names in the workspace
9
+ ## bash core/scripts/plugins.sh --configure <name> its own settings file, created from the template
10
+ ## bash core/scripts/plugins.sh --deactivate <name> enabled: false (the files stay)
11
+ ## bash core/scripts/plugins.sh --uninstall <name> remove what --install placed
12
+ ## bash core/scripts/plugins.sh --restart restart the dashboard app, so it loads the change
13
+ ##
14
+ ## A plugin is a node package with a `workspacePlugin` manifest in its package.json, kept in its
15
+ ## own repository (github.com/webship/workspace-<name>). The four steps are what it takes to turn a
16
+ ## feature on; --list shows which step a plugin is at. --install is idempotent and says when the
17
+ ## dashboard container needs `ddev restart` (a compose file or host mount it brought).
18
+
19
+ set -u
20
+ WORKSPACE_SCRIPTS="${WORKSPACE_SCRIPTS:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}";
21
+ WORKSPACE_ROOT="${WORKSPACE_ROOT:-$(cd "${WORKSPACE_SCRIPTS}/../.." && pwd)}";
22
+ # The dashboard app lives beside these scripts (not necessarily under WORKSPACE_ROOT: a test points the
23
+ # root at a temporary tree while the code stays here).
24
+ APP="$(cd "${WORKSPACE_SCRIPTS}/../workspace-app" && pwd)";
25
+ SETTINGS="${WORKSPACE_ROOT}/core/config/settings.yml";
26
+
27
+ usage() { sed -n '2,20p' "${BASH_SOURCE[0]}" | sed 's/^## \{0,1\}//'; }
28
+
29
+ # Inside the dashboard container the app runs supervised; on the host there is nothing to restart but
30
+ # the container's process, reached through docker.
31
+ restart_app() {
32
+ # A test drives these verbs against a temporary tree; it must never restart the dashboard that serves.
33
+ [ -n "${WORKSPACE_PLUGINS_NO_RESTART:-}" ] && return 0 ;
34
+ if command -v supervisorctl > /dev/null 2>&1 && supervisorctl status webextradaemons:workspace-app > /dev/null 2>&1 ; then
35
+ supervisorctl restart webextradaemons:workspace-app ;
36
+ elif command -v docker > /dev/null 2>&1 ; then
37
+ docker exec ddev-workspace-web supervisorctl restart webextradaemons:workspace-app 2>/dev/null \
38
+ || echo "The dashboard is not running; it will load the change when it starts." ;
39
+ fi
40
+ }
41
+
42
+ # One settings.yml edit, through the same code the Settings page uses, so comments survive.
43
+ set_plugin_setting() {
44
+ local name="$1" key="$2" value="$3" ;
45
+ ( cd "${APP}" && node -e '
46
+ const [name, key, value] = process.argv.slice(1);
47
+ const { upsertSettingsValue } = require("./settings-file");
48
+ upsertSettingsValue("settings.yml", `plugins.${name}.${key}`, value === "true" ? true : value === "false" ? false : value);
49
+ ' "${name}" "${key}" "${value}" ) ;
50
+ }
51
+
52
+ plugin_module() { ( cd "${APP}" && node plugin-manifest.js --json "$1" 2>/dev/null | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const p=JSON.parse(s||"null");process.stdout.write(p&&p.module?p.module:"")})' ) ; }
53
+ plugin_known() { ( cd "${APP}" && node plugin-manifest.js "$1" > /dev/null 2>&1 ) ; }
54
+ # A plugin that IS a workspace folder names it in its manifest (workspace.key); activating it puts the
55
+ # key on settings.yml's workspaces list (the dashboard's order), deactivating takes it off.
56
+ plugin_workspace_key() { ( cd "${APP}" && node plugin-manifest.js --json "$1" 2>/dev/null | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const p=JSON.parse(s||"null");const w=p&&p.manifest&&p.manifest.workspace;process.stdout.write(w&&w.key?String(w.key):"")})' ) ; }
57
+ set_workspaces_list() {
58
+ local verb="$1" key="$2" ;
59
+ [ -n "${key}" ] || return 0 ;
60
+ ( cd "${APP}" && node -e '
61
+ const [verb, key] = process.argv.slice(1);
62
+ const { upsertSettingsList } = require("./settings-file");
63
+ const { loadSettings } = require("./workspaces");
64
+ const now = (loadSettings().workspaces || []).map(String);
65
+ const next = verb === "add" ? (now.includes(key) ? now : [...now, key]) : now.filter((k) => k !== key);
66
+ if (next.join(",") !== now.join(",")) upsertSettingsList("settings.yml", "workspaces", next);
67
+ process.stdout.write(verb === "add" ? (now.includes(key) ? "" : `Workspace ${key} added to the workspaces list.\n`) : (now.includes(key) ? `Workspace ${key} taken off the workspaces list (the folder and its settings stay).\n` : ""));
68
+ ' "${verb}" "${key}" ) ;
69
+ }
70
+
71
+ verb="${1:-}"; name="${2:-}";
72
+ case "${verb}" in
73
+ -h|--help|'') usage ; exit 0 ;;
74
+
75
+ --list)
76
+ echo "Plugins the dashboard can see (core/workspace-app), and the step each is at:" ;
77
+ ( cd "${APP}" && node -e '
78
+ const { rows, STEPS } = require("./plugins-page");
79
+ for (const p of rows()) {
80
+ const step = p.step >= 3 ? "ready" : `${STEPS[p.step]} · next: ${["activate", "install", "configure"][p.step]}`;
81
+ const missing = p.placed.missing && p.placed.missing.length ? ` (missing ${p.placed.missing.length} placed file(s): --install again)` : "";
82
+ console.log(` ${p.name.padEnd(18)} ${(p.module || p.spec || "-").padEnd(36)} ${(p.version || "").padEnd(8)} ${step}${missing}`);
83
+ }
84
+ ' ) ;;
85
+
86
+ --require)
87
+ [ -n "${name}" ] || { echo "Which package? e.g. --require github:webship/workspace-upsun" ; exit 1 ; } ;
88
+ echo "→ npm install ${name} (core/workspace-app)" ;
89
+ # The plugin repositories are private: let git borrow the gh CLI's login for github.com, the way
90
+ # the commands tooling does, so a github: spec resolves without a token in the environment.
91
+ if command -v gh > /dev/null 2>&1 && gh api user --jq .login > /dev/null 2>&1 ; then
92
+ export GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0="credential.https://github.com.helper" GIT_CONFIG_VALUE_0="!gh auth git-credential" ;
93
+ fi
94
+ ( cd "${APP}" && npm install --no-audit --no-fund "${name}" ) || exit 1 ;
95
+ echo "Required. Next: --activate <name> (the name is the manifest's: --list shows it)." ;;
96
+
97
+ --activate)
98
+ [ -n "${name}" ] || { echo "Which plugin? --list shows them." ; exit 1 ; } ;
99
+ plugin_known "${name}" || { echo "No plugin named '${name}' is installed in the dashboard. --require it first." ; exit 1 ; } ;
100
+ module="$(plugin_module "${name}")" ;
101
+ set_plugin_setting "${name}" enabled true ;
102
+ [ -n "${module}" ] && set_plugin_setting "${name}" module "${module}" ;
103
+ set_workspaces_list add "$(plugin_workspace_key "${name}")" ;
104
+ echo "Activated: plugins.${name} in core/config/settings.yml. Next: --install ${name}." ;;
105
+
106
+ --deactivate)
107
+ [ -n "${name}" ] || { echo "Which plugin?" ; exit 1 ; } ;
108
+ set_plugin_setting "${name}" enabled false ;
109
+ set_workspaces_list remove "$(plugin_workspace_key "${name}")" ;
110
+ echo "Deactivated: plugins.${name}.enabled: false. Its files stay; --uninstall removes them." ;
111
+ restart_app ;;
112
+
113
+ --install)
114
+ [ -n "${name}" ] || { echo "Which plugin? --list shows them." ; exit 1 ; } ;
115
+ out="$( cd "${APP}" && node plugin-install.js install "${name}" )" || { echo "${out}" ; exit 1 ; } ;
116
+ echo "${out}" | grep -v '^RESTART_' ;
117
+ host="${WORKSPACE_SCRIPTS}/plugins/${name}/host-install.sh" ;
118
+ if [ -f "${host}" ] ; then
119
+ echo "→ the host side (${name}):" ;
120
+ bash "${host}" --check || true ;
121
+ fi
122
+ if echo "${out}" | grep -q '^RESTART_NEEDED' ; then
123
+ echo "" ;
124
+ echo "The dashboard container needs a restart for the compose file or host mount this plugin brought:" ;
125
+ echo " cd ${APP} && ddev restart" ;
126
+ else
127
+ restart_app ;
128
+ fi
129
+ echo "Installed. Next: --configure ${name}." ;;
130
+
131
+ --uninstall)
132
+ [ -n "${name}" ] || { echo "Which plugin?" ; exit 1 ; } ;
133
+ ( cd "${APP}" && node plugin-install.js uninstall "${name}" ) | grep -v '^RESTART_' ;
134
+ set_plugin_setting "${name}" enabled false ;
135
+ echo "Uninstalled and deactivated. The package stays in node_modules: npm uninstall <module> in core/workspace-app removes it." ;
136
+ restart_app ;;
137
+
138
+ --configure)
139
+ [ -n "${name}" ] || { echo "Which plugin?" ; exit 1 ; } ;
140
+ file="$( cd "${APP}" && node -e 'const p=require("./plugin-manifest").pluginByName(process.argv[1]);process.stdout.write(p&&p.manifest.settingsFile?p.manifest.settingsFile:"")' "${name}" )" ;
141
+ [ -n "${file}" ] || { echo "${name} has no settings file of its own." ; exit 0 ; } ;
142
+ if [ ! -f "${WORKSPACE_ROOT}/core/config/${file}" ] ; then
143
+ ( cd "${APP}" && node plugin-install.js install "${name}" > /dev/null ) ;
144
+ fi
145
+ echo "Its settings: ${WORKSPACE_ROOT}/core/config/${file}" ;
146
+ echo "Edit it there, or on the dashboard: https://workspace.ddev.site/settings/${file}" ;
147
+ sed 's/^\(.*token.*:\).*/\1 <hidden>/' "${WORKSPACE_ROOT}/core/config/${file}" ;;
148
+
149
+ --restart) restart_app ;;
150
+
151
+ *) usage ; exit 1 ;;
152
+ esac
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Cut the next release of this tooling: stamp the version, tag the branch, publish
4
+ # the release. The stamp is written BEFORE the tag, so a machine can never be on a
5
+ # release while still reporting the one before it.
6
+ #
7
+ # Confirm-gated: without --confirm it prints the plan and creates nothing. A tag
8
+ # and a release page are public and permanent, and neither should be a side effect
9
+ # of asking what would happen.
10
+
11
+ # Bootstrap.
12
+ # Find the workspace tooling from this script, so a fresh clone needs no setup.
13
+ WORKSPACE_SCRIPTS="${WORKSPACE_SCRIPTS:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}";
14
+ source ${WORKSPACE_SCRIPTS}/bootstrap.sh || exit 1 ;
15
+
16
+ ARGPARSE_DESCRIPTION="Release the next tag of this tooling (stamps the version first)"
17
+ source ${WORKSPACE_SCRIPTS}/args/arg-release.sh || exit 1 ;
18
+
19
+ shift $#;
20
+
21
+ CLONE="${WORKSPACE_ROOT}/products/workspace"
22
+ REMOTE='github'
23
+
24
+ if [ ! -d "${CLONE}/.git" ]; then
25
+ echo "No clone at ${CLONE}. Releases are cut from the git checkout, not from the live tree." >&2
26
+ exit 1
27
+ fi
28
+
29
+ REPO="$(release_repo)" || exit 1
30
+
31
+ echo "Checking the clone…"
32
+ release_ready "${CLONE}" "${BRANCH}" "${REMOTE}" || READY=1
33
+
34
+ CURRENT="$(release_current_tag "${CLONE}")"
35
+ if [ -n "${TAG}" ]; then
36
+ NEXT="${TAG}"
37
+ else
38
+ NEXT="$(release_next_tag "${CURRENT}")"
39
+ if [ -z "${NEXT}" ]; then
40
+ echo "Cannot work out the next tag from '${CURRENT:-none}'. Name one with --tag." >&2
41
+ exit 1
42
+ fi
43
+ fi
44
+
45
+ if git -C "${CLONE}" rev-parse -q --verify "refs/tags/${NEXT}" > /dev/null 2>&1 ; then
46
+ echo "${NEXT} already exists. A released tag is never moved." >&2
47
+ exit 1
48
+ fi
49
+
50
+ release_plan "${CLONE}" "${BRANCH}" "${CURRENT}" "${NEXT}" "${REPO}"
51
+
52
+ if [ "${NO_GATE}" != 'yes' ]; then
53
+ release_gate "${CLONE}" || GATED=1
54
+ else
55
+ echo "Gate skipped (--no-gate)."
56
+ fi
57
+
58
+ if [ "${CONFIRM}" != 'yes' ]; then
59
+ echo "Nothing was created. Add --confirm to cut ${NEXT}."
60
+ exit 0
61
+ fi
62
+
63
+ if [ -n "${READY}" ] || [ -n "${GATED}" ]; then
64
+ echo "" >&2
65
+ echo "Refusing to release: the checks above did not pass." >&2
66
+ exit 1
67
+ fi
68
+
69
+ release_cut "${CLONE}" "${BRANCH}" "${NEXT}" "${REPO}" "${NOTES}" "${REMOTE}"
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Keep whole workspace folders on a second disk: storage.second in settings.yml.
4
+ # A moved workspace is a symlink, <root>/<name> -> <storage>/<name>, so nothing else changes.
5
+ #
6
+ # bash core/scripts/storage.sh status (the default)
7
+ # bash core/scripts/storage.sh --move videos copy, verify, swap to a symlink
8
+ # bash core/scripts/storage.sh --remove-pre-move videos
9
+ # bash core/scripts/storage.sh --back videos the reverse
10
+ # bash core/scripts/storage.sh --mounts the dashboard container's mounts
11
+ # bash core/scripts/storage.sh --relink --mounts after the drive got a new mount point
12
+
13
+ # Bootstrap.
14
+ # Find the workspace tooling from this script, so a fresh clone needs no setup.
15
+ WORKSPACE_SCRIPTS="${WORKSPACE_SCRIPTS:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}";
16
+ source ${WORKSPACE_SCRIPTS}/bootstrap.sh || exit 1 ;
17
+
18
+
19
+ ARGPARSE_DESCRIPTION="Keep workspace folders on a second disk (storage.second in settings.yml)"
20
+ source ${WORKSPACE_SCRIPTS}/args/arg-storage.sh || exit 1 ;
21
+
22
+ shift $#;
23
+
24
+ status=0 ;
25
+ [ -n "${MOVE}" ] && { storage_move "${MOVE}" || exit 1 ; } ;
26
+ [ -n "${BACK}" ] && { storage_back "${BACK}" || exit 1 ; } ;
27
+ [ -n "${REMOVE_PRE_MOVE}" ] && { storage_remove_pre_move "${REMOVE_PRE_MOVE}" || status=1 ; } ;
28
+ [ "${RELINK}" == 'yes' ] && { storage_relink || status=1 ; } ;
29
+ # A move or a relink changes what the dashboard has to mount, so --mounts runs last.
30
+ if [ "${MOUNTS}" == 'yes' ] && [ "${DRY_RUN}" != 'yes' ] ; then
31
+ storage_write_mounts || status=1 ;
32
+ elif [ -n "${MOVE}${BACK}" ] && [ "${DRY_RUN}" != 'yes' ] && [ "$(storage_compose)" != "$(cat "$(storage_compose_file)" 2>/dev/null)" ] ; then
33
+ echo "" ;
34
+ echo " ! The dashboard's mounts no longer match. Run: bash ${WORKSPACE_SCRIPTS}/storage.sh --mounts" ;
35
+ fi
36
+ if [ "${STATUS}" == 'yes' ] || [ -z "${MOVE}${BACK}${REMOVE_PRE_MOVE}${RELINK}${MOUNTS}" ] ; then
37
+ storage_status ;
38
+ fi
39
+ exit ${status} ;
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Copy the tooling from the Webship Workspace git clone into the live workspace
4
+ # it is checked out inside — the step that follows every merged PR.
5
+ #
6
+ # ~/workspace/products/workspace the clone: where commits and PRs happen
7
+ # ~/workspace the live tree: where projects are built
8
+ #
9
+ # It syncs the shared core/, each workspace folder's cmd-*.sh, README.md and
10
+ # *.code-workspace, and prunes commands the clone no longer ships. Built
11
+ # project content is never touched.
12
+ #
13
+ # core/config/settings.yml is DELIBERATELY not synced: the live copy holds the
14
+ # real account password and API keys, while the committed one ships CHANGE_ME
15
+ # and sk-change-this placeholders. Only the `workspaces:` list is reconciled,
16
+ # and only by reporting what is missing.
17
+
18
+ # Bootstrap.
19
+ # Find the workspace tooling from this script, so a fresh clone needs no setup.
20
+ WORKSPACE_SCRIPTS="${WORKSPACE_SCRIPTS:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}";
21
+ source ${WORKSPACE_SCRIPTS}/bootstrap.sh || exit 1 ;
22
+
23
+
24
+ ARGPARSE_DESCRIPTION="Sync the workspace tooling from the git clone into the live workspace"
25
+ argparse "$@" <<EOF || exit 1
26
+ parser.add_argument('CLONE_NAME',
27
+ default='workspace',
28
+ nargs='?',
29
+ help='The clone directory inside the products workspace [default %(default)s].')
30
+ parser.add_argument('-p', '--pull',
31
+ action='store_true',
32
+ default=False,
33
+ help='git pull the clone first (fast-forward only), so a merged PR is picked up.')
34
+ parser.add_argument('-n', '--dry-run',
35
+ action='store_true',
36
+ default=False,
37
+ help='Show what would change and copy nothing.')
38
+ parser.add_argument('-s', '--skip-tests',
39
+ action='store_true',
40
+ default=False,
41
+ help='Skip the smoke test that normally runs after the sync.')
42
+ EOF
43
+
44
+ shift $#;
45
+
46
+ # The clone lives in the products workspace: it is a Webship product like any other.
47
+ source_root="${WORKSPACE_ROOT}/products/${CLONE_NAME}";
48
+ # Where this script itself is, so the prune below cannot delete the file it is running from.
49
+ self_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")";
50
+ target_root="${WORKSPACE_ROOT}";
51
+
52
+ if [ ! -d "${source_root}/core/scripts" ]; then
53
+ echo "No workspace clone at ${source_root}.";
54
+ echo "Expected the git checkout of webship/workspace there.";
55
+ exit 1 ;
56
+ fi
57
+
58
+ if [ "${source_root}" == "${target_root}" ]; then
59
+ echo "The clone and the live workspace are the same directory — nothing to sync.";
60
+ exit 1 ;
61
+ fi
62
+
63
+ rsync_flags="-a";
64
+ if [ "${DRY_RUN}" == 'yes' ] ; then
65
+ rsync_flags="-a --dry-run --itemize-changes";
66
+ echo "DRY RUN — nothing will be written.";
67
+ fi
68
+
69
+ echo "*---------------------------------------------------------------------*";
70
+ echo " Sync tooling";
71
+ echo " from ${source_root}";
72
+ echo " to ${target_root}";
73
+ echo "*---------------------------------------------------------------------*";
74
+
75
+ if [ "${PULL}" == 'yes' ] ; then
76
+ echo "";
77
+ echo "Updating the clone…";
78
+ (cd "${source_root}" && git pull --ff-only) || {
79
+ echo "git pull failed — resolve the clone's state first, then re-run.";
80
+ exit 1 ;
81
+ }
82
+ fi
83
+
84
+ echo "";
85
+ echo "Clone is at: $(cd "${source_root}" && git log --oneline -1 2>/dev/null || echo 'not a git checkout')";
86
+
87
+ # Shared scripts: mirrored, so a deleted function or arg file disappears here too.
88
+ echo "";
89
+ echo "→ core/scripts";
90
+ rsync ${rsync_flags} --delete "${source_root}/core/scripts/" "${target_root}/core/scripts/" ;
91
+
92
+ # Per-workspace settings only. settings.yml stays local: it holds real secrets.
93
+ echo "→ core/config/workspace.*.settings.yml";
94
+ rsync ${rsync_flags} "${source_root}"/core/config/workspace.*.settings.yml "${target_root}/core/config/" ;
95
+
96
+ # The dashboard, minus what belongs to the running instance.
97
+ echo "→ core/workspace-app";
98
+ rsync ${rsync_flags} --exclude=node_modules --exclude=actions.log --exclude=logs --exclude=.chats --exclude=.memory --exclude=.voice-cache --exclude=.auth \
99
+ "${source_root}/core/workspace-app/" "${target_root}/core/workspace-app/" ;
100
+
101
+ # Each workspace folder's commands and docs — never its built projects.
102
+ # AGENTS.md and CLAUDE.md come across too: they are what a Claude Code session
103
+ # started anywhere under a workspace reads to find its context and its rules.
104
+ echo "→ <workspace>/cmd-*.sh, README.md, AGENTS.md, CLAUDE.md, *.code-workspace";
105
+ for workspace_dir in "${source_root}"/*/ ; do
106
+ workspace_name=$(basename "${workspace_dir}");
107
+ # A workspace on second storage whose drive is not mounted: writing through the dangling link would
108
+ # recreate its folder under the mount point, on the wrong disk. Skip it and say so.
109
+ if [ -L "${target_root}/${workspace_name}" ] && [ ! -d "${target_root}/${workspace_name}" ] ; then
110
+ echo " skipped ${workspace_name}: it links to $(readlink "${target_root}/${workspace_name}"), which is not mounted" ;
111
+ continue ;
112
+ fi
113
+ [ -d "${target_root}/${workspace_name}" ] || mkdir -p "${target_root}/${workspace_name}" ;
114
+ # scripts/ carries the assets a builder copies into a project. It is empty for
115
+ # the site templates now that the front-end libraries come from Composer, but
116
+ # the include stays: a builder that needs to ship an asset again should not
117
+ # have to rediscover why the file never reached the live tree.
118
+ rsync ${rsync_flags} --include='cmd-*.sh' --include='README.md' --include='AGENTS.md' \
119
+ --include='CLAUDE.md' --include='*.code-workspace' \
120
+ --include='scripts/' --include='scripts/**' \
121
+ --exclude='*' "${workspace_dir}" "${target_root}/${workspace_name}/" ;
122
+ done
123
+
124
+ # The specs workspace is the one whose CONTENT is the deliverable rather than its commands: the
125
+ # templates every spec starts from, and the constitution of each product. Those are committed, so
126
+ # a --pull that skipped them left a machine with the command and none of the material it reads —
127
+ # `-a constitution` would answer "no template", on a tree that has one in the repository.
128
+ #
129
+ # Only the two shared kinds. A numbered spec is about one change in one tree and belongs to
130
+ # whoever is making it.
131
+ if [ -d "${source_root}/specs" ] ; then
132
+ echo "→ specs/_defaults and every 00-constitution.md";
133
+ rsync ${rsync_flags} --include='_defaults/' --include='_defaults/**' \
134
+ --include='*/' --include='00-constitution.md' \
135
+ --exclude='*' "${source_root}/specs/" "${target_root}/specs/" ;
136
+ fi
137
+
138
+ # core/workspace-app was just mirrored, and two files in it carry THIS machine's docker
139
+ # GID — the Dockerfile's group and the compose group_add. The clone cannot know that
140
+ # number, so a pull would leave the dashboard unable to reach Docker: every project
141
+ # Stopped, no Start/Stop item, and nothing to suggest a permissions problem. Re-align
142
+ # it here, where the overwrite happened.
143
+ if [ -f "${WORKSPACE_SCRIPTS}/docker-gid.sh" ] && [ "${DRY_RUN}" != 'yes' ] ; then
144
+ echo "";
145
+ echo "→ the dashboard's Docker access";
146
+ bash "${WORKSPACE_SCRIPTS}/docker-gid.sh" || true ;
147
+ fi
148
+
149
+ # The same for the second storage: the mounts that let the dashboard follow a workspace symlink onto
150
+ # another disk are this machine's paths, generated from storage.second. Rewritten only when they differ.
151
+ if [ -f "${WORKSPACE_SCRIPTS}/storage.sh" ] && [ "${DRY_RUN}" != 'yes' ] ; then
152
+ bash "${WORKSPACE_SCRIPTS}/storage.sh" --mounts --quiet || true ;
153
+ fi
154
+
155
+ # The tree's own root CLAUDE.md — the file that tells a session how to work out which
156
+ # workspace it is in. Placed only when missing: it is a live-tree file, and
157
+ # overwriting it would discard whatever this machine has added.
158
+ if [ ! -f "${target_root}/CLAUDE.md" ] && [ -f "${source_root}/core/templates/workspace-root-CLAUDE.md" ] ; then
159
+ cp "${source_root}/core/templates/workspace-root-CLAUDE.md" "${target_root}/CLAUDE.md" ;
160
+ echo " placed ${target_root}/CLAUDE.md from the template (it was missing)" ;
161
+ fi
162
+
163
+ # Commands the clone dropped (a removed builder, a renamed tool).
164
+ echo "";
165
+ echo "→ pruning commands the clone no longer ships";
166
+ pruned=0;
167
+ cd "${target_root}";
168
+ for command_file in */cmd-*.sh ; do
169
+ [ -f "${command_file}" ] || continue ;
170
+ # Never delete the script performing the sync. This is not hypothetical: the release
171
+ # that moved autostart, brand-tokens and sync-tooling into core/scripts is pulled BY
172
+ # the old products/cmd-tools-sync-tooling.sh, which the clone no longer ships — and
173
+ # bash reads a script as it executes, so removing it mid-run can truncate the rest.
174
+ if [ "$(cd "$(dirname "${command_file}")" && pwd)/$(basename "${command_file}")" == "${self_path}" ] ; then
175
+ echo " keeping ${command_file} — it is running this sync. Delete it by hand, then use";
176
+ echo " core/scripts/$(basename "${command_file}" | sed 's/^cmd-tools-//') from now on.";
177
+ continue ;
178
+ fi
179
+ if [ ! -f "${source_root}/${command_file}" ]; then
180
+ if [ "${DRY_RUN}" == 'yes' ] ; then
181
+ echo " would remove ${command_file}";
182
+ else
183
+ rm -f "${command_file}";
184
+ fi
185
+ pruned=$((pruned+1));
186
+ fi
187
+ done
188
+ echo " ${pruned} stale command(s)";
189
+
190
+ # settings.yml is not copied, so a workspace added in the clone would be
191
+ # invisible here. Report it rather than editing a file with real secrets.
192
+ echo "";
193
+ echo "→ checking the workspaces: list";
194
+ missing_workspaces="";
195
+ for workspace_name in $(grep -A100 '^workspaces:' "${source_root}/core/config/settings.yml" | grep '^ - ' | sed 's/^ - //') ; do
196
+ if ! grep -q "^ - ${workspace_name}$" "${target_root}/core/config/settings.yml" ; then
197
+ missing_workspaces="${missing_workspaces} ${workspace_name}";
198
+ fi
199
+ done
200
+ if [ -n "${missing_workspaces}" ]; then
201
+ echo " MISSING from your ${target_root}/core/config/settings.yml:${missing_workspaces}";
202
+ echo " Add them to its workspaces: list — it is not synced because it holds your real";
203
+ echo " account password and API keys. The list order is the dashboard card order.";
204
+ else
205
+ echo " up to date";
206
+ fi
207
+
208
+ if [ "${DRY_RUN}" == 'yes' ] ; then
209
+ echo "";
210
+ echo "DRY RUN — nothing was written.";
211
+ exit 0 ;
212
+ fi
213
+
214
+ echo "";
215
+ # Stamp the version this pull brought in. The clone IS a checkout, so the tag it sits on
216
+ # is the honest answer — and without this a machine that keeps up to date via the clone
217
+ # reports "(untracked)" to update.sh for ever and is told to update to what it already has.
218
+ if command -v workspace_clone_version > /dev/null 2>&1 ; then
219
+ sync_tag="$(workspace_clone_version "${source_root}")" ;
220
+ if [ -n "${sync_tag}" ] ; then
221
+ WORKSPACE_PATH="${target_root}/core" workspace_version_stamp "${sync_tag}" \
222
+ && echo "→ recorded this tree as ${sync_tag}" ;
223
+ else
224
+ echo "→ the clone is on no tag, so the version is not recorded" ;
225
+ fi
226
+ fi
227
+
228
+ if [ ! "${SKIP_TESTS}" == 'yes' ] ; then
229
+ echo "";
230
+ echo "→ smoke test";
231
+ (cd "${target_root}" && bash core/scripts/tests/cmd-smoke-test.sh 2>&1 | tail -3) ;
232
+ fi
233
+
234
+ echo "";
235
+ echo "*---------------------------------------------------------------------*";
236
+ echo " Synced.";
237
+ echo "";
238
+ echo " If core/workspace-app/.ddev/ or its Dockerfile changed, rebuild the";
239
+ echo " dashboard container so it picks that up — when no build jobs are";
240
+ echo " running, because the job registry is in memory:";
241
+ echo " cd ${target_root}/core/workspace-app && ddev restart";
242
+ echo "";
243
+ echo " For a change to server.js or workspaces.js alone, restarting the app";
244
+ echo " is enough (supervisord respawns it):";
245
+ echo " docker exec ddev-workspace-web sh -c 'pkill -f \"node server.js\"'";
246
+ echo "*---------------------------------------------------------------------*";
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env bash
2
+ # Smoke-test every cmd-*.sh in every workspace folder, plus the machine-level scripts
3
+ # in core/scripts that used to be cmd-*.sh in one.
4
+ #
5
+ # For each script:
6
+ # 1. bash -n — syntax check (always)
7
+ # 2. --help execution — only for argparse-based scripts (safe: argparse
8
+ # prints usage and exits before any real work),
9
+ # which exercises bootstrap.sh, parse_yaml, the
10
+ # workspace + distribution configs and arg-*.sh
11
+ # 3. workspace-name — builder scripts must carry the "# workspace-name:"
12
+ # header the dashboard shows in Build dropdowns
13
+ #
14
+ # Exit code: number of failing scripts (0 = all green).
15
+
16
+ # Find the workspace tooling from this script, so a fresh clone needs no setup.
17
+ WORKSPACE_SCRIPTS="${WORKSPACE_SCRIPTS:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
18
+ source ${WORKSPACE_SCRIPTS}/bootstrap.sh || exit 1
19
+
20
+ pass=0; fail=0; failures=()
21
+
22
+ # The registered workspaces, plus commands/ — which is a Settings section rather than
23
+ # a workspace, but still ships a cmd-*.sh that must pass the same checks. Without it
24
+ # here, deregistering that folder silently dropped its script from the run.
25
+ # The machine-level scripts: autostart.sh and sync-tooling.sh were
26
+ # cmd-*.sh in products/ until they moved here, and moving a script out of a workspace
27
+ # folder must not quietly drop it from the run — that happened once already, to
28
+ # commands/. Named explicitly rather than globbed, because core/scripts is also full
29
+ # of libraries and bootstrap files that are sourced, never run. So every NEW machine
30
+ # script has to be added here by hand — host-mounts.sh and upsun-ai.sh had been
31
+ # sitting in core/scripts untested because that step was missed.
32
+ MACHINE_SCRIPTS=(autostart.sh sync-tooling.sh install.sh trust-https.sh docker-gid.sh host-mounts.sh storage.sh plugins.sh)
33
+
34
+ for ws in "${workspaces[@]}" commands core/scripts; do
35
+ dir="${WORKSPACE_ROOT}/${ws}"
36
+ [ -d "$dir" ] || continue
37
+ if [ "$ws" == 'core/scripts' ] ; then
38
+ scripts=()
39
+ for name in "${MACHINE_SCRIPTS[@]}"; do
40
+ [ -f "${dir}/${name}" ] && scripts+=("${dir}/${name}")
41
+ done
42
+ else
43
+ scripts=("$dir"/cmd-*.sh)
44
+ fi
45
+ for f in "${scripts[@]}"; do
46
+ [ -f "$f" ] || continue
47
+ rel="${ws}/$(basename "$f")"
48
+ err=""
49
+
50
+ # 1. Syntax
51
+ if ! bash -n "$f" 2>/tmp/cmd-smoke-err; then
52
+ err="syntax: $(head -1 /tmp/cmd-smoke-err)"
53
+ fi
54
+
55
+ # 2. argparse scripts: run --help (safe, exercises the full bootstrap chain)
56
+ if [ -z "$err" ] && grep -q 'argparse "\$@"\|arg-${distribution_name}\|arg-\${distribution_name}\|--help)' "$f"; then
57
+ if ! (cd "$dir" && timeout 30 bash "$f" --help >/tmp/cmd-smoke-out 2>&1); then
58
+ # argparse exits non-zero on --help in some versions; accept if usage was printed
59
+ if ! grep -qi "usage" /tmp/cmd-smoke-out; then
60
+ err="--help: $(tail -1 /tmp/cmd-smoke-out | cut -c1-120)"
61
+ fi
62
+ fi
63
+ fi
64
+
65
+ # 3. The function the script ends by calling must actually EXIST after bootstrap.
66
+ # `--help` returns before that line, so a script whose function file was never added to
67
+ # bootstrap-functions.sh passes every check above and then dies with "command not found"
68
+ # the first time it is run for real. That is how sixteen site-template builders shipped.
69
+ if [ -z "$err" ]; then
70
+ for fn in $(grep -oE '^[a-z_][a-z0-9_]* ;$' "$f" | tr -d ' ;' | sort -u); do
71
+ # A machine script may define the function it ends by calling, in itself.
72
+ grep -qE "^(function )?${fn}\(\)" "$f" && continue
73
+ if ! (cd "$dir" && bash -c 'source "$1" >/dev/null 2>&1; declare -F "$2" >/dev/null' \
74
+ _ "${WORKSPACE_SCRIPTS}/bootstrap.sh" "$fn") ; then
75
+ err="calls ${fn}() but nothing defines it — is its file sourced in bootstrap-functions.sh?"
76
+ break
77
+ fi
78
+ done
79
+ fi
80
+
81
+ # 4. Builder scripts must have the human-readable name header.
82
+ # A builder is cmd-<distribution><version>-project.sh. cmd-tool-*/cmd-tools-* are the
83
+ # workspace's own tools — projects/cmd-tool-backup-project.sh ends in -project.sh too,
84
+ # and is not a builder.
85
+ if [ -z "$err" ] && [[ "$(basename "$f")" == cmd-*-project.sh ]] \
86
+ && [[ "$(basename "$f")" != cmd-tool-* ]] && [[ "$(basename "$f")" != cmd-tools-* ]] \
87
+ && [[ "$(basename "$f")" != cmd-automated-testing-* ]] && [[ "$(basename "$f")" != cmd-bulk-* ]]; then
88
+ if ! grep -q "^# workspace-name:" "$f"; then
89
+ err="missing '# workspace-name:' header"
90
+ fi
91
+ fi
92
+
93
+ if [ -z "$err" ]; then
94
+ pass=$((pass+1))
95
+ printf "PASS %s\n" "$rel"
96
+ else
97
+ fail=$((fail+1))
98
+ failures+=("$rel — $err")
99
+ printf "FAIL %s — %s\n" "$rel" "$err"
100
+ fi
101
+ done
102
+ done
103
+
104
+ echo
105
+ echo "=================================================="
106
+ echo " cmd- smoke test: ${pass} passed, ${fail} failed"
107
+ echo "=================================================="
108
+ for f in "${failures[@]}"; do echo " ✗ $f"; done
109
+ exit $fail