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

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 (630) 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/core/workspace-app/README.md +380 -0
  160. package/{actions → core/workspace-app/actions}/ddev.js +0 -1
  161. package/{actions → core/workspace-app/actions}/rag.js +0 -1
  162. package/{actions → core/workspace-app/actions}/testing.js +0 -1
  163. package/{assistant.js → core/workspace-app/assistant.js} +1 -10
  164. package/{git-info.js → core/workspace-app/git-info.js} +17 -1
  165. package/core/workspace-app/package.json +29 -0
  166. package/core/workspace-app/plugin-catalog.js +50 -0
  167. package/{plugins-page.js → core/workspace-app/plugins-page.js} +28 -2
  168. package/{server.js → core/workspace-app/server.js} +18 -0
  169. package/core/workspace-app/tests/features/actions-rail.feature +44 -0
  170. package/core/workspace-app/tests/features/ai-items.feature +23 -0
  171. package/core/workspace-app/tests/features/assistant-speech.feature +63 -0
  172. package/core/workspace-app/tests/features/checks.feature +39 -0
  173. package/core/workspace-app/tests/features/clone-project.feature +30 -0
  174. package/core/workspace-app/tests/features/command-authoring.feature +58 -0
  175. package/core/workspace-app/tests/features/dashboard.feature +57 -0
  176. package/core/workspace-app/tests/features/menus.feature +29 -0
  177. package/core/workspace-app/tests/features/plugins/jira/jira.feature +47 -0
  178. package/core/workspace-app/tests/features/plugins.feature +20 -0
  179. package/core/workspace-app/tests/features/project-actions.feature +40 -0
  180. package/core/workspace-app/tests/features/screens.feature +29 -0
  181. package/core/workspace-app/tests/features/settings.feature +46 -0
  182. package/core/workspace-app/tests/features/test-reports.feature +32 -0
  183. package/core/workspace-app/tests/features/theme.feature +40 -0
  184. package/core/workspace-app/tests/step-definitions/actions-post.steps.js +25 -0
  185. package/core/workspace-app/tests/step-definitions/assistant-speech.steps.js +152 -0
  186. package/core/workspace-app/tests/step-definitions/preconditions.steps.js +100 -0
  187. package/core/workspace-app/tests/unit/_isolated-config.js +31 -0
  188. package/core/workspace-app/tests/unit/accessibility.test.js +124 -0
  189. package/core/workspace-app/tests/unit/actions-rail-ux.test.js +56 -0
  190. package/core/workspace-app/tests/unit/actions-rail.test.js +51 -0
  191. package/core/workspace-app/tests/unit/ai-inventory.test.js +64 -0
  192. package/core/workspace-app/tests/unit/app-docs.test.js +64 -0
  193. package/core/workspace-app/tests/unit/assistant-avatar.test.js +110 -0
  194. package/core/workspace-app/tests/unit/assistant-cast.test.js +105 -0
  195. package/core/workspace-app/tests/unit/assistant-send-animation.test.js +15 -0
  196. package/core/workspace-app/tests/unit/assistant-suggestions.test.js +112 -0
  197. package/core/workspace-app/tests/unit/assistant-switches.test.js +53 -0
  198. package/core/workspace-app/tests/unit/assistant-views.test.js +146 -0
  199. package/core/workspace-app/tests/unit/assistant-working-indicator.test.js +49 -0
  200. package/core/workspace-app/tests/unit/assistant.test.js +61 -0
  201. package/core/workspace-app/tests/unit/audio-player.test.js +147 -0
  202. package/core/workspace-app/tests/unit/audio-voice.test.js +634 -0
  203. package/core/workspace-app/tests/unit/auth-google.test.js +180 -0
  204. package/core/workspace-app/tests/unit/autostart-watch.test.js +76 -0
  205. package/core/workspace-app/tests/unit/browsers.test.js +76 -0
  206. package/core/workspace-app/tests/unit/build-distribution.test.js +125 -0
  207. package/core/workspace-app/tests/unit/build-order.test.js +153 -0
  208. package/core/workspace-app/tests/unit/builder-args.test.js +113 -0
  209. package/core/workspace-app/tests/unit/builders.test.js +158 -0
  210. package/core/workspace-app/tests/unit/card-state-toggle.test.js +29 -0
  211. package/core/workspace-app/tests/unit/changelog.test.js +177 -0
  212. package/core/workspace-app/tests/unit/chat-thread.test.js +92 -0
  213. package/core/workspace-app/tests/unit/checks-plan.test.js +205 -0
  214. package/core/workspace-app/tests/unit/claude-args.test.js +182 -0
  215. package/core/workspace-app/tests/unit/claude-code-here.test.js +15 -0
  216. package/core/workspace-app/tests/unit/claude-resume.test.js +147 -0
  217. package/core/workspace-app/tests/unit/claude-screen-options.test.js +84 -0
  218. package/core/workspace-app/tests/unit/claude-session.test.js +41 -0
  219. package/core/workspace-app/tests/unit/command-flags.test.js +45 -0
  220. package/core/workspace-app/tests/unit/command-palette.test.js +105 -0
  221. package/core/workspace-app/tests/unit/commands-center.test.js +338 -0
  222. package/core/workspace-app/tests/unit/composer-menu.test.js +187 -0
  223. package/core/workspace-app/tests/unit/config-yaml.test.js +116 -0
  224. package/core/workspace-app/tests/unit/confirm-dialog.test.js +69 -0
  225. package/core/workspace-app/tests/unit/create-card.test.js +85 -0
  226. package/core/workspace-app/tests/unit/ddev-addons.test.js +144 -0
  227. package/core/workspace-app/tests/unit/ddev-auth-ssh.test.js +40 -0
  228. package/core/workspace-app/tests/unit/ddev-custom-commands.test.js +56 -0
  229. package/core/workspace-app/tests/unit/ddev-diagnose.test.js +57 -0
  230. package/core/workspace-app/tests/unit/ddev-domains.test.js +153 -0
  231. package/core/workspace-app/tests/unit/ddev-hostnames.test.js +143 -0
  232. package/core/workspace-app/tests/unit/ddev-import.test.js +82 -0
  233. package/core/workspace-app/tests/unit/ddev-mail.test.js +135 -0
  234. package/core/workspace-app/tests/unit/ddev-menu-and-create.test.js +28 -0
  235. package/core/workspace-app/tests/unit/ddev-mutagen.test.js +37 -0
  236. package/core/workspace-app/tests/unit/ddev-options.test.js +51 -0
  237. package/core/workspace-app/tests/unit/ddev-share.test.js +40 -0
  238. package/core/workspace-app/tests/unit/ddev-shim.test.js +57 -0
  239. package/core/workspace-app/tests/unit/ddev-snapshots.test.js +142 -0
  240. package/core/workspace-app/tests/unit/ddev-start-daemons.test.js +62 -0
  241. package/core/workspace-app/tests/unit/ddev-xdebug.test.js +41 -0
  242. package/core/workspace-app/tests/unit/deep-chat-origin.test.js +38 -0
  243. package/core/workspace-app/tests/unit/density.test.js +52 -0
  244. package/core/workspace-app/tests/unit/elevenlabs.test.js +453 -0
  245. package/core/workspace-app/tests/unit/event-log.test.js +102 -0
  246. package/core/workspace-app/tests/unit/favicon.test.js +68 -0
  247. package/core/workspace-app/tests/unit/files-browser.test.js +224 -0
  248. package/core/workspace-app/tests/unit/git-info.test.js +26 -0
  249. package/core/workspace-app/tests/unit/grid-and-list.test.js +103 -0
  250. package/core/workspace-app/tests/unit/host-tool-wrapper.test.js +18 -0
  251. package/core/workspace-app/tests/unit/html-patterns.test.js +51 -0
  252. package/core/workspace-app/tests/unit/ide-infra.test.js +28 -0
  253. package/core/workspace-app/tests/unit/images-ai.test.js +201 -0
  254. package/core/workspace-app/tests/unit/images-create.test.js +59 -0
  255. package/core/workspace-app/tests/unit/images-providers.test.js +248 -0
  256. package/core/workspace-app/tests/unit/images-svg.test.js +213 -0
  257. package/core/workspace-app/tests/unit/images-workspace.test.js +144 -0
  258. package/core/workspace-app/tests/unit/jobs-fragment.test.js +66 -0
  259. package/core/workspace-app/tests/unit/media-ux.test.js +164 -0
  260. package/core/workspace-app/tests/unit/modal-fit.test.js +87 -0
  261. package/core/workspace-app/tests/unit/modules-load.test.js +23 -0
  262. package/core/workspace-app/tests/unit/narration.test.js +186 -0
  263. package/core/workspace-app/tests/unit/navigation-editor.test.js +260 -0
  264. package/core/workspace-app/tests/unit/navigation.test.js +254 -0
  265. package/core/workspace-app/tests/unit/new-folder.test.js +121 -0
  266. package/core/workspace-app/tests/unit/new-screen-form.test.js +149 -0
  267. package/core/workspace-app/tests/unit/node-menu.test.js +161 -0
  268. package/core/workspace-app/tests/unit/notes.test.js +128 -0
  269. package/core/workspace-app/tests/unit/page-structure.test.js +40 -0
  270. package/core/workspace-app/tests/unit/page-width.test.js +59 -0
  271. package/core/workspace-app/tests/unit/php-version.test.js +90 -0
  272. package/core/workspace-app/tests/unit/plan-card.test.js +44 -0
  273. package/core/workspace-app/tests/unit/plugin-catalog.test.js +31 -0
  274. package/core/workspace-app/tests/unit/plugin-system.test.js +251 -0
  275. package/core/workspace-app/tests/unit/plugins-page.test.js +28 -0
  276. package/core/workspace-app/tests/unit/plugins.test.js +58 -0
  277. package/core/workspace-app/tests/unit/project-activity-filter.test.js +180 -0
  278. package/core/workspace-app/tests/unit/project-make.test.js +143 -0
  279. package/core/workspace-app/tests/unit/project-name.test.js +202 -0
  280. package/core/workspace-app/tests/unit/reader.test.js +62 -0
  281. package/core/workspace-app/tests/unit/release.test.js +92 -0
  282. package/core/workspace-app/tests/unit/remove-confirm.test.js +37 -0
  283. package/core/workspace-app/tests/unit/report-pdf.test.js +171 -0
  284. package/core/workspace-app/tests/unit/round-11.test.js +31 -0
  285. package/core/workspace-app/tests/unit/round-12.test.js +37 -0
  286. package/core/workspace-app/tests/unit/row-layout.test.js +585 -0
  287. package/core/workspace-app/tests/unit/row-menus-fold.test.js +29 -0
  288. package/core/workspace-app/tests/unit/rows-add-modal.test.js +68 -0
  289. package/core/workspace-app/tests/unit/screen-runner-queue.test.js +41 -0
  290. package/core/workspace-app/tests/unit/screen-window.test.js +116 -0
  291. package/core/workspace-app/tests/unit/screens-beside-running.test.js +19 -0
  292. package/core/workspace-app/tests/unit/screens-columns.test.js +79 -0
  293. package/core/workspace-app/tests/unit/screens-menu.test.js +84 -0
  294. package/core/workspace-app/tests/unit/screens-modal-overlay.test.js +14 -0
  295. package/core/workspace-app/tests/unit/screens-waiting.test.js +129 -0
  296. package/core/workspace-app/tests/unit/screens.test.js +74 -0
  297. package/core/workspace-app/tests/unit/second-storage.test.js +218 -0
  298. package/core/workspace-app/tests/unit/session-name.test.js +64 -0
  299. package/core/workspace-app/tests/unit/settings-file.test.js +173 -0
  300. package/core/workspace-app/tests/unit/settings-nested-list.test.js +54 -0
  301. package/core/workspace-app/tests/unit/settings-raw.test.js +177 -0
  302. package/core/workspace-app/tests/unit/shared-prefs.test.js +49 -0
  303. package/core/workspace-app/tests/unit/speech.test.js +290 -0
  304. package/core/workspace-app/tests/unit/static-caching.test.js +39 -0
  305. package/core/workspace-app/tests/unit/status-language.test.js +47 -0
  306. package/core/workspace-app/tests/unit/tab-modal.test.js +69 -0
  307. package/core/workspace-app/tests/unit/tab-title.test.js +37 -0
  308. package/core/workspace-app/tests/unit/template-literals.test.js +52 -0
  309. package/core/workspace-app/tests/unit/terminal-scrollback.test.js +61 -0
  310. package/core/workspace-app/tests/unit/terminal-size.test.js +103 -0
  311. package/core/workspace-app/tests/unit/terminal-style.test.js +84 -0
  312. package/core/workspace-app/tests/unit/terminal-windows.test.js +154 -0
  313. package/core/workspace-app/tests/unit/themes.test.js +453 -0
  314. package/core/workspace-app/tests/unit/tool-labels.test.js +34 -0
  315. package/core/workspace-app/tests/unit/topbar-icons.test.js +47 -0
  316. package/core/workspace-app/tests/unit/update-docker-gid.test.js +51 -0
  317. package/core/workspace-app/tests/unit/user-guide.test.js +60 -0
  318. package/core/workspace-app/tests/unit/version-check.test.js +98 -0
  319. package/core/workspace-app/tests/unit/version-link.test.js +50 -0
  320. package/core/workspace-app/tests/unit/video-borrow.test.js +198 -0
  321. package/core/workspace-app/tests/unit/video-edit-ask.test.js +93 -0
  322. package/core/workspace-app/tests/unit/video-edit-short.test.js +42 -0
  323. package/core/workspace-app/tests/unit/video-edit.test.js +417 -0
  324. package/core/workspace-app/tests/unit/video-transcript.test.js +237 -0
  325. package/core/workspace-app/tests/unit/waiting.test.js +48 -0
  326. package/core/workspace-app/tests/unit/wordpress-odoo-builders.test.js +38 -0
  327. package/core/workspace-app/tests/unit/workspace-bin.test.js +48 -0
  328. package/core/workspace-app/tests/unit/workspace-card-tools.test.js +30 -0
  329. package/core/workspace-app/tests/unit/workspace-delete.test.js +77 -0
  330. package/core/workspace-app/tests/unit/workspace-types.test.js +68 -0
  331. package/core/workspace-app/tests/unit/worktree-clone.test.js +250 -0
  332. package/package.json +38 -36
  333. /package/{PLUGINS.md → core/workspace-app/PLUGINS.md} +0 -0
  334. /package/{WORKSPACES.md → core/workspace-app/WORKSPACES.md} +0 -0
  335. /package/{actions → core/workspace-app/actions}/ai-items.js +0 -0
  336. /package/{actions → core/workspace-app/actions}/audio.js +0 -0
  337. /package/{actions → core/workspace-app/actions}/build-order.js +0 -0
  338. /package/{actions → core/workspace-app/actions}/checks.js +0 -0
  339. /package/{actions → core/workspace-app/actions}/claude-session.js +0 -0
  340. /package/{actions → core/workspace-app/actions}/commands-center.js +0 -0
  341. /package/{actions → core/workspace-app/actions}/composer.js +0 -0
  342. /package/{actions → core/workspace-app/actions}/ddev-addons.js +0 -0
  343. /package/{actions → core/workspace-app/actions}/ddev-mail.js +0 -0
  344. /package/{actions → core/workspace-app/actions}/folders.js +0 -0
  345. /package/{actions → core/workspace-app/actions}/images-svg.js +0 -0
  346. /package/{actions → core/workspace-app/actions}/images.js +0 -0
  347. /package/{actions → core/workspace-app/actions}/navigation.js +0 -0
  348. /package/{actions → core/workspace-app/actions}/node.js +0 -0
  349. /package/{actions → core/workspace-app/actions}/notes.js +0 -0
  350. /package/{actions → core/workspace-app/actions}/plugins.js +0 -0
  351. /package/{actions → core/workspace-app/actions}/project-make.js +0 -0
  352. /package/{actions → core/workspace-app/actions}/row-actions.js +0 -0
  353. /package/{actions → core/workspace-app/actions}/screens.js +0 -0
  354. /package/{actions → core/workspace-app/actions}/video-edit.js +0 -0
  355. /package/{ai-inventory.js → core/workspace-app/ai-inventory.js} +0 -0
  356. /package/{ai-items.js → core/workspace-app/ai-items.js} +0 -0
  357. /package/{assistant-cast.js → core/workspace-app/assistant-cast.js} +0 -0
  358. /package/{assistant-suggestions.js → core/workspace-app/assistant-suggestions.js} +0 -0
  359. /package/{audio-voice.js → core/workspace-app/audio-voice.js} +0 -0
  360. /package/{auth-google.js → core/workspace-app/auth-google.js} +0 -0
  361. /package/{build-ai.js → core/workspace-app/build-ai.js} +0 -0
  362. /package/{build-order-page.js → core/workspace-app/build-order-page.js} +0 -0
  363. /package/{build-order.js → core/workspace-app/build-order.js} +0 -0
  364. /package/{builder-args.js → core/workspace-app/builder-args.js} +0 -0
  365. /package/{changelog.js → core/workspace-app/changelog.js} +0 -0
  366. /package/{chat-threads.js → core/workspace-app/chat-threads.js} +0 -0
  367. /package/{checks.js → core/workspace-app/checks.js} +0 -0
  368. /package/{claude-args.js → core/workspace-app/claude-args.js} +0 -0
  369. /package/{claude-sessions.js → core/workspace-app/claude-sessions.js} +0 -0
  370. /package/{command-author.js → core/workspace-app/command-author.js} +0 -0
  371. /package/{command-block.js → core/workspace-app/command-block.js} +0 -0
  372. /package/{commands → core/workspace-app/commands}/defaults.yml +0 -0
  373. /package/{commands-page.js → core/workspace-app/commands-page.js} +0 -0
  374. /package/{commands.js → core/workspace-app/commands.js} +0 -0
  375. /package/{cucumber.js → core/workspace-app/cucumber.js} +0 -0
  376. /package/{ddev-addons-page.js → core/workspace-app/ddev-addons-page.js} +0 -0
  377. /package/{ddev-addons.js → core/workspace-app/ddev-addons.js} +0 -0
  378. /package/{ddev-custom-commands.js → core/workspace-app/ddev-custom-commands.js} +0 -0
  379. /package/{ddev-domains.js → core/workspace-app/ddev-domains.js} +0 -0
  380. /package/{ddev-import.js → core/workspace-app/ddev-import.js} +0 -0
  381. /package/{ddev-mail-page.js → core/workspace-app/ddev-mail-page.js} +0 -0
  382. /package/{ddev-mail.js → core/workspace-app/ddev-mail.js} +0 -0
  383. /package/{ddev-options.js → core/workspace-app/ddev-options.js} +0 -0
  384. /package/{ddev-snapshots.js → core/workspace-app/ddev-snapshots.js} +0 -0
  385. /package/{ddev.js → core/workspace-app/ddev.js} +0 -0
  386. /package/{docs → core/workspace-app/docs}/DEVELOPER-GUIDE.md +0 -0
  387. /package/{docs → core/workspace-app/docs}/README.md +0 -0
  388. /package/{docs → core/workspace-app/docs}/REFERENCE.md +0 -0
  389. /package/{docs → core/workspace-app/docs}/USER-GUIDE.md +0 -0
  390. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-board.png +0 -0
  391. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-coffee.png +0 -0
  392. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-colours.png +0 -0
  393. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-icons.png +0 -0
  394. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-moves.png +0 -0
  395. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-pick-cookieman.png +0 -0
  396. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-settings-voices.png +0 -0
  397. /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-status.png +0 -0
  398. /package/{docs → core/workspace-app/docs}/screenshots/create-card/create-card.png +0 -0
  399. /package/{docs → core/workspace-app/docs}/screenshots/create-card/start-ai.png +0 -0
  400. /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-address.png +0 -0
  401. /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-worktree-off.png +0 -0
  402. /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-worktree-on.png +0 -0
  403. /package/{docs → core/workspace-app/docs}/screenshots/guide-ddev-menu.png +0 -0
  404. /package/{docs → core/workspace-app/docs}/screenshots/guide-domains.png +0 -0
  405. /package/{docs → core/workspace-app/docs}/screenshots/guide-home.png +0 -0
  406. /package/{docs → core/workspace-app/docs}/screenshots/guide-ide-menu.png +0 -0
  407. /package/{docs → core/workspace-app/docs}/screenshots/guide-remove-refusal.png +0 -0
  408. /package/{docs → core/workspace-app/docs}/screenshots/guide-rows-worktree.png +0 -0
  409. /package/{docs → core/workspace-app/docs}/screenshots/guide-screens.png +0 -0
  410. /package/{docs → core/workspace-app/docs}/screenshots/guide-settings.png +0 -0
  411. /package/{docs → core/workspace-app/docs}/screenshots/guide-workspace-page.png +0 -0
  412. /package/{docs → core/workspace-app/docs}/screenshots/home/card-settings.png +0 -0
  413. /package/{docs → core/workspace-app/docs}/screenshots/home/drag-reorder.png +0 -0
  414. /package/{docs → core/workspace-app/docs}/screenshots/home/edit-card.png +0 -0
  415. /package/{docs → core/workspace-app/docs}/screenshots/images/claude-code-image.png +0 -0
  416. /package/{docs → core/workspace-app/docs}/screenshots/images/edit-with-ai.png +0 -0
  417. /package/{docs → core/workspace-app/docs}/screenshots/images/gallery.png +0 -0
  418. /package/{docs → core/workspace-app/docs}/screenshots/images/generate-description.png +0 -0
  419. /package/{docs → core/workspace-app/docs}/screenshots/images/generate-plan.png +0 -0
  420. /package/{docs → core/workspace-app/docs}/screenshots/images/providers.png +0 -0
  421. /package/{docs → core/workspace-app/docs}/screenshots/images/svg-form.png +0 -0
  422. /package/{docs → core/workspace-app/docs}/screenshots/images/svg-result.png +0 -0
  423. /package/{docs → core/workspace-app/docs}/screenshots/images/upload.png +0 -0
  424. /package/{docs → core/workspace-app/docs}/screenshots/new-folder/2-form.png +0 -0
  425. /package/{docs → core/workspace-app/docs}/screenshots/new-folder/8-ddev-options.png +0 -0
  426. /package/{docs → core/workspace-app/docs}/screenshots/new-folder/files-folder.png +0 -0
  427. /package/{docs → core/workspace-app/docs}/screenshots/projects/ddev-custom-commands.png +0 -0
  428. /package/{docs → core/workspace-app/docs}/screenshots/projects/state-chip-stop.png +0 -0
  429. /package/{docs → core/workspace-app/docs}/screenshots/readme/dashboard-dark.png +0 -0
  430. /package/{docs → core/workspace-app/docs}/screenshots/readme/dashboard-light.png +0 -0
  431. /package/{docs → core/workspace-app/docs}/screenshots/readme/dev-dark.png +0 -0
  432. /package/{docs → core/workspace-app/docs}/screenshots/readme/dev-light.png +0 -0
  433. /package/{docs → core/workspace-app/docs}/screenshots/readme/docs-dark.png +0 -0
  434. /package/{docs → core/workspace-app/docs}/screenshots/readme/docs-light.png +0 -0
  435. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/ai.svg +0 -0
  436. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/code.svg +0 -0
  437. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/docs.svg +0 -0
  438. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/services.svg +0 -0
  439. /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/sites.svg +0 -0
  440. /package/{docs → core/workspace-app/docs}/screenshots/readme/test-report-dark.png +0 -0
  441. /package/{docs → core/workspace-app/docs}/screenshots/readme/test-report-light.png +0 -0
  442. /package/{docs → core/workspace-app/docs}/screenshots/readme/test-scenarios.png +0 -0
  443. /package/{docs → core/workspace-app/docs}/screenshots/readme/test-steps.png +0 -0
  444. /package/{docs → core/workspace-app/docs}/screenshots/readme/videos-dark.png +0 -0
  445. /package/{docs → core/workspace-app/docs}/screenshots/readme/videos-light.png +0 -0
  446. /package/{docs → core/workspace-app/docs}/screenshots/screens-menu.png +0 -0
  447. /package/{docs → core/workspace-app/docs}/screenshots/screens-new.png +0 -0
  448. /package/{docs → core/workspace-app/docs}/screenshots/settings/auth-google-lists.png +0 -0
  449. /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-1-row.png +0 -0
  450. /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-2-confirm.png +0 -0
  451. /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-3-type-name.png +0 -0
  452. /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-4-type-yes.png +0 -0
  453. /package/{event-log.js → core/workspace-app/event-log.js} +0 -0
  454. /package/{files-browser.js → core/workspace-app/files-browser.js} +0 -0
  455. /package/{folders.js → core/workspace-app/folders.js} +0 -0
  456. /package/{format.js → core/workspace-app/format.js} +0 -0
  457. /package/{github-auth.js → core/workspace-app/github-auth.js} +0 -0
  458. /package/{html.js → core/workspace-app/html.js} +0 -0
  459. /package/{icons.js → core/workspace-app/icons.js} +0 -0
  460. /package/{images-ai.js → core/workspace-app/images-ai.js} +0 -0
  461. /package/{images-create.js → core/workspace-app/images-create.js} +0 -0
  462. /package/{images-page.js → core/workspace-app/images-page.js} +0 -0
  463. /package/{images-records.js → core/workspace-app/images-records.js} +0 -0
  464. /package/{images-render.js → core/workspace-app/images-render.js} +0 -0
  465. /package/{images-svg-core.js → core/workspace-app/images-svg-core.js} +0 -0
  466. /package/{images-svg-sanitize.js → core/workspace-app/images-svg-sanitize.js} +0 -0
  467. /package/{images-svg.js → core/workspace-app/images-svg.js} +0 -0
  468. /package/{images.js → core/workspace-app/images.js} +0 -0
  469. /package/{jobs.js → core/workspace-app/jobs.js} +0 -0
  470. /package/{linger.js → core/workspace-app/linger.js} +0 -0
  471. /package/{lists.js → core/workspace-app/lists.js} +0 -0
  472. /package/{media-info.js → core/workspace-app/media-info.js} +0 -0
  473. /package/{navigation-page.js → core/workspace-app/navigation-page.js} +0 -0
  474. /package/{navigation.js → core/workspace-app/navigation.js} +0 -0
  475. /package/{notes.js → core/workspace-app/notes.js} +0 -0
  476. /package/{palette-index.js → core/workspace-app/palette-index.js} +0 -0
  477. /package/{playwright.config.js → core/workspace-app/playwright.config.js} +0 -0
  478. /package/{plugin-install.js → core/workspace-app/plugin-install.js} +0 -0
  479. /package/{plugin-loader.js → core/workspace-app/plugin-loader.js} +0 -0
  480. /package/{plugin-manifest.js → core/workspace-app/plugin-manifest.js} +0 -0
  481. /package/{plugin-settings.js → core/workspace-app/plugin-settings.js} +0 -0
  482. /package/{plugins → core/workspace-app/plugins}/workspace-notes/index.js +0 -0
  483. /package/{project-make.js → core/workspace-app/project-make.js} +0 -0
  484. /package/{project-name.js → core/workspace-app/project-name.js} +0 -0
  485. /package/{public → core/workspace-app/public}/assistant-avatar-moves.js +0 -0
  486. /package/{public → core/workspace-app/public}/assistant-avatar-ui.js +0 -0
  487. /package/{public → core/workspace-app/public}/assistant-avatar.js +0 -0
  488. /package/{public → core/workspace-app/public}/avatar/druplicon.vrm +0 -0
  489. /package/{public → core/workspace-app/public}/css/base.css +0 -0
  490. /package/{public → core/workspace-app/public}/css/components/ai-assistant.css +0 -0
  491. /package/{public → core/workspace-app/public}/css/components/assistant-avatar.css +0 -0
  492. /package/{public → core/workspace-app/public}/css/components/assistant-views.css +0 -0
  493. /package/{public → core/workspace-app/public}/css/components/build-order.css +0 -0
  494. /package/{public → core/workspace-app/public}/css/components/clone-as-a-git-worktree.css +0 -0
  495. /package/{public → core/workspace-app/public}/css/components/command-palette.css +0 -0
  496. /package/{public → core/workspace-app/public}/css/components/commands-center.css +0 -0
  497. /package/{public → core/workspace-app/public}/css/components/confirm-dialog.css +0 -0
  498. /package/{public → core/workspace-app/public}/css/components/create-card.css +0 -0
  499. /package/{public → core/workspace-app/public}/css/components/ddev-menu.css +0 -0
  500. /package/{public → core/workspace-app/public}/css/components/deep-chat.css +0 -0
  501. /package/{public → core/workspace-app/public}/css/components/density.css +0 -0
  502. /package/{public → core/workspace-app/public}/css/components/floating-assistant-workspace-pages.css +0 -0
  503. /package/{public → core/workspace-app/public}/css/components/folders.css +0 -0
  504. /package/{public → core/workspace-app/public}/css/components/full-height-left-assistant-sidebar-all-pages.css +0 -0
  505. /package/{public → core/workspace-app/public}/css/components/full-height-right-actions-rail-pages-that-have-actions.css +0 -0
  506. /package/{public → core/workspace-app/public}/css/components/grid-and-list.css +0 -0
  507. /package/{public → core/workspace-app/public}/css/components/help-page.css +0 -0
  508. /package/{public → core/workspace-app/public}/css/components/hero.css +0 -0
  509. /package/{public → core/workspace-app/public}/css/components/images.css +0 -0
  510. /package/{public → core/workspace-app/public}/css/components/layout-rhythm-and-spacing-polish.css +0 -0
  511. /package/{public → core/workspace-app/public}/css/components/mic-on-any-field-that-wants-typing.css +0 -0
  512. /package/{public → core/workspace-app/public}/css/components/modal-fit.css +0 -0
  513. /package/{public → core/workspace-app/public}/css/components/page-width.css +0 -0
  514. /package/{public → core/workspace-app/public}/css/components/plugins-page.css +0 -0
  515. /package/{public → core/workspace-app/public}/css/components/project-cards.css +0 -0
  516. /package/{public → core/workspace-app/public}/css/components/project-rows.css +0 -0
  517. /package/{public → core/workspace-app/public}/css/components/reordering-the-workspace-cards.css +0 -0
  518. /package/{public → core/workspace-app/public}/css/components/responsive-home-and-the-workspace-pages.css +0 -0
  519. /package/{public → core/workspace-app/public}/css/components/running-commands-as-toasts.css +0 -0
  520. /package/{public → core/workspace-app/public}/css/components/settings-editor-core-config-yml.css +0 -0
  521. /package/{public → core/workspace-app/public}/css/components/short-results-as-a-toast-at-the-top.css +0 -0
  522. /package/{public → core/workspace-app/public}/css/components/sound-player.css +0 -0
  523. /package/{public → core/workspace-app/public}/css/components/suggest-agents-skills-commands.css +0 -0
  524. /package/{public → core/workspace-app/public}/css/components/tab-modal.css +0 -0
  525. /package/{public → core/workspace-app/public}/css/components/terminals.css +0 -0
  526. /package/{public → core/workspace-app/public}/css/components/test-report-media-one-file-per-row-paged.css +0 -0
  527. /package/{public → core/workspace-app/public}/css/components/top-toolbar-logo-breadcrumb.css +0 -0
  528. /package/{public → core/workspace-app/public}/css/components/video-edit.css +0 -0
  529. /package/{public → core/workspace-app/public}/css/components/web-ide-open-with.css +0 -0
  530. /package/{public → core/workspace-app/public}/css/components/working-indicators.css +0 -0
  531. /package/{public → core/workspace-app/public}/css/components/workspace-cards.css +0 -0
  532. /package/{public → core/workspace-app/public}/favicon.ico +0 -0
  533. /package/{public → core/workspace-app/public}/favicon.png +0 -0
  534. /package/{public → core/workspace-app/public}/htmx.min.js +0 -0
  535. /package/{public → core/workspace-app/public}/logo.png +0 -0
  536. /package/{public → core/workspace-app/public}/media-player.js +0 -0
  537. /package/{public → core/workspace-app/public}/mic.js +0 -0
  538. /package/{public → core/workspace-app/public}/narration.js +0 -0
  539. /package/{public → core/workspace-app/public}/palette.js +0 -0
  540. /package/{public → core/workspace-app/public}/sortable.js +0 -0
  541. /package/{public → core/workspace-app/public}/suggest.js +0 -0
  542. /package/{public → core/workspace-app/public}/terminal.js +0 -0
  543. /package/{public → core/workspace-app/public}/themes/default/theme.css +0 -0
  544. /package/{public → core/workspace-app/public}/themes/ember/theme.css +0 -0
  545. /package/{public → core/workspace-app/public}/themes/press/theme.css +0 -0
  546. /package/{public → core/workspace-app/public}/themes/slate/theme.css +0 -0
  547. /package/{public → core/workspace-app/public}/touch-icon.png +0 -0
  548. /package/{public → core/workspace-app/public}/ui.js +0 -0
  549. /package/{public → core/workspace-app/public}/vendor/ace/LICENSE.txt +0 -0
  550. /package/{public → core/workspace-app/public}/vendor/ace/ace.js +0 -0
  551. /package/{public → core/workspace-app/public}/vendor/ace/ext-language_tools.js +0 -0
  552. /package/{public → core/workspace-app/public}/vendor/ace/ext-searchbox.js +0 -0
  553. /package/{public → core/workspace-app/public}/vendor/ace/mode-css.js +0 -0
  554. /package/{public → core/workspace-app/public}/vendor/ace/mode-html.js +0 -0
  555. /package/{public → core/workspace-app/public}/vendor/ace/mode-javascript.js +0 -0
  556. /package/{public → core/workspace-app/public}/vendor/ace/mode-markdown.js +0 -0
  557. /package/{public → core/workspace-app/public}/vendor/ace/mode-sh.js +0 -0
  558. /package/{public → core/workspace-app/public}/vendor/ace/mode-yaml.js +0 -0
  559. /package/{public → core/workspace-app/public}/vendor/ace/theme-textmate.js +0 -0
  560. /package/{public → core/workspace-app/public}/vendor/ace/theme-tomorrow_night.js +0 -0
  561. /package/{public → core/workspace-app/public}/vendor/ace/worker-yaml.js +0 -0
  562. /package/{public → core/workspace-app/public}/vendor/deep-chat.LICENSE +0 -0
  563. /package/{public → core/workspace-app/public}/vendor/deep-chat.bundle.js +0 -0
  564. /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-LICENSE.txt +0 -0
  565. /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-latin-400-italic.woff2 +0 -0
  566. /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-latin-400-normal.woff2 +0 -0
  567. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-LICENSE.txt +0 -0
  568. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-400-italic.woff2 +0 -0
  569. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-400-normal.woff2 +0 -0
  570. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-600-italic.woff2 +0 -0
  571. /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-600-normal.woff2 +0 -0
  572. /package/{public → core/workspace-app/public}/vendor/fonts/jetbrains-mono-LICENSE.txt +0 -0
  573. /package/{public → core/workspace-app/public}/vendor/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
  574. /package/{public → core/workspace-app/public}/vendor/fonts/ubuntu-mono-LICENSE.txt +0 -0
  575. /package/{public → core/workspace-app/public}/vendor/fonts/ubuntu-mono-latin-wght-normal.woff2 +0 -0
  576. /package/{public → core/workspace-app/public}/vendor/tabler-LICENSE.txt +0 -0
  577. /package/{public → core/workspace-app/public}/vendor/tabler-sprite.svg +0 -0
  578. /package/{public → core/workspace-app/public}/vendor/three/LICENSE +0 -0
  579. /package/{public → core/workspace-app/public}/vendor/three/addons/loaders/GLTFLoader.js +0 -0
  580. /package/{public → core/workspace-app/public}/vendor/three/addons/utils/BufferGeometryUtils.js +0 -0
  581. /package/{public → core/workspace-app/public}/vendor/three/addons/utils/SkeletonUtils.js +0 -0
  582. /package/{public → core/workspace-app/public}/vendor/three/three.core.min.js +0 -0
  583. /package/{public → core/workspace-app/public}/vendor/three/three.module.min.js +0 -0
  584. /package/{public → core/workspace-app/public}/vendor/three-vrm/LICENSE +0 -0
  585. /package/{public → core/workspace-app/public}/vendor/three-vrm/three-vrm.module.min.js +0 -0
  586. /package/{public → core/workspace-app/public}/vendor/uikit-icons.min.js +0 -0
  587. /package/{public → core/workspace-app/public}/vendor/uikit.min.css +0 -0
  588. /package/{public → core/workspace-app/public}/vendor/uikit.min.js +0 -0
  589. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/bookmark-outlined.svg +0 -0
  590. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/headset.svg +0 -0
  591. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/menu.svg +0 -0
  592. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/pause.svg +0 -0
  593. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/play.svg +0 -0
  594. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/share.svg +0 -0
  595. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/sound-off.svg +0 -0
  596. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/sound-on.svg +0 -0
  597. /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/stop.svg +0 -0
  598. /package/{public → core/workspace-app/public}/vendor/xterm/addon-fit.js +0 -0
  599. /package/{public → core/workspace-app/public}/vendor/xterm/addon-unicode11.js +0 -0
  600. /package/{public → core/workspace-app/public}/vendor/xterm/addon-web-links.js +0 -0
  601. /package/{public → core/workspace-app/public}/vendor/xterm/xterm.css +0 -0
  602. /package/{public → core/workspace-app/public}/vendor/xterm/xterm.js +0 -0
  603. /package/{rag.js → core/workspace-app/rag.js} +0 -0
  604. /package/{reader.js → core/workspace-app/reader.js} +0 -0
  605. /package/{repo-blobs.js → core/workspace-app/repo-blobs.js} +0 -0
  606. /package/{report-pdf.js → core/workspace-app/report-pdf.js} +0 -0
  607. /package/{row-layout.js → core/workspace-app/row-layout.js} +0 -0
  608. /package/{screenrc → core/workspace-app/screenrc} +0 -0
  609. /package/{screens.js → core/workspace-app/screens.js} +0 -0
  610. /package/{scripts → core/workspace-app/scripts}/code-server-start.sh +0 -0
  611. /package/{scripts → core/workspace-app/scripts}/images-claude-finish.js +0 -0
  612. /package/{scripts → core/workspace-app/scripts}/screen-host.sh +0 -0
  613. /package/{scripts → core/workspace-app/scripts}/screen-runner.js +0 -0
  614. /package/{scripts → core/workspace-app/scripts}/screen-then.js +0 -0
  615. /package/{scripts → core/workspace-app/scripts}/update.sh +0 -0
  616. /package/{settings-file.js → core/workspace-app/settings-file.js} +0 -0
  617. /package/{speech.js → core/workspace-app/speech.js} +0 -0
  618. /package/{tab-modal.js → core/workspace-app/tab-modal.js} +0 -0
  619. /package/{test-reports.js → core/workspace-app/test-reports.js} +0 -0
  620. /package/{themes.js → core/workspace-app/themes.js} +0 -0
  621. /package/{transcripts.js → core/workspace-app/transcripts.js} +0 -0
  622. /package/{urls.js → core/workspace-app/urls.js} +0 -0
  623. /package/{validate.js → core/workspace-app/validate.js} +0 -0
  624. /package/{version-check.js → core/workspace-app/version-check.js} +0 -0
  625. /package/{video-edit.js → core/workspace-app/video-edit.js} +0 -0
  626. /package/{waiting.js → core/workspace-app/waiting.js} +0 -0
  627. /package/{workspace-card-tools.js → core/workspace-app/workspace-card-tools.js} +0 -0
  628. /package/{workspace-delete.js → core/workspace-app/workspace-delete.js} +0 -0
  629. /package/{workspace-types.js → core/workspace-app/workspace-types.js} +0 -0
  630. /package/{workspaces.js → core/workspace-app/workspaces.js} +0 -0
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # ElevenLabs for the final voiceover of a narrated video (videos/cmd-tools-elevenlabs.sh).
4
+ # The key is read here and handed to libs/elevenlabs.py in one process's environment, never on a command line.
5
+
6
+ ELEVENLABS_BLOCK='
7
+ # ElevenLabs, for the final voiceover of a narrated video (videos/cmd-tools-elevenlabs.sh). Nothing is
8
+ # sent to ElevenLabs unless a person agrees to a run. ELEVENLABS_API_KEY in the environment wins over api_key.
9
+ # voice_id may be an id or a voice name such as Brian; voice and model are accepted for voice_id and model_id.
10
+ elevenlabs:
11
+ api_key: CHANGE_ME
12
+ voice_id: ask
13
+ model_id: eleven_v4
14
+ region: global
15
+ # Brand names are respelled for the voice only (built in: Webship=Var-dot; Webship=Var-base). Add more as
16
+ # "Word=Respelling; Word=Respelling" when a voice misreads one.
17
+ pronunciation: ""
18
+ ';
19
+
20
+ # parse_yaml keeps a value's quotes.
21
+ function elevenlabs_setting() {
22
+ local value="$1";
23
+ case "${value}" in
24
+ \"*\") value="${value#\"}"; value="${value%\"}" ;;
25
+ \'*\') value="${value#\'}"; value="${value%\'}" ;;
26
+ esac
27
+ printf '%s' "${value}";
28
+ }
29
+
30
+ function elevenlabs_key_source() {
31
+ local settings_key;
32
+ settings_key="$(elevenlabs_setting "${elevenlabs_api_key}")";
33
+ if [ -n "${ELEVENLABS_API_KEY:-}" ] ; then echo 'environment' ; return 0 ; fi
34
+ case "${settings_key}" in
35
+ ''|CHANGE_ME|sk-change-this) return 1 ;;
36
+ esac
37
+ echo 'settings.yml';
38
+ }
39
+
40
+ function elevenlabs_key() {
41
+ case "$(elevenlabs_key_source)" in
42
+ environment) printf '%s' "${ELEVENLABS_API_KEY}" ;;
43
+ settings.yml) elevenlabs_setting "${elevenlabs_api_key}" ;;
44
+ esac
45
+ }
46
+
47
+ function elevenlabs_base() {
48
+ if [ -n "${ELEVENLABS_API_BASE:-}" ] ; then echo "${ELEVENLABS_API_BASE%/}" ; return 0 ; fi
49
+ case "$(elevenlabs_setting "${elevenlabs_region}")" in
50
+ us) echo 'https://api.us.elevenlabs.io' ;;
51
+ eu) echo 'https://api.eu.residency.elevenlabs.io' ;;
52
+ in) echo 'https://api.in.residency.elevenlabs.io' ;;
53
+ sg) echo 'https://api.sg.residency.elevenlabs.io' ;;
54
+ *) echo 'https://api.elevenlabs.io' ;;
55
+ esac
56
+ }
57
+
58
+ function elevenlabs_model() {
59
+ local model;
60
+ model="$(elevenlabs_setting "${elevenlabs_model_id:-${elevenlabs_model:-}}")";
61
+ echo "${ELEVENLABS_MODEL:-${model:-eleven_v4}}";
62
+ }
63
+
64
+ function elevenlabs_voice() {
65
+ local voice;
66
+ voice="$(elevenlabs_setting "${elevenlabs_voice_id:-${elevenlabs_voice:-}}")";
67
+ case "${voice}" in ''|ask|CHANGE_ME) voice='' ;; esac
68
+ echo "${ELEVENLABS_VOICE:-${voice}}";
69
+ }
70
+
71
+ function elevenlabs_engine() {
72
+ ELEVENLABS_API_KEY="$(elevenlabs_key)" ELEVENLABS_API_BASE="$(elevenlabs_base)" \
73
+ ELEVENLABS_MODEL="$(elevenlabs_model)" ELEVENLABS_VOICE="$(elevenlabs_voice)" \
74
+ ELEVENLABS_PRONUNCIATION="${ELEVENLABS_PRONUNCIATION:-$(elevenlabs_setting "${elevenlabs_pronunciation:-}")}" \
75
+ python3 "${WORKSPACE_SCRIPTS}/libs/elevenlabs.py" "$@" ;
76
+ }
77
+
78
+ function elevenlabs_status() {
79
+ local key_source voice;
80
+ key_source="$(elevenlabs_key_source)";
81
+ voice="$(elevenlabs_voice)";
82
+ echo "ElevenLabs";
83
+ if [ -n "${key_source}" ] ; then echo " key: set (${key_source})" ; else echo " key: not set" ; fi
84
+ echo " block: $(grep -q '^elevenlabs:' "${WORKSPACE_CONFIG}/settings.yml" 2>/dev/null && echo 'in settings.yml' || echo 'missing from settings.yml (run -a init)')";
85
+ echo " server: $(elevenlabs_base)";
86
+ echo " model: $(elevenlabs_model)";
87
+ echo " voice: ${voice:-ask each time (list them with -a voices)}";
88
+ if [ -z "${key_source}" ] ; then
89
+ echo "";
90
+ echo "No key, so the final voiceover stage is not offered. Add one at /settings (ElevenLabs); never paste it into a chat.";
91
+ return 3 ;
92
+ fi
93
+ }
94
+
95
+ function elevenlabs_init() {
96
+ local file="${WORKSPACE_CONFIG}/settings.yml";
97
+ if [ ! -f "${file}" ] ; then echo "No settings.yml at ${file}." ; return 1 ; fi
98
+ if grep -q '^elevenlabs:' "${file}" ; then
99
+ echo "settings.yml already has an elevenlabs: block. Set api_key at /settings (ElevenLabs).";
100
+ return 0 ;
101
+ fi
102
+ [ -n "$(tail -c1 "${file}")" ] && printf '\n' >> "${file}" ;
103
+ printf '%s' "${ELEVENLABS_BLOCK}" >> "${file}" ;
104
+ echo "Added an elevenlabs: block to ${file} with a placeholder key. Open /settings, find ElevenLabs and set the key there.";
105
+ }
106
+
107
+ function elevenlabs_mcp() {
108
+ local name='elevenlabs' url;
109
+ url="$(elevenlabs_base)/v1/mcp";
110
+ if ! command -v claude > /dev/null 2>&1 ; then echo "The Claude Code CLI (claude) is not on PATH." ; return 1 ; fi
111
+ case "$1" in
112
+ status)
113
+ timeout 60 claude mcp get "${name}" 2>&1 || echo "Not registered in Claude Code yet. Run -a mcp-register." ;
114
+ ;;
115
+ register)
116
+ if claude mcp get "${name}" > /dev/null 2>&1 ; then
117
+ echo "${name} is already registered. -a mcp-unregister removes it first if the address must change.";
118
+ return 0 ;
119
+ fi
120
+ claude mcp add --transport http --scope user "${name}" "${url}" || return 1 ;
121
+ echo "";
122
+ echo "Registered ${name} (${url}). No key is stored: it signs in with OAuth.";
123
+ echo " Open a NEW session, run /mcp, pick ${name} and sign in with your ElevenLabs account.";
124
+ echo " It manages ElevenLabs agents and can generate speech samples. An agent update is published directly,";
125
+ echo " with no draft, so keep its write tools on ask-first in the client.";
126
+ ;;
127
+ unregister)
128
+ claude mcp remove --scope user "${name}" && echo "Removed ${name} from the Claude Code CLI." ;
129
+ ;;
130
+ esac
131
+ }
132
+
133
+ function elevenlabs_usage() {
134
+ cat <<'USAGE'
135
+ usage: cmd-tools-elevenlabs.sh -a ACTION [options]
136
+
137
+ Free, nothing is sent to ElevenLabs:
138
+ -a status key, voice, model and server (exit 3 when no key is set)
139
+ -a init add the elevenlabs: block to settings.yml when it is missing
140
+ -a sections --script FILE the timed sections of a voiceover script and their characters
141
+
142
+ Reads the account, no credits spent:
143
+ -a check status, plan and characters left
144
+ -a voices [--search WORD] the voices on the account
145
+
146
+ Spends credits, so it prints a plan and stops unless --confirm is given:
147
+ -a speak --text-file F --out F.mp3 [--voice ID]
148
+ -a voiceover --script S.md --video V.mp4 --out O.mp4 [--voice ID] [--drop-optional] [--max-speedup 1.08] [--redo]
149
+ -a isolate --audio TAKE --out CLEAN.mp3
150
+ -a polish --audio TAKE --video V.mp4 --out O.mp4 [--isolate] [--no-normalize]
151
+
152
+ The hosted MCP server (OAuth, no key stored):
153
+ -a mcp-status | mcp-register | mcp-unregister
154
+
155
+ Add --json for machine-readable output and --force to replace an existing file.
156
+ Exit codes: 0 ok, 1 error, 2 usage, 3 no key, 4 plan only, 5 sections do not fit.
157
+ USAGE
158
+ }
159
+
160
+ function elevenlabs_main() {
161
+ local action='status';
162
+ while [ $# -gt 0 ] ; do
163
+ case "$1" in
164
+ -h|--help) elevenlabs_usage ; return 0 ;;
165
+ -a|--action) action="$2"; shift 2 || { elevenlabs_usage >&2 ; return 2 ; } ;;
166
+ *) break ;;
167
+ esac
168
+ done
169
+ case "${action}" in
170
+ status) elevenlabs_status ;;
171
+ init) elevenlabs_init ;;
172
+ check) elevenlabs_status && elevenlabs_engine account "$@" ;;
173
+ sections|voices|speak|isolate|voiceover|polish) elevenlabs_engine "${action}" "$@" ;;
174
+ mcp-status) elevenlabs_mcp status ;;
175
+ mcp-register) elevenlabs_mcp register ;;
176
+ mcp-unregister) elevenlabs_mcp unregister ;;
177
+ *) echo "Unknown action: ${action}" >&2 ; elevenlabs_usage >&2 ; return 2 ;;
178
+ esac
179
+ }
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Change file permissions and ownership
4
+ function set_chmod() {
5
+ sudo chmod 775 -R ${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME} ;
6
+ }
7
+
8
+ # Change file permissions and ownership
9
+ function set_chown() {
10
+ sudo chown www-data:${user_name} -R ${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME} ;
11
+ }
12
+
13
+ # Securing file permissions and ownership.
14
+ function set_chmod_chown() {
15
+ echo "Securing file permissions and ownership";
16
+ sudo chmod 775 -R ${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME} ;
17
+ sudo chown www-data:${user_name} -R ${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME} ;
18
+ }
19
+
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ################################################################################
4
+ ## Knowing what a project's folder IS, before anything deletes it.
5
+ ################################################################################
6
+ ## Once a project can be cloned as a git worktree (see fun-clone-project.sh) a
7
+ ## workspace folder holds three different kinds of thing that all look identical
8
+ ## in `ls`:
9
+ ##
10
+ ## plain a git checkout that nothing else depends on
11
+ ## primary the checkout that owns the real .git — other folders live off it
12
+ ## linked a worktree; its .git is a FILE pointing at the primary's
13
+ ##
14
+ ## The difference matters exactly once, and destructively:
15
+ ##
16
+ ## * Deleting a PRIMARY deletes the shared .git, and every linked worktree of it
17
+ ## becomes an orphan — a directory full of files git can no longer say
18
+ ## anything about. The branches, the stashes and the reflog go with it. That
19
+ ## is unrecoverable in a way that deleting a worktree is not.
20
+ ## * Deleting a LINKED worktree is cheap — unless it holds commits that were
21
+ ## never pushed, which is the one thing `git worktree remove` will happily
22
+ ## destroy for you.
23
+ ##
24
+ ## So remove_project asks these questions first and refuses rather than guessing.
25
+ ## Everything here is read-only except git_worktree_prune, which only tidies
26
+ ## administrative data git itself calls stale.
27
+ ################################################################################
28
+
29
+ # plain | primary | linked | none — what this directory is.
30
+ function git_worktree_role() {
31
+ local dir="${1:-}" common toplevel
32
+ [ -n "${dir}" ] && [ -d "${dir}" ] || { echo 'none' ; return 0 ; }
33
+ git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || { echo 'none' ; return 0 ; }
34
+
35
+ # In a linked worktree the git dir sits INSIDE the primary's .git as
36
+ # worktrees/<name>, so the two paths differ. In the primary they are the same.
37
+ local gitdir gitcommon
38
+ gitdir="$(git -C "${dir}" rev-parse --absolute-git-dir 2>/dev/null)"
39
+ gitcommon="$(git -C "${dir}" rev-parse --path-format=absolute --git-common-dir 2>/dev/null)"
40
+ if [ -n "${gitdir}" ] && [ -n "${gitcommon}" ] && [ "${gitdir}" != "${gitcommon}" ] ; then
41
+ echo 'linked' ; return 0 ;
42
+ fi
43
+ # The primary. Whether it is "primary" or merely "plain" is about whether
44
+ # anything else depends on it.
45
+ if [ -n "$(git_worktree_others "${dir}")" ] ; then
46
+ echo 'primary' ;
47
+ else
48
+ echo 'plain' ;
49
+ fi
50
+ }
51
+
52
+ # The other worktrees of this repository, one absolute path per line, this
53
+ # directory excluded. Parsed from the porcelain form, which is stable output
54
+ # meant for scripts — `git worktree list` without it aligns columns and would
55
+ # break on a path containing spaces.
56
+ function git_worktree_others() {
57
+ local dir="${1:-}" self
58
+ [ -n "${dir}" ] && [ -d "${dir}" ] || return 0
59
+ git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || return 0
60
+ self="$(cd "${dir}" && pwd -P)"
61
+ git -C "${dir}" worktree list --porcelain 2>/dev/null \
62
+ | sed -n 's/^worktree //p' \
63
+ | while IFS= read -r p ; do
64
+ [ -n "${p}" ] || continue
65
+ # Compare resolved paths: a symlinked workspace root would otherwise make
66
+ # a folder look like a different one from itself.
67
+ [ "$( (cd "${p}" 2>/dev/null && pwd -P) || echo "${p}")" == "${self}" ] && continue
68
+ echo "${p}" ;
69
+ done
70
+ }
71
+
72
+ # The primary worktree's path — where the real .git lives.
73
+ function git_worktree_primary() {
74
+ local dir="${1:-}"
75
+ [ -n "${dir}" ] && [ -d "${dir}" ] || return 0
76
+ git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || return 0
77
+ git -C "${dir}" worktree list --porcelain 2>/dev/null | sed -n '1s/^worktree //p'
78
+ }
79
+
80
+ # The branch checked out here, or '' when detached.
81
+ function git_worktree_branch() {
82
+ local dir="${1:-}" b
83
+ b="$(git -C "${dir}" rev-parse --abbrev-ref HEAD 2>/dev/null)"
84
+ [ "${b}" == 'HEAD' ] && b=''
85
+ echo "${b}"
86
+ }
87
+
88
+ # How many commits reachable from HEAD are on NO remote — i.e. what deleting this
89
+ # folder would destroy. Counting against every remote rather than against an
90
+ # upstream, because a worktree branch created locally has no upstream at all and
91
+ # `@{upstream}` would simply error, which is the case that most needs the answer.
92
+ function git_worktree_unpushed() {
93
+ local dir="${1:-}" n
94
+ [ -n "${dir}" ] && [ -d "${dir}" ] || { echo 0 ; return 0 ; }
95
+ git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || { echo 0 ; return 0 ; }
96
+ n="$(git -C "${dir}" rev-list --count HEAD --not --remotes 2>/dev/null)"
97
+ echo "${n:-0}"
98
+ }
99
+
100
+ # Uncommitted work in the folder: tracked changes plus untracked files that are
101
+ # not ignored. Unpushed commits are not the only thing a delete throws away.
102
+ function git_worktree_dirty() {
103
+ local dir="${1:-}"
104
+ [ -n "${dir}" ] && [ -d "${dir}" ] || { echo 0 ; return 0 ; }
105
+ git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || { echo 0 ; return 0 ; }
106
+ # `grep -c` prints 0 AND exits 1 when nothing matches, so a `|| echo 0` fallback
107
+ # prints a SECOND zero and the caller reads "0 0". Count the lines instead.
108
+ local n
109
+ n="$(git -C "${dir}" status --porcelain --untracked-files=normal 2>/dev/null | wc -l | tr -d '[:space:]')"
110
+ echo "${n:-0}"
111
+ }
112
+
113
+ # After a worktree's directory is gone, its registration in the primary is stale.
114
+ # git says so on every `worktree list` until it is pruned, and a new worktree at
115
+ # the same path is refused while it stands. Only ever called with the primary.
116
+ function git_worktree_prune() {
117
+ local primary="${1:-}"
118
+ [ -n "${primary}" ] && [ -d "${primary}" ] || return 0
119
+ git -C "${primary}" worktree prune 2>/dev/null || true
120
+ }
121
+
122
+ # One human line about a folder, for a listing or a confirmation. Says nothing at
123
+ # all for a folder that is not a git checkout, so callers can print it blind.
124
+ function git_worktree_summary() {
125
+ local dir="${1:-}" role others n branch unpushed
126
+ role="$(git_worktree_role "${dir}")"
127
+ case "${role}" in
128
+ none) return 0 ;;
129
+ linked)
130
+ branch="$(git_worktree_branch "${dir}")"
131
+ unpushed="$(git_worktree_unpushed "${dir}")"
132
+ printf 'a git worktree on %s of %s' "${branch:-a detached HEAD}" "$(git_worktree_primary "${dir}")" ;
133
+ [ "${unpushed}" -gt 0 ] && printf ' — %s unpushed commit(s)' "${unpushed}" ;
134
+ echo ;;
135
+ primary)
136
+ n="$(git_worktree_others "${dir}" | grep -c .)"
137
+ echo "the main checkout, with ${n} worktree(s) depending on its .git" ;;
138
+ plain)
139
+ branch="$(git_worktree_branch "${dir}")"
140
+ echo "a git checkout on ${branch:-a detached HEAD}" ;;
141
+ esac
142
+ }
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # gitlab-ci-local (https://github.com/firecow/gitlab-ci-local) runs a project's
4
+ # GitLab CI pipeline in local Docker containers. It is how the Webship
5
+ # green-gate is enforced: before committing to an issue-fork branch or pushing
6
+ # anything to git.drupalcode.org, the full pipeline runs locally and the push
7
+ # waits until every stage and every job is green.
8
+ #
9
+ # Drupal projects include drupal/gitlab_templates, whose jobs die on an unset
10
+ # _GITLAB_TEMPLATES_REPO unless the template variables are resolved. The
11
+ # standard fix is a wrapper that adds --remote-variables over SSH (upstream
12
+ # says HTTPS clones "do not work completely without issues"), which these
13
+ # functions install once as ~/.local/bin/drupal-ci-local.
14
+
15
+ # Make sure gitlab-ci-local is on PATH; offer the install paths if not.
16
+ function ensure_gitlab_ci_local() {
17
+ if command -v gitlab-ci-local > /dev/null 2>&1 ; then
18
+ return 0 ;
19
+ fi
20
+ echo "gitlab-ci-local is not installed — installing with npm.";
21
+ npm install -g gitlab-ci-local || {
22
+ echo "npm install failed. Alternatives:" ;
23
+ echo " brew install gitlab-ci-local # macOS" ;
24
+ echo " see https://github.com/firecow/gitlab-ci-local#installation" ;
25
+ return 1 ;
26
+ }
27
+ command -v gitlab-ci-local > /dev/null 2>&1 || {
28
+ echo "Still not on PATH — check npm's global bin directory." ;
29
+ return 1 ;
30
+ }
31
+ }
32
+
33
+ # The Drupal wrapper: gitlab-ci-local plus the drupal/gitlab_templates remote
34
+ # variables. Written once, then everything Drupal runs through it.
35
+ function ensure_drupal_ci_wrapper() {
36
+ local wrapper="${HOME}/.local/bin/drupal-ci-local";
37
+ if [ -x "${wrapper}" ]; then
38
+ return 0 ;
39
+ fi
40
+ mkdir -p "${HOME}/.local/bin" ;
41
+ cat > "${wrapper}" <<'WRAP'
42
+ #!/bin/bash
43
+ # gitlab-ci-local wired for drupal/gitlab_templates. SSH on purpose: upstream
44
+ # documents that HTTPS template clones do not work completely without issues.
45
+ gitlab-ci-local \
46
+ --remote-variables git@git.drupal.org:project/gitlab_templates=includes/include.drupalci.variables.yml=main \
47
+ --variable="_GITLAB_TEMPLATES_REPO=project/gitlab_templates" \
48
+ "$@"
49
+ WRAP
50
+ chmod +x "${wrapper}" ;
51
+ echo "Installed ${wrapper}." ;
52
+ }
53
+
54
+ # Everything a run needs, checked up front with real error messages.
55
+ function gitlab_ci_local_doctor() {
56
+ local ok=0;
57
+ ensure_gitlab_ci_local || ok=1 ;
58
+ ensure_drupal_ci_wrapper || ok=1 ;
59
+ if ! docker info > /dev/null 2>&1 ; then
60
+ echo "Docker is not reachable — every job runs in a container. Start Docker first." ;
61
+ ok=1 ;
62
+ fi
63
+ if ! ssh -o BatchMode=yes -o ConnectTimeout=8 git@git.drupal.org 2>&1 | grep -q 'Welcome to GitLab' ; then
64
+ echo "SSH to git.drupal.org failed — the Drupal template variables are fetched over SSH." ;
65
+ echo "Load your key into ssh-agent, or add one: https://git.drupalcode.org/-/user_settings/ssh_keys" ;
66
+ ok=1 ;
67
+ fi
68
+ return ${ok} ;
69
+ }
70
+
71
+ # Run a project's pipeline (or one job) with the green-gate framing.
72
+ function gitlab_ci_local_run() {
73
+ local project_path="${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME}";
74
+
75
+ if [ ! -d "${project_path}" ]; then
76
+ echo "No such project: ${project_path}";
77
+ return 1 ;
78
+ fi
79
+
80
+ gitlab_ci_local_doctor || return 1 ;
81
+ cd "${project_path}" ;
82
+
83
+ # Pick the file: --slim prefers the project's committed .gitlab-ci-local.yml
84
+ # (the reproducible subset); otherwise the real pipeline.
85
+ local ci_args="";
86
+ local runner="drupal-ci-local";
87
+ if [ "${SLIM}" == 'yes' ] ; then
88
+ if [ ! -f ".gitlab-ci-local.yml" ]; then
89
+ echo "No .gitlab-ci-local.yml in this project — run without --slim, or add one";
90
+ echo "(see the webship-gitlab-ci-local-runner skill for the pattern).";
91
+ return 1 ;
92
+ fi
93
+ ci_args="--file .gitlab-ci-local.yml";
94
+ runner="gitlab-ci-local"; # the slim file is self-contained, no templates
95
+ elif [ ! -f ".gitlab-ci.yml" ]; then
96
+ echo "No .gitlab-ci.yml here — nothing to run.";
97
+ return 1 ;
98
+ fi
99
+
100
+ if [ ! "${VARIABLE}" == '_none_' ] ; then
101
+ ci_args="${ci_args} --variable ${VARIABLE}";
102
+ fi
103
+
104
+ # gitignore the artifacts dir once, quietly.
105
+ if [ -d .git ] && ! grep -qs '^\.gitlab-ci-local/' .gitignore 2>/dev/null ; then
106
+ echo ".gitlab-ci-local/" >> .gitignore ;
107
+ echo "Added .gitlab-ci-local/ to .gitignore (artifacts and logs land there)." ;
108
+ fi
109
+
110
+ if [ "${LIST}" == 'yes' ] ; then
111
+ ${runner} ${ci_args} --list ;
112
+ return $? ;
113
+ fi
114
+
115
+ echo "*---------------------------------------------------------------------*";
116
+ echo " Green-gate run: ${doc_name}/${PROJECT_NAME}${JOB:+ — job: ${JOB}}";
117
+ echo "*---------------------------------------------------------------------*";
118
+
119
+ local output_file;
120
+ output_file=$(mktemp) ;
121
+ if [ -n "${JOB}" ] && [ ! "${JOB}" == '_none_' ] ; then
122
+ ${runner} ${ci_args} "${JOB}" 2>&1 | tee "${output_file}" ;
123
+ else
124
+ ${runner} ${ci_args} 2>&1 | tee "${output_file}" ;
125
+ fi
126
+ local status=${PIPESTATUS[0]} ;
127
+
128
+ # Known blocker: gitlab-ci-local crashes evaluating any rule whose =~ regex
129
+ # embeds a $variable (firecow/gitlab-ci-local#1893), and drupal/gitlab_templates
130
+ # has used that pattern for years — every ref, every gitlab-ci-local version.
131
+ # Until that lands upstream, the slim .gitlab-ci-local.yml is the only
132
+ # runnable path for a templates-based project.
133
+ if [ ${status} -ne 0 ] && grep -q 'Error attempting to evaluate the following rules' "${output_file}" ; then
134
+ echo "";
135
+ echo "This is firecow/gitlab-ci-local#1893: a \$variable nested inside an =~ regex";
136
+ echo "crashes rule evaluation, and drupal/gitlab_templates uses that pattern on";
137
+ echo "every ref. The full templates pipeline cannot run locally until that bug";
138
+ echo "is fixed upstream. Run the reproducible subset instead:";
139
+ echo " bash cmd-tools-gitlab-ci-local.sh ${PROJECT_NAME} --slim";
140
+ echo "(add a .gitlab-ci-local.yml first if the project has none — the";
141
+ echo "webship-gitlab-ci-local-runner skill carries the pattern), and gate the";
142
+ echo "template-only jobs on the remote pipeline.";
143
+ fi
144
+ rm -f "${output_file}" ;
145
+
146
+ echo "";
147
+ if [ ${status} -eq 0 ] ; then
148
+ echo "GREEN — every executed job passed. Jobs that cannot run locally are";
149
+ echo "not a pass: gate those on the remote pipeline before merging.";
150
+ else
151
+ echo "RED (exit ${status}) — the push is blocked. Fix the failing job and";
152
+ echo "re-run; never mask it with allow_failure or || true.";
153
+ fi
154
+ cd "${WORKSPACE_ROOT}/${doc_name}";
155
+ return ${status} ;
156
+ }
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # The command layer over fun-ddev-hostnames.sh: one project, or a listing of the
4
+ # whole workspace. Kept apart from the functions that touch DDEV so the reporting
5
+ # path cannot accidentally write anything.
6
+
7
+ function hostnames_command() {
8
+ local workspace_dir="${WORKSPACE_ROOT}/${doc_name}"
9
+ local project="${PROJECT_NAME}"
10
+
11
+ if [ -z "${project}" ] || [ "${project}" == '_none_' ] ; then
12
+ hostnames_list_workspace ;
13
+ return 0 ;
14
+ fi
15
+
16
+ project="$(trim_project_name "${project}")"
17
+ local dir="${workspace_dir}/${project}"
18
+ if [ ! -d "${dir}" ] ; then
19
+ echo "No project '${project}' in ${workspace_dir}." ; return 1 ;
20
+ fi
21
+ if [ ! -f "${dir}/.ddev/config.yaml" ] ; then
22
+ echo "'${project}' is not a DDEV project — there is no hostname to change." ; return 1 ;
23
+ fi
24
+
25
+ local changed='no'
26
+ if [ "${REMOVE}" != '_none_' ] && [ -n "${REMOVE}" ] ; then
27
+ ddev_hostnames_remove "${dir}" "${REMOVE}" || return 1 ;
28
+ changed='yes' ;
29
+ fi
30
+ local to_add=()
31
+ [ "${ADD}" != '_none_' ] && [ -n "${ADD}" ] && to_add+=("${ADD}")
32
+ if [ "${WITH_WORKSPACE}" == 'yes' ] ; then
33
+ to_add+=("$(ddev_workspace_hostname "${project}" "${doc_name}")")
34
+ fi
35
+ if [ "${#to_add[@]}" -gt 0 ] ; then
36
+ echo "Adding to ${doc_name}/${project}:" ;
37
+ ddev_hostnames_add "${dir}" "${to_add[@]}" || return 1 ;
38
+ changed='yes' ;
39
+ fi
40
+
41
+ echo "" ;
42
+ echo "*---------------------------------------------------------------------*" ;
43
+ echo " ${doc_name}/${project} answers at" ;
44
+ echo "*---------------------------------------------------------------------*" ;
45
+ ddev_hostnames_report "${dir}" "${project}" "${doc_name}" ;
46
+
47
+ # --start is honoured whether or not anything changed here. It was gated on
48
+ # `changed` at first, so `--start` on a project whose hostname was added a
49
+ # minute ago printed the report and did nothing — and the hostname stayed 404,
50
+ # which looks exactly like the feature not working.
51
+ if [ "${changed}" == 'yes' ] || [ "${START}" == 'yes' ] ; then
52
+ if [ "${START}" == 'yes' ] ; then
53
+ echo "" ;
54
+ echo "Starting the project so the router picks the change up…" ;
55
+ ( cd "${dir}" && ddev start -y ) || return 1 ;
56
+ else
57
+ echo "" ;
58
+ echo " Not live yet: a hostname reaches the router on the next start." ;
59
+ echo " Re-run with --start, or: cd ${dir} && ddev start" ;
60
+ fi
61
+ fi
62
+ }
63
+
64
+ # Every project in this workspace and what it answers at. The reason this exists
65
+ # as a listing: two projects claiming one hostname is invisible one project at a
66
+ # time, and it is exactly the mistake --with-workspace exists to avoid.
67
+ function hostnames_list_workspace() {
68
+ local workspace_dir="${WORKSPACE_ROOT}/${doc_name}" d p extra tld
69
+ tld="$(ddev_project_tld)"
70
+ echo "*---------------------------------------------------------------------*" ;
71
+ echo " ${doc_name}: what each project answers at (TLD: ${tld})" ;
72
+ echo "*---------------------------------------------------------------------*" ;
73
+ local found=0
74
+ for d in "${workspace_dir}"/*/ ; do
75
+ [ -d "${d}" ] || continue
76
+ p="$(basename "${d}")"
77
+ [ -f "${d}/.ddev/config.yaml" ] || continue
78
+ found=$((found+1))
79
+ extra="$(ddev_hostnames_list "${d}" | paste -sd' ' -)"
80
+ printf " %-34s %s\n" "${p}" "$(ddev_project_name "${d}" 2>/dev/null).${tld}" ;
81
+ [ -n "${extra}" ] && printf " %-34s + %s\n" "" "${extra}" ;
82
+ done
83
+ [ "${found}" -eq 0 ] && echo " no DDEV projects here." ;
84
+ echo "" ;
85
+ echo " Add one: bash cmd-tools-hostnames.sh <project> --add <label> --start" ;
86
+ echo " Or the flat, workspace-qualified one (<project>-${doc_name}):" ;
87
+ echo " bash cmd-tools-hostnames.sh <project> --with-workspace --start" ;
88
+ }