@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,44 @@
1
+ Feature: The actions rail
2
+ The rail on the right of every page collapses to its icons and remembers the choice.
3
+
4
+ # This exists because the feature was broken by having TWO of it. A delegated handler near the
5
+ # top of ui.js toggled the class and wrote `actions-collapsed`; a second implementation at
6
+ # the bottom, from another line of work, bound its own listener to the same button, read the
7
+ # already-toggled class and toggled it straight back. Every click undid itself a millisecond
8
+ # later, so the rail simply did not move. Nothing in the suite noticed, because nothing asserted
9
+ # what a click DOES — only that the button was on the page.
10
+ #
11
+ # So these assert the state after the click, in both directions, and that it is remembered.
12
+
13
+ Scenario: The rail starts collapsed, because the page wants the width more than the labels do
14
+ Given I am on "/dev"
15
+ Then the element "#actions-rail" should be displayed
16
+ And the element ".actions-toggle" should be displayed
17
+ And the element "html" with the attribute "class" and the value containing "actions-collapsed" should exist
18
+ And the element ".actions-toggle" with the attribute "aria-expanded" and the value "false" should exist
19
+
20
+ Scenario: Clicking the toggle expands it
21
+ Given I am on "/dev"
22
+ When I click on the element ".actions-toggle"
23
+ Then the element "html" with the attribute "class" and the value containing "actions-collapsed" should not exist
24
+ And the element ".actions-toggle" with the attribute "aria-expanded" and the value "true" should exist
25
+ And I should see "All workspaces"
26
+
27
+ Scenario: Clicking it again collapses it — the click is not undone by a second handler
28
+ Given I am on "/dev"
29
+ When I click on the element ".actions-toggle"
30
+ And I click on the element ".actions-toggle"
31
+ Then the element "html" with the attribute "class" and the value containing "actions-collapsed" should exist
32
+ And the element ".actions-toggle" with the attribute "aria-expanded" and the value "false" should exist
33
+
34
+ # A layout preference that resets on every navigation is one you set on every page.
35
+ Scenario: The choice survives a navigation
36
+ Given I am on "/dev"
37
+ When I click on the element ".actions-toggle"
38
+ And I am on "/settings"
39
+ Then the element "html" with the attribute "class" and the value containing "actions-collapsed" should not exist
40
+
41
+ Scenario: The rail is on the settings page too, not only on a workspace page
42
+ Given I am on "/settings"
43
+ Then the element "#actions-rail" should be displayed
44
+ And the element ".actions-toggle" should be displayed
@@ -0,0 +1,23 @@
1
+ Feature: Installing agents, skills and prompts
2
+
3
+ Scenario: An item can be installed into the global Claude Code, or into one project
4
+ Given I am on "/ai-agents"
5
+ Then "select[name='toWorkspace']" should be attached
6
+ And "select[name='toProject']" should be attached
7
+ And "[hx-post='/actions/install-item']" should be attached
8
+
9
+ # htmx 4 fires after:swap on the element that MADE the request, not on the one
10
+ # swapped — so a listener reading e.target saw the button and never opened the
11
+ # modal. The content had loaded; nothing appeared.
12
+ Scenario: Editing a prompt opens the editor with its text in it
13
+ Given I am on "/ai-prompts"
14
+ When I click on the element "[hx-get^='/fragments/ai-prompts/edit/'] >> nth=0"
15
+ Then "#editor-modal.uk-open" should be visible
16
+ And "#editor-modal .ace_editor" should be visible
17
+ And "#editor-modal form[hx-post='/actions/save-item']" should be attached
18
+
19
+ Scenario: The same Edit works on the agents workspace
20
+ Given I am on "/ai-agents"
21
+ When I click on the element "[hx-get^='/fragments/ai-agents/edit/'] >> nth=0"
22
+ Then "#editor-modal.uk-open" should be visible
23
+ And "#editor-modal .ace_editor" should be visible
@@ -0,0 +1,63 @@
1
+ Feature: Talking to the assistant
2
+ The panel takes dictation and reads its answer back. Both are the browser's own — no key, no
3
+ service, nothing leaves the machine — so what is asserted here is that the component was actually
4
+ handed a working configuration, not that a remote service replied.
5
+
6
+ # Asserting the button EXISTS, not that speech works: a scenario cannot speak, and a browser will
7
+ # not grant a microphone to an automated run. What can go wrong without anyone noticing is the
8
+ # button being absent, or present with a config deep-chat silently ignored — so that is the target.
9
+ Scenario: The assistant offers a microphone
10
+ Given I am on "/"
11
+ Then "deep-chat" should be attached
12
+ And the assistant should offer voice input
13
+ And the assistant should read its replies aloud
14
+
15
+ # The microphone is what says voice is available. It used to be said in the placeholder as well
16
+ # ("Ask about dev… (or use voice)"), but the composer ships with no placeholder at all now: an
17
+ # empty field with a cursor in it already says "type here", and a prompt that suggests what to ask
18
+ # narrows what gets asked. So the button has to be there AND have a name — an icon-only control
19
+ # with no accessible name is a button a screen reader announces as nothing.
20
+ Scenario: The microphone is there, and it is named
21
+ Given I am on "/"
22
+ Then the assistant should show a named microphone button
23
+
24
+ # Nothing drawn in the box, and the box still has a name. These are one scenario because they are
25
+ # in tension: deep-chat resolves the placeholder as `text || "Ask me anything!"`, so an empty
26
+ # string does not remove its placeholder, it restores deep-chat's — and the text it is given also
27
+ # becomes the composer's aria-label. Removing what is drawn without removing the name is the whole
28
+ # trick, and either half alone is a bug.
29
+ Scenario: The composer shows no placeholder, and is still named
30
+ Given I am on "/"
31
+ Then the assistant composer should draw no placeholder
32
+ And the assistant composer should have an accessible name
33
+
34
+ # The recogniser's language is the setting that decides whether dictation works in a second
35
+ # language at all: left on the wrong one it does not fail, it returns confident nonsense. So a
36
+ # language is always pinned rather than inherited — en-US ships, and the dropdown offers the rest.
37
+ Scenario: A dictation language is always pinned, never left to chance
38
+ Given I am on "/"
39
+ Then the assistant speech language should be pinned
40
+
41
+ # An empty phrase is not a disabled command. If `commands` were built from blank strings, a
42
+ # command could fire on almost anything dictated — so with none configured the key must be absent.
43
+ Scenario: No voice commands are armed unless one is configured
44
+ Given I am on "/"
45
+ Then the assistant should have no voice commands
46
+
47
+ Scenario: Voice styling follows the theme rather than deep-chat's stock colours
48
+ Given I am on "/"
49
+ Then the assistant speech colours should be design tokens
50
+
51
+ # The panel is on every workspace page, not only the home page, and its context travels with it.
52
+ Scenario: A workspace page gets the same microphone
53
+ Given I am on "/dev"
54
+ Then "deep-chat" should be attached
55
+ And the assistant should offer voice input
56
+
57
+ # A browser with no synthesis voices accepts speak(), fires error: synthesis-failed, and is silent.
58
+ # Nothing reported it, so "read replies aloud" looked switched on and did nothing at all — the worst
59
+ # state a setting can be in.
60
+ Scenario: The settings page says which voices this browser actually has
61
+ Given I am on "/settings"
62
+ Then "[data-voice-name]" should be attached
63
+ And the voice list should report what this browser has
@@ -0,0 +1,39 @@
1
+ Feature: The checks a project already declares
2
+ Every package here carries its own quality scripts. The dashboard offers them without inventing any.
3
+
4
+ # One quality menu, not two. On a packages workspace there is no browser suite at all, and on a
5
+ # site there was no checks control — a separate button would have been the only one present in
6
+ # each case. They live together under Tests, with the checks nested inside it.
7
+ Scenario: A package row offers its checks inside the Tests menu
8
+ Given I am on "/products"
9
+ Then the element ".project-row .act-menu-tests" should be displayed
10
+ And ".act-menu-tests .act-menu-checks" should be attached
11
+ And I should see "Tests"
12
+
13
+ Scenario: The button says what the package covers without running anything
14
+ Given I am on "/products"
15
+ Then the element ".act-menu-tests + .act-status" should be displayed
16
+ And "[hx-post='/actions/checks-plan']" should be attached
17
+
18
+ # The pair is the point: the canonical name is what you type (--only js), the code beside it is
19
+ # the script the package itself declared. Listing them together is how the mapping is checkable.
20
+ Scenario: The nested menu lists each alias against the script it runs
21
+ Given I am on "/products"
22
+ Then ".checks-sub" should be attached
23
+ And ".checks-sub .checks-alias" should be attached
24
+ And ".checks-sub .checks-script" should be attached
25
+
26
+ @needs-check-aliases
27
+ Scenario: Each alias can be run on its own, and so can all of them
28
+ Given I am on "/products"
29
+ Then "[hx-post='/actions/checks']" should be attached
30
+ And "[hx-vals*='only']" should be attached
31
+
32
+ # A site gets the same nested list: its package.json declares the same vocabulary, and its
33
+ # ddev-dev-tools add-on adds the PHP and Twig checks on top.
34
+ Scenario: A site keeps its testing verbs and gains the checks beside them
35
+ Given I am on "/dev"
36
+ Then the element ".project-row .act-menu-tests" should be displayed
37
+ And "[hx-post='/actions/testing-configure']" should be attached
38
+ And "[hx-post='/actions/testing-run']" should be attached
39
+ And ".act-menu-tests .act-menu-checks" should be attached
@@ -0,0 +1,30 @@
1
+ Feature: Cloning a project
2
+ The clone modal validates before anything runs, and never clones over an
3
+ existing project or a name DDEV already tracks.
4
+
5
+ Scenario: The DDEV menu offers the clone
6
+ Given I am on "/dev"
7
+ Then "[hx-get^='/fragments/projects/clone-form/dev/']" should be attached
8
+
9
+ Scenario: The form arrives prefilled, with the live check wired
10
+ Given I am on "/fragments/projects/clone-form/dev/v11x00b1i18n"
11
+ Then "input[name='to'][value='v11x00b1i18n-copy']" should be attached
12
+ And "select[name='toWorkspace']" should be attached
13
+ And "[hx-get='/fragments/projects/clone-check']" should be attached
14
+ And "textarea[name='prompt']" should be attached
15
+
16
+ Scenario: The live check refuses an existing project
17
+ Given I am on "/fragments/projects/clone-check?to=v11x00b1i18n&toWorkspace=dev"
18
+ Then I should see "already exists"
19
+
20
+ Scenario: The live check blesses a free name
21
+ Given I am on "/fragments/projects/clone-check?to=surely-free-name-zz&toWorkspace=dev"
22
+ Then I should see "is free"
23
+
24
+ Scenario: Cloning over an existing project is refused server-side too
25
+ When I post "/actions/clone-project" with '{"workspace":"dev","projectName":"v11x00b1i18n","to":"v11x00b1i18n","toWorkspace":"dev"}'
26
+ Then the action response should contain "already exists"
27
+
28
+ Scenario: A source that does not exist is refused
29
+ When I post "/actions/clone-project" with '{"workspace":"dev","projectName":"no-such-src","to":"whatever-zz","toWorkspace":"dev"}'
30
+ Then the action response should contain "Project not found"
@@ -0,0 +1,58 @@
1
+ Feature: Writing and changing the workspace commands
2
+ A cmd-*.sh is executed by the dashboard and by a terminal, so nothing changes one unreviewed.
3
+
4
+ Scenario: A new command can be given a purpose, not just a name
5
+ Given I am on "/settings/commands"
6
+ Then I should see "New command"
7
+
8
+ # The scaffold alone is a correct command that does nothing. Saying what it is FOR is what makes it
9
+ # a command for that thing — the assistant reads the workspace's own conventions and writes it.
10
+ Scenario: The new-command form asks what the command should do
11
+ Given I am on "/fragments/commands/new"
12
+ Then "textarea[name='purpose']" should be attached
13
+ And "input[name='newName']" should be attached
14
+ And "select[name='target']" should be attached
15
+
16
+ Scenario: The editor offers the assistant a change to make
17
+ Given I am on "/fragments/commands/edit/dev/cmd-tools-checks.sh"
18
+ Then "textarea[name='instruction']" should be attached
19
+ And ".cmd-ai-row .field-mic" should be attached
20
+ And "[hx-post='/actions/command-ai']" should be attached
21
+ And I should see "Ask"
22
+
23
+ # The command is still what gets saved by hand: the assistant is an extra way in, not the only one.
24
+ Scenario: The editor still edits the command directly
25
+ Given I am on "/fragments/commands/edit/dev/cmd-tools-checks.sh"
26
+ Then "textarea[name='content']" should be attached
27
+ And "[hx-post='/actions/command-save']" should be attached
28
+ And I should see "bash -n"
29
+
30
+ # 239 commands is too many to scroll. Searching matches the file name, the human name AND the
31
+ # description, because "reclaim" and "back up" are what somebody types and neither is a file name.
32
+ # A file name is a string you are about to type. In the body font it reads as prose and loses its
33
+ # word boundaries, and cmd-tool-backup-product.sh has a lot of boundaries.
34
+ Scenario: File names are shown as code wherever they appear
35
+ Given I am on "/fragments/commands/edit/dev/cmd-tools-checks.sh"
36
+ Then "h3 code.fname" should be attached
37
+ And "p code.fname" should be attached
38
+
39
+ Scenario: Commands can be searched and narrowed to one workspace folder
40
+ Given I am on "/commands"
41
+ Then "input[name='q']" should be attached
42
+ And "select[name='source']" should be attached
43
+ And ".cmd-title" should be attached
44
+ And ".cmd-file" should be attached
45
+
46
+ # Every list in the app 500d the moment `auto` reached the query, which is the first click of the
47
+ # auto-search checkbox: lists.js called hubDomain() without importing it.
48
+ Scenario: A list survives the auto-search preference being sent
49
+ Given I am on "/fragments/commands/list?q=backup&ws=all&auto=0&page=1"
50
+ Then ".cmd-title" should be attached
51
+
52
+ # Six action buttons and a full sentence on the same line squeezed each other into two-word
53
+ # columns. What a command is reads first; what you can do to it follows underneath.
54
+ Scenario: A command row reads top to bottom, with its actions on their own line
55
+ Given I am on "/settings/commands"
56
+ Then ".cmd-row-stack" should be attached
57
+ And ".cmd-row-stack .cmd-id" should be attached
58
+ And ".cmd-row-stack .project-actions" should be attached
@@ -0,0 +1,57 @@
1
+ Feature: The workspace dashboard
2
+ The pages a person opens every day, asserted against the running site.
3
+
4
+ Scenario: The hub lists the workspaces
5
+ Given I am on "/"
6
+ Then the element "#workspace-cards" should be displayed
7
+ And the element ".ws-card-wrap" should be displayed
8
+ And I should see "Products"
9
+ And I should see "Dev"
10
+ And I should see "RAG"
11
+
12
+ Scenario: A card carries the handle that reorders it
13
+ Given I am on "/"
14
+ Then the element ".ws-card-handle" should be displayed
15
+ And the element "#workspace-cards" with the attribute "data-sortable" and the value containing "ws-card-wrap" should exist
16
+
17
+ Scenario: A workspace page offers its builder and its projects
18
+ Given I am on "/dev"
19
+ Then I should see "Build a new project"
20
+ And the element ".project-row" should be displayed
21
+ And the element "select" should be displayed
22
+
23
+ Scenario: The settings file editor is reachable and shows the style block
24
+ Given I am on "/settings/settings.yml"
25
+ Then I should see "Workspace name"
26
+ And I should see "theme"
27
+
28
+ Scenario: The assistant panel is on the page it belongs to
29
+ Given I am on "/"
30
+ Then I should see "AI Assistant"
31
+
32
+ # It is ONE assistant, whose conversation follows you between workspaces — the thread id is a
33
+ # cookie on the hub domain for exactly that reason. The panel used to prefix the workspace it was
34
+ # scoped to ("Dev AI Assistant"), which read as a different assistant on every page. The scope is
35
+ # still shown, where it belongs: in the command picker, which carries that workspace's commands.
36
+ Scenario: The assistant is called the same thing on a workspace page
37
+ Given I am on "/dev"
38
+ Then I should see "AI Assistant"
39
+ And I should not see "Dev AI Assistant"
40
+ And I should see "the agent decides (Dev)"
41
+
42
+ # What it is called is configuration: `assistant: name:` in settings.yml for the dashboard, and in
43
+ # a workspace's own file for that workspace's page. Shipped, both say AI Assistant.
44
+ Scenario: Its name comes from the settings file, where anyone can change it
45
+ Given I am on "/settings/settings.yml"
46
+ Then I should see "What the assistant is called"
47
+ And I should see "What the box says when it is empty"
48
+
49
+ Scenario: A workspace with no projects still renders its page
50
+ Given I am on "/projects"
51
+ Then I should see "Projects"
52
+ And "#webship-workspace-projects" should be attached
53
+
54
+ Scenario: The assistant is a deep-chat component with its own input
55
+ Given I am on "/"
56
+ Then "#ws-deep-chat" should be attached
57
+ And "deep-chat" should be attached
@@ -0,0 +1,29 @@
1
+ Feature: The menus on a project row
2
+ Every project row carries its state above the name and its verbs in menus.
3
+
4
+ Scenario: State is a line above the folder name, not a word after it
5
+ Given I am on "/dev"
6
+ Then ".project-row .pcard-state-line" should be attached
7
+ And ".project-row .pcard-head" should be attached
8
+
9
+ # The Graph menu is the graph plugin's, asserted by its own feature.
10
+ Scenario: The row offers the DDEV and Tests menus
11
+ Given I am on "/dev"
12
+ Then ".project-row .act-menu-ddev" should be attached
13
+ And ".project-row .act-menu-tests" should be attached
14
+ And ".project-row .act-menu-more" should be attached
15
+
16
+ Scenario: A menu that carries a state word captions it under the button
17
+ Given I am on "/dev"
18
+ Then the element ".act-with-status" should be displayed
19
+ And the element ".act-with-status .act-status" should be displayed
20
+
21
+ # Opened on /rag rather than /dev: the rag workspace holds exactly one instance, so a click by
22
+ # selector is unambiguous. On a page of twelve rows every selector matches twelve buttons, and a
23
+ # test that has to say "the third one" is a test that breaks when a project is built.
24
+ Scenario: The DDEV menu opens and holds the verbs that moved into it
25
+ Given I am on "/dev"
26
+ And I click on the element ".project-row >> nth=0 >> .act-menu-ddev button"
27
+ Then ".uk-dropdown.uk-open" should be visible
28
+ And I should see "Restart"
29
+ And I should see "Describe (URLs, services)"
@@ -0,0 +1,47 @@
1
+ Feature: The Jira plugin on the project rows
2
+ A sites workspace project row offers its Jira surface, and the actions hold
3
+ their guards without ever needing Jira to answer.
4
+
5
+ # The menu is gated on twg + settings; in this environment both hold, so the
6
+ # rows carry the menu and the modal link.
7
+ Scenario: The JIRA menu is on the project rows
8
+ Given I am on "/dev"
9
+ Then "[hx-get^='/fragments/p/jira/list/dev/']" should be attached
10
+
11
+ # The guards answer without Jira: a malformed key never reaches twg.
12
+ Scenario: A malformed key is refused at the door
13
+ When I post "/actions/p/jira/task" with '{"workspace":"dev","projectName":"v11x00b1i18n","key":"not-a-key","mode":"view"}'
14
+ Then the action response should contain "Not a Jira key"
15
+
16
+ @needs-jira-writes-off
17
+ Scenario: Write modes are refused while Jira writes are off
18
+ When I post "/actions/p/jira/task" with '{"workspace":"dev","projectName":"v11x00b1i18n","key":"WEBSHIP-1","mode":"comment"}'
19
+ Then the action response should contain "Writing to Jira is off"
20
+
21
+ Scenario: An unknown project cannot host an agent
22
+ When I post "/actions/p/jira/task" with '{"workspace":"dev","projectName":"no-such-project","key":"WEBSHIP-1","mode":"view"}'
23
+ Then the action response should contain "Project not found"
24
+
25
+ Scenario: Watching a task nobody worked on says so
26
+ When I post "/actions/p/jira/task" with '{"workspace":"dev","projectName":"v11x00b1i18n","key":"WEBSHIP-424242","mode":"watch"}'
27
+ Then the action response should contain "No agent log"
28
+
29
+ Scenario: The Screens modal lists sessions or says there are none
30
+ Given I am on "/fragments/screens"
31
+ Then I should see "Screen sessions"
32
+
33
+ Scenario: Stopping a screen needs confirmation
34
+ When I post "/actions/screen-stop" with '{"session":"whatever-zz"}'
35
+ Then the action response should contain "requires confirmation"
36
+
37
+ Scenario: A hostile session name is refused
38
+ When I post "/actions/screen-stop" with '{"session":"x; rm -rf /","confirm":"yes"}'
39
+ Then the action response should contain "Not a screen session name"
40
+
41
+ Scenario: Remembering a Jira project refuses a bad key
42
+ When I post "/actions/jira-set-project" with '{"workspace":"dev","projectName":"v11x00b1i18n","key":"bad-key-1"}'
43
+ Then the action response should contain "Not a Jira project key"
44
+
45
+ Scenario: Remembering needs a real project
46
+ When I post "/actions/jira-set-project" with '{"workspace":"dev","projectName":"no-such","key":"WEBSHIP"}'
47
+ Then the action response should contain "Project not found"
@@ -0,0 +1,20 @@
1
+ Feature: Settings → Plugins
2
+ Optional features are packages, turned on in four steps; the page shows every package the
3
+ dashboard can see and the step each is at.
4
+
5
+ Scenario: The Plugins page lists the packages with their steps
6
+ Given I am on "/settings/plugins"
7
+ Then I should see "Plugins"
8
+ And the element ".plugin-card" should be displayed
9
+ And the element ".plugin-steps" should be displayed
10
+ And I should see "required"
11
+ And I should see "configured"
12
+
13
+ Scenario: A package can be required from the page
14
+ Given I am on "/settings/plugins"
15
+ Then the element ".plugin-require input[name=spec]" should be displayed
16
+ And I should see "Require"
17
+
18
+ Scenario: Settings offers Plugins among the dashboard's own sections
19
+ Given I am on "/settings"
20
+ Then I should see "Plugins"
@@ -0,0 +1,40 @@
1
+ Feature: What a project row can actually do
2
+ The verbs on a row, asserted where they are rather than by opening every menu.
3
+
4
+ # Each menu carries the name of the verb it opens (act-menu-ddev, act-menu-tests, …). A page of
5
+ # thirteen projects has thirteen of each, so these assert that the control and its items EXIST
6
+ # rather than clicking one — a test that has to say "the third one" breaks the moment a project
7
+ # is built. The one click test lives on /rag, which holds exactly one row.
8
+
9
+ Scenario: A row carries a menu for each thing it can do
10
+ Given I am on "/dev"
11
+ Then the element ".project-row .act-menu-ddev" should be displayed
12
+ And the element ".project-row .act-menu-tests" should be displayed
13
+ And the element ".project-row .act-menu-graph" should be displayed
14
+ And the element ".project-row .act-menu-more" should be displayed
15
+
16
+ # These two are the whole testing feature as far as the interface is concerned: one sets the
17
+ # environment up, the other runs the suite. Both post to their own action.
18
+ Scenario: The Tests menu offers setting the environment up and running the suite
19
+ Given I am on "/dev"
20
+ Then "[hx-post='/actions/testing-configure']" should be attached
21
+ And "[hx-post='/actions/testing-run']" should be attached
22
+
23
+ # The state under the button is the answer to "is there anything to look at yet" — it says
24
+ # webship, webship-js or none, and it is a caption under the control rather than a word inside it.
25
+ Scenario: A menu that carries a state word captions it under the button
26
+ Given I am on "/dev"
27
+ Then the element ".act-with-status .act-status" should be displayed
28
+
29
+ Scenario: The DDEV menu opens and holds the verbs that moved into it
30
+ Given I am on "/rag"
31
+ When I click on the element ".project-row .act-menu-ddev button"
32
+ Then ".uk-dropdown.uk-open" should be visible
33
+ And I should see "Restart"
34
+ And I should see "Describe (URLs, services)"
35
+
36
+ # Launch belongs with the hostname it opens, not in the row of things you DO to a project.
37
+ Scenario: A running project offers its own URL beside the Launch button
38
+ Given I am on "/dev"
39
+ Then the element ".proj-launch-line" should be displayed
40
+ And the element ".proj-launch-line .proj-alias" should be displayed
@@ -0,0 +1,29 @@
1
+ Feature: The Screens manager
2
+ Screen sessions are where long work lives — Jira agents, builds, anything
3
+ started with cmd-tools-screen.sh. The page must list them, refuse what would
4
+ reach a shell, and never let another site drive it.
5
+
6
+ Scenario: Screens is its own page, not a settings tab
7
+ Given I am on "/screens"
8
+ Then I should see "New screen"
9
+ And I should see "Remove ended sessions"
10
+
11
+ Scenario: The old settings URL still lands on the manager
12
+ Given I am on "/settings/screens"
13
+ Then I should see "New screen"
14
+
15
+ Scenario: A new session needs a place that the server offered
16
+ When I post "/actions/screen-new" with '{"session":"zz-nope","target":"/etc"}'
17
+ Then the action response should contain "Unknown place"
18
+
19
+ Scenario: A session name that screen would read as an option is refused
20
+ When I post "/actions/screen-new" with '{"session":"-S","target":"root"}'
21
+ Then the action response should contain "session name"
22
+
23
+ Scenario: Killing a session is refused without confirmation
24
+ When I post "/actions/screen-stop" with '{"session":"whatever-zz"}'
25
+ Then the action response should contain "requires confirmation"
26
+
27
+ Scenario: A hostile session name never reaches screen
28
+ When I post "/actions/screen-interrupt" with '{"session":"x; rm -rf /"}'
29
+ Then the action response should contain "Not a screen session name"
@@ -0,0 +1,46 @@
1
+ Feature: The settings editor
2
+ The one page that holds real credentials, so what it does NOT show matters as much as what it does.
3
+
4
+ Scenario: The editor lists the settings files and edits one at a time
5
+ Given I am on "/settings/settings.yml"
6
+ Then the element ".settings-tabs" should be displayed
7
+ And I should see "settings.yml"
8
+ And I should see "Workspace name"
9
+
10
+ # A secret's value never reaches the browser: the field renders empty with a note saying a blank
11
+ # submission keeps what is on disk. This asserts the mechanism rather than the absence of one
12
+ # particular string, which would pass on a page that simply failed to render.
13
+ # The note lives in the field's placeholder, not in the page text: it belongs to the box you are
14
+ # about to type in, and as body copy it would repeat itself once per secret on the page.
15
+ Scenario: A secret is offered as a field to replace, never as a value to read
16
+ Given I am on "/settings/settings.yml"
17
+ Then the element "input[type='password']" should be displayed
18
+ And the element "input[type='password']" with the attribute "placeholder" and the value containing "leave blank to keep" should exist
19
+ And the element "input[type='password']" with the attribute "value" and the value containing "-" should not exist
20
+
21
+ # account.pass is deliberately NOT a secret: it is the admin password a fresh local install is
22
+ # given, and masking it made the field useless for the one thing it is for.
23
+ Scenario: The local admin password stays readable, because that is what it is for
24
+ Given I am on "/settings/settings.yml"
25
+ Then I should see "pass"
26
+ And I should see "That admin password"
27
+
28
+ Scenario: A workspace has its own settings file with its card presentation in it
29
+ Given I am on "/settings/workspace.rag.settings.yml"
30
+ Then I should see "presentation"
31
+ And the element "#ws-presentation" should be displayed
32
+
33
+ # The icon chooser writes only the two fields it owns. The rest of the block — label, noun, kind,
34
+ # also_files — has to still be there afterwards, which is what the unit tests assert; here we
35
+ # assert the chooser is what the page offers rather than a free-text field.
36
+ Scenario: The icon is chosen from the icons that will actually render
37
+ Given I am on "/settings/workspace.rag.settings.yml"
38
+ Then the element ".icon-filter" should be displayed
39
+ And the element ".icon-grid" should be displayed
40
+
41
+ Scenario: The settings hub groups what can be configured and leads to the files
42
+ Given I am on "/settings"
43
+ Then I should see "The dashboard"
44
+ And I should see "Workspace settings"
45
+ And I should see "Styles"
46
+ And "a[href='/settings/settings.yml']" should be attached
@@ -0,0 +1,32 @@
1
+ Feature: The report a test run leaves behind
2
+ A finished run is readable in the dashboard and downloadable as a document.
3
+
4
+ # The report opens in a modal from the Tests menu, so the row links to the FRAGMENT that renders
5
+ # it. Asserted on the fragment itself rather than by opening thirteen menus to find one.
6
+ @needs-test-report
7
+ Scenario: The Tests menu links to the report of a project that has been tested
8
+ Given I am on "/dev"
9
+ Then "[hx-get^='/fragments/dev/test-report/']" should be attached
10
+
11
+ @needs-test-report
12
+ Scenario: The report offers itself as a PDF, for people who were not at the run
13
+ Given I am on "/fragments/dev/test-report/amd-website_starter-1-0-x-site-template-manager"
14
+ Then I should see "Download as PDF"
15
+ And "[href^='/report-pdf/dev/']" should be attached
16
+
17
+ # Not navigated to: the route answers with Content-Disposition: attachment, which a browser
18
+ # downloads rather than renders — so the PDF itself is asserted by the unit tests, which check
19
+ # the document it builds. This checks the interface offers it.
20
+ @needs-test-report
21
+ Scenario: The report leads with the counts, not with a list to scroll
22
+ Given I am on "/fragments/dev/test-report/amd-website_starter-1-0-x-site-template-manager"
23
+ Then I should see "passed"
24
+ And I should see "failed"
25
+ And I should see "scenarios"
26
+ And the element ".uk-label-success" should be displayed
27
+ And the element ".uk-label-danger" should be displayed
28
+
29
+ @needs-test-report
30
+ Scenario: The HTML report is reachable from it as well
31
+ Given I am on "/fragments/dev/test-report/amd-website_starter-1-0-x-site-template-manager"
32
+ Then I should see "Open the HTML report"
@@ -0,0 +1,40 @@
1
+ Feature: The theme system
2
+ One stylesheet is assembled from a base, the components, and the palette last.
3
+
4
+ Scenario: The page asks for the assembled stylesheet, not a file on disk
5
+ Given I am on "/"
6
+ Then "link[href*='/style.css?v=']" should be attached
7
+
8
+ # Which style is last is a per-machine setting, so naming one here asserted the machine rather
9
+ # than the code: the scenario failed on any machine not wearing `default`, which since the Styles
10
+ # page is most of them. What the assembly guarantees is the ORDER — base, components, then a
11
+ # style — so that is what is asserted.
12
+ Scenario: The assembled sheet carries the base, the components and a style
13
+ Given I am on "/style.css"
14
+ Then I should see "/* base */"
15
+ And I should see "/* component: workspace-cards */"
16
+ And I should see "/* component: project-rows */"
17
+ And I should see "/* theme:"
18
+
19
+ # Every style names itself and declares the palette tokens, whichever one is worn.
20
+ Scenario: The style in use names itself and declares its palette
21
+ Given I am on "/style.css"
22
+ Then I should see "@name"
23
+ And I should see "--brand-primary:"
24
+
25
+ # Not a button: the only primary button on the home page used to be the assistant's Send, and
26
+ # deep-chat renders its own inside a shadow root where a selector cannot reach it. The card chips
27
+ # carry the brand colour on every page, which is what this scenario is actually about.
28
+ Scenario: The dashboard still renders with its own brand colour
29
+ Given I am on "/"
30
+ Then the element "#workspace-cards" should be displayed
31
+ And the element ".ws-card-wrap .uk-label" should be displayed
32
+
33
+ # The favicon is the artwork from the brand tokens (node 5743:11748): a square with the emblem
34
+ # SUBTRACTED out of it, one boolean path. Its fill flips with the viewer's colour scheme, because a
35
+ # knocked-out mark has no colour of its own — asserted on the file in tests/unit/favicon.test.js,
36
+ # since a browser handed an SVG renders it as an image and there is nothing here to select.
37
+ Scenario: The tab carries the Webship favicon, not a bare emblem
38
+ Given I am on "/"
39
+ Then "link[rel='alternate icon'][href$='.png']" should be attached
40
+ And "link[rel='apple-touch-icon'][href$='.png']" should be attached
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Steps that exercise an action's GUARDS over the wire, without a browser round
3
+ * trip: post the form, read the fragment that comes back. Used for actions whose
4
+ * happy path needs an external system (Jira through twg) — the guards answer
5
+ * locally and deterministically either way, and they are what must not regress.
6
+ */
7
+
8
+ 'use strict';
9
+
10
+ const { When, Then } = require('@cucumber/cucumber');
11
+ const assert = require('assert');
12
+
13
+ When('I post {string} with {string}', async function (path, json) {
14
+ const form = JSON.parse(json);
15
+ const base = process.env.LAUNCH_URL || 'https://workspace.ddev.site';
16
+ const response = await this.page.request.post(`${base}${path}`, { form });
17
+ this.lastActionResponse = await response.text();
18
+ });
19
+
20
+ Then('the action response should contain {string}', function (needle) {
21
+ assert.ok(
22
+ (this.lastActionResponse || '').includes(needle),
23
+ `expected the response to contain ${JSON.stringify(needle)} — got: ${(this.lastActionResponse || '').slice(0, 300)}`,
24
+ );
25
+ });