@webship.co/workspace 1.0.0-alpha1 → 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.
- package/LICENSE +339 -0
- package/README.md +28 -364
- package/core/bin/workspace.js +135 -0
- package/core/config/settings.labels.yml +514 -0
- package/core/config/settings.template.yml +292 -0
- package/core/config/style.yml +53 -0
- package/core/config/theme.default.yml +161 -0
- package/core/config/theme.dispatch.yml +166 -0
- package/core/config/theme.drupal.yml +175 -0
- package/core/config/theme.ember.yml +160 -0
- package/core/config/theme.github.yml +172 -0
- package/core/config/theme.gitlab.yml +168 -0
- package/core/config/theme.press.yml +161 -0
- package/core/config/theme.slate.yml +160 -0
- package/core/config/theme.upsun.yml +174 -0
- package/core/docs/architecture.svg +65 -0
- package/core/docs/getting-started.md +51 -0
- package/core/docs/plugins.md +27 -0
- package/core/docs/releases.md +23 -0
- package/core/docs/testing.md +15 -0
- package/core/docs/workspaces.md +25 -0
- package/core/scripts/args/arg-ai-items.sh +65 -0
- package/core/scripts/args/arg-autostart.sh +31 -0
- package/core/scripts/args/arg-avatar-agent.sh +28 -0
- package/core/scripts/args/arg-avatar-catalog.sh +12 -0
- package/core/scripts/args/arg-avatar-character.sh +68 -0
- package/core/scripts/args/arg-avatar-voice.sh +24 -0
- package/core/scripts/args/arg-avatar.sh +22 -0
- package/core/scripts/args/arg-checks.sh +36 -0
- package/core/scripts/args/arg-clone.sh +42 -0
- package/core/scripts/args/arg-commands.sh +51 -0
- package/core/scripts/args/arg-cucumber.sh +34 -0
- package/core/scripts/args/arg-distribution.sh +30 -0
- package/core/scripts/args/arg-drupal.sh +39 -0
- package/core/scripts/args/arg-drupal_cms.sh +18 -0
- package/core/scripts/args/arg-gitlab-ci-local.sh +25 -0
- package/core/scripts/args/arg-graphify.sh +36 -0
- package/core/scripts/args/arg-graphs.sh +12 -0
- package/core/scripts/args/arg-hostnames.sh +23 -0
- package/core/scripts/args/arg-milvus-backup.sh +8 -0
- package/core/scripts/args/arg-milvus-mcp.sh +12 -0
- package/core/scripts/args/arg-milvus.sh +32 -0
- package/core/scripts/args/arg-obsidian.sh +17 -0
- package/core/scripts/args/arg-odoo.sh +18 -0
- package/core/scripts/args/arg-penpot-backup.sh +8 -0
- package/core/scripts/args/arg-penpot-mcp.sh +15 -0
- package/core/scripts/args/arg-penpot-token.sh +17 -0
- package/core/scripts/args/arg-penpot.sh +44 -0
- package/core/scripts/args/arg-rag.sh +21 -0
- package/core/scripts/args/arg-ragify.sh +35 -0
- package/core/scripts/args/arg-reclaim.sh +18 -0
- package/core/scripts/args/arg-release.sh +21 -0
- package/core/scripts/args/arg-screen.sh +28 -0
- package/core/scripts/args/arg-site-template.sh +13 -0
- package/core/scripts/args/arg-spdd.sh +16 -0
- package/core/scripts/args/arg-specs.sh +22 -0
- package/core/scripts/args/arg-storage.sh +36 -0
- package/core/scripts/args/arg-testing.sh +36 -0
- package/core/scripts/args/arg-webship.sh +34 -0
- package/core/scripts/args/arg-webships-project.sh +22 -0
- package/core/scripts/args/arg-webships-site-template.sh +17 -0
- package/core/scripts/args/arg-webships.sh +34 -0
- package/core/scripts/args/arg-website-site-template.sh +17 -0
- package/core/scripts/args/arg-website.sh +25 -0
- package/core/scripts/args/arg-wordpress.sh +18 -0
- package/core/scripts/autostart-run.sh +162 -0
- package/core/scripts/autostart-stop.sh +30 -0
- package/core/scripts/autostart-watch.sh +43 -0
- package/core/scripts/autostart.sh +26 -0
- package/core/scripts/bootstrap-functions.sh +117 -0
- package/core/scripts/bootstrap-libraries.sh +10 -0
- package/core/scripts/bootstrap.sh +71 -0
- package/core/scripts/ddev-shim/ddev +122 -0
- package/core/scripts/docker-gid.sh +119 -0
- package/core/scripts/functions/arg-site-template.sh +28 -0
- package/core/scripts/functions/fun-ai-items-lock.sh +175 -0
- package/core/scripts/functions/fun-ai-items-sources.sh +298 -0
- package/core/scripts/functions/fun-ai-items.sh +621 -0
- package/core/scripts/functions/fun-ai-providers.sh +72 -0
- package/core/scripts/functions/fun-autostart.sh +429 -0
- package/core/scripts/functions/fun-avatar.sh +441 -0
- package/core/scripts/functions/fun-backup-item.sh +50 -0
- package/core/scripts/functions/fun-build-distribution.sh +226 -0
- package/core/scripts/functions/fun-build-site-template.sh +104 -0
- package/core/scripts/functions/fun-build-webships.sh +161 -0
- package/core/scripts/functions/fun-build-website.sh +199 -0
- package/core/scripts/functions/fun-checks.sh +243 -0
- package/core/scripts/functions/fun-clone-project.sh +289 -0
- package/core/scripts/functions/fun-commands.sh +521 -0
- package/core/scripts/functions/fun-database.sh +63 -0
- package/core/scripts/functions/fun-ddev-hostnames.sh +213 -0
- package/core/scripts/functions/fun-ddev-nodejs.sh +15 -0
- package/core/scripts/functions/fun-ddev-telemetry.sh +15 -0
- package/core/scripts/functions/fun-default-settings.sh +28 -0
- package/core/scripts/functions/fun-distribution-cucumber.sh +45 -0
- package/core/scripts/functions/fun-distribution-drupal.sh +25 -0
- package/core/scripts/functions/fun-distribution-drupal_cms.sh +35 -0
- package/core/scripts/functions/fun-distribution-webship.sh +28 -0
- package/core/scripts/functions/fun-distribution-webships.sh +33 -0
- package/core/scripts/functions/fun-distribution-website.sh +19 -0
- package/core/scripts/functions/fun-drush.sh +48 -0
- package/core/scripts/functions/fun-elevenlabs.sh +179 -0
- package/core/scripts/functions/fun-files.sh +19 -0
- package/core/scripts/functions/fun-git-worktrees.sh +142 -0
- package/core/scripts/functions/fun-gitlab-ci.sh +156 -0
- package/core/scripts/functions/fun-hostnames-cli.sh +88 -0
- package/core/scripts/functions/fun-milvus.sh +584 -0
- package/core/scripts/functions/fun-odoo.sh +121 -0
- package/core/scripts/functions/fun-penpot.sh +724 -0
- package/core/scripts/functions/fun-project-name.sh +20 -0
- package/core/scripts/functions/fun-rag.sh +253 -0
- package/core/scripts/functions/fun-ragify.sh +165 -0
- package/core/scripts/functions/fun-reclaim.sh +297 -0
- package/core/scripts/functions/fun-release.sh +159 -0
- package/core/scripts/functions/fun-remove-project.sh +319 -0
- package/core/scripts/functions/fun-screen.sh +96 -0
- package/core/scripts/functions/fun-spdd.sh +676 -0
- package/core/scripts/functions/fun-specs-share.sh +237 -0
- package/core/scripts/functions/fun-storage.sh +347 -0
- package/core/scripts/functions/fun-testing.sh +329 -0
- package/core/scripts/functions/fun-users.sh +87 -0
- package/core/scripts/functions/fun-version.sh +72 -0
- package/core/scripts/functions/fun-video-edit.sh +48 -0
- package/core/scripts/functions/fun-voice.sh +45 -0
- package/core/scripts/functions/fun-wordpress.sh +59 -0
- package/core/scripts/host-mounts.sh +161 -0
- package/core/scripts/install.sh +602 -0
- package/core/scripts/libs/__pycache__/video_edit.cpython-312.pyc +0 -0
- package/core/scripts/libs/argparse.sh +93 -0
- package/core/scripts/libs/bash-yaml.sh +52 -0
- package/core/scripts/libs/checks_plan.js +312 -0
- package/core/scripts/libs/elevenlabs.py +627 -0
- package/core/scripts/libs/progress-bar.sh +19 -0
- package/core/scripts/libs/rag_index.py +446 -0
- package/core/scripts/libs/video_edit.py +636 -0
- package/core/scripts/libs/voice.py +430 -0
- package/core/scripts/plugins/jira/host-install.sh +119 -0
- package/core/scripts/plugins/jira/host-mounts.txt +2 -0
- package/core/scripts/plugins/upsun/args/arg-upsun.sh +51 -0
- package/core/scripts/plugins/upsun/functions/fun-upsun.sh +304 -0
- package/core/scripts/plugins/upsun/host-install.sh +99 -0
- package/core/scripts/plugins/upsun/host-mounts.txt +1 -0
- package/core/scripts/plugins/upsun/upsun-ai.sh +133 -0
- package/core/scripts/plugins.sh +152 -0
- package/core/scripts/release.sh +69 -0
- package/core/scripts/storage.sh +39 -0
- package/core/scripts/sync-tooling.sh +246 -0
- package/core/scripts/tests/cmd-smoke-test.sh +109 -0
- package/core/scripts/trust-https.sh +257 -0
- package/core/workspace-app/.ddev/commands/web/test-dashboard +49 -0
- package/core/workspace-app/.ddev/config.yaml +400 -0
- package/core/workspace-app/.ddev/docker-compose.dood.yaml +45 -0
- package/core/workspace-app/.ddev/docker-compose.plugin-jira-twg.yaml +26 -0
- package/core/workspace-app/.ddev/docker-compose.plugin-upsun-upsun-cli.yaml +8 -0
- package/core/workspace-app/.ddev/docker-compose.screens.yaml +15 -0
- package/core/workspace-app/.ddev/nginx_full/nginx-site.conf +114 -0
- package/core/workspace-app/.ddev/web-build/Dockerfile.workspace-app +203 -0
- package/core/workspace-app/.ddev/web-build/ddev-shim-ddev +122 -0
- package/{PLUGINS.md → core/workspace-app/PLUGINS.md} +1 -1
- package/core/workspace-app/README.md +380 -0
- package/{actions → core/workspace-app/actions}/ddev.js +0 -1
- package/{actions → core/workspace-app/actions}/rag.js +0 -1
- package/{actions → core/workspace-app/actions}/testing.js +0 -1
- package/{assistant.js → core/workspace-app/assistant.js} +1 -10
- package/{git-info.js → core/workspace-app/git-info.js} +17 -1
- package/core/workspace-app/package.json +29 -0
- package/core/workspace-app/plugin-catalog.js +50 -0
- package/{plugin-loader.js → core/workspace-app/plugin-loader.js} +19 -1
- package/{plugins-page.js → core/workspace-app/plugins-page.js} +28 -2
- package/{row-layout.js → core/workspace-app/row-layout.js} +0 -1
- package/{server.js → core/workspace-app/server.js} +26 -225
- package/core/workspace-app/tests/features/actions-rail.feature +44 -0
- package/core/workspace-app/tests/features/ai-items.feature +23 -0
- package/core/workspace-app/tests/features/assistant-speech.feature +63 -0
- package/core/workspace-app/tests/features/checks.feature +39 -0
- package/core/workspace-app/tests/features/clone-project.feature +30 -0
- package/core/workspace-app/tests/features/command-authoring.feature +58 -0
- package/core/workspace-app/tests/features/dashboard.feature +57 -0
- package/core/workspace-app/tests/features/menus.feature +29 -0
- package/core/workspace-app/tests/features/plugins/jira/jira.feature +47 -0
- package/core/workspace-app/tests/features/plugins.feature +20 -0
- package/core/workspace-app/tests/features/project-actions.feature +40 -0
- package/core/workspace-app/tests/features/screens.feature +29 -0
- package/core/workspace-app/tests/features/settings.feature +46 -0
- package/core/workspace-app/tests/features/test-reports.feature +32 -0
- package/core/workspace-app/tests/features/theme.feature +40 -0
- package/core/workspace-app/tests/step-definitions/actions-post.steps.js +25 -0
- package/core/workspace-app/tests/step-definitions/assistant-speech.steps.js +152 -0
- package/core/workspace-app/tests/step-definitions/preconditions.steps.js +100 -0
- package/core/workspace-app/tests/unit/_isolated-config.js +31 -0
- package/core/workspace-app/tests/unit/accessibility.test.js +124 -0
- package/core/workspace-app/tests/unit/actions-rail-ux.test.js +56 -0
- package/core/workspace-app/tests/unit/actions-rail.test.js +51 -0
- package/core/workspace-app/tests/unit/ai-inventory.test.js +64 -0
- package/core/workspace-app/tests/unit/app-docs.test.js +64 -0
- package/core/workspace-app/tests/unit/assistant-avatar.test.js +110 -0
- package/core/workspace-app/tests/unit/assistant-cast.test.js +105 -0
- package/core/workspace-app/tests/unit/assistant-send-animation.test.js +15 -0
- package/core/workspace-app/tests/unit/assistant-suggestions.test.js +112 -0
- package/core/workspace-app/tests/unit/assistant-switches.test.js +53 -0
- package/core/workspace-app/tests/unit/assistant-views.test.js +146 -0
- package/core/workspace-app/tests/unit/assistant-working-indicator.test.js +49 -0
- package/core/workspace-app/tests/unit/assistant.test.js +61 -0
- package/core/workspace-app/tests/unit/audio-player.test.js +147 -0
- package/core/workspace-app/tests/unit/audio-voice.test.js +634 -0
- package/core/workspace-app/tests/unit/auth-google.test.js +180 -0
- package/core/workspace-app/tests/unit/autostart-watch.test.js +76 -0
- package/core/workspace-app/tests/unit/browsers.test.js +76 -0
- package/core/workspace-app/tests/unit/build-distribution.test.js +125 -0
- package/core/workspace-app/tests/unit/build-order.test.js +153 -0
- package/core/workspace-app/tests/unit/builder-args.test.js +113 -0
- package/core/workspace-app/tests/unit/builders.test.js +158 -0
- package/core/workspace-app/tests/unit/card-state-toggle.test.js +29 -0
- package/core/workspace-app/tests/unit/changelog.test.js +177 -0
- package/core/workspace-app/tests/unit/chat-thread.test.js +92 -0
- package/core/workspace-app/tests/unit/checks-plan.test.js +205 -0
- package/core/workspace-app/tests/unit/claude-args.test.js +182 -0
- package/core/workspace-app/tests/unit/claude-code-here.test.js +15 -0
- package/core/workspace-app/tests/unit/claude-resume.test.js +147 -0
- package/core/workspace-app/tests/unit/claude-screen-options.test.js +84 -0
- package/core/workspace-app/tests/unit/claude-session.test.js +41 -0
- package/core/workspace-app/tests/unit/command-flags.test.js +45 -0
- package/core/workspace-app/tests/unit/command-palette.test.js +105 -0
- package/core/workspace-app/tests/unit/commands-center.test.js +338 -0
- package/core/workspace-app/tests/unit/composer-menu.test.js +187 -0
- package/core/workspace-app/tests/unit/config-yaml.test.js +116 -0
- package/core/workspace-app/tests/unit/confirm-dialog.test.js +69 -0
- package/core/workspace-app/tests/unit/create-card.test.js +85 -0
- package/core/workspace-app/tests/unit/ddev-addons.test.js +144 -0
- package/core/workspace-app/tests/unit/ddev-auth-ssh.test.js +40 -0
- package/core/workspace-app/tests/unit/ddev-custom-commands.test.js +56 -0
- package/core/workspace-app/tests/unit/ddev-diagnose.test.js +57 -0
- package/core/workspace-app/tests/unit/ddev-domains.test.js +153 -0
- package/core/workspace-app/tests/unit/ddev-hostnames.test.js +143 -0
- package/core/workspace-app/tests/unit/ddev-import.test.js +82 -0
- package/core/workspace-app/tests/unit/ddev-mail.test.js +135 -0
- package/core/workspace-app/tests/unit/ddev-menu-and-create.test.js +28 -0
- package/core/workspace-app/tests/unit/ddev-mutagen.test.js +37 -0
- package/core/workspace-app/tests/unit/ddev-options.test.js +51 -0
- package/core/workspace-app/tests/unit/ddev-share.test.js +40 -0
- package/core/workspace-app/tests/unit/ddev-shim.test.js +57 -0
- package/core/workspace-app/tests/unit/ddev-snapshots.test.js +142 -0
- package/core/workspace-app/tests/unit/ddev-start-daemons.test.js +62 -0
- package/core/workspace-app/tests/unit/ddev-xdebug.test.js +41 -0
- package/core/workspace-app/tests/unit/deep-chat-origin.test.js +38 -0
- package/core/workspace-app/tests/unit/density.test.js +52 -0
- package/core/workspace-app/tests/unit/elevenlabs.test.js +453 -0
- package/core/workspace-app/tests/unit/event-log.test.js +102 -0
- package/core/workspace-app/tests/unit/favicon.test.js +68 -0
- package/core/workspace-app/tests/unit/files-browser.test.js +224 -0
- package/core/workspace-app/tests/unit/git-info.test.js +26 -0
- package/core/workspace-app/tests/unit/grid-and-list.test.js +103 -0
- package/core/workspace-app/tests/unit/host-tool-wrapper.test.js +18 -0
- package/core/workspace-app/tests/unit/html-patterns.test.js +51 -0
- package/core/workspace-app/tests/unit/ide-infra.test.js +28 -0
- package/core/workspace-app/tests/unit/images-ai.test.js +201 -0
- package/core/workspace-app/tests/unit/images-create.test.js +59 -0
- package/core/workspace-app/tests/unit/images-providers.test.js +248 -0
- package/core/workspace-app/tests/unit/images-svg.test.js +213 -0
- package/core/workspace-app/tests/unit/images-workspace.test.js +144 -0
- package/core/workspace-app/tests/unit/jobs-fragment.test.js +66 -0
- package/core/workspace-app/tests/unit/media-ux.test.js +164 -0
- package/core/workspace-app/tests/unit/modal-fit.test.js +87 -0
- package/core/workspace-app/tests/unit/modules-load.test.js +23 -0
- package/core/workspace-app/tests/unit/narration.test.js +186 -0
- package/core/workspace-app/tests/unit/navigation-editor.test.js +260 -0
- package/core/workspace-app/tests/unit/navigation.test.js +254 -0
- package/core/workspace-app/tests/unit/new-folder.test.js +121 -0
- package/core/workspace-app/tests/unit/new-screen-form.test.js +149 -0
- package/core/workspace-app/tests/unit/node-menu.test.js +161 -0
- package/core/workspace-app/tests/unit/notes.test.js +128 -0
- package/core/workspace-app/tests/unit/page-structure.test.js +40 -0
- package/core/workspace-app/tests/unit/page-width.test.js +59 -0
- package/core/workspace-app/tests/unit/php-version.test.js +90 -0
- package/core/workspace-app/tests/unit/plan-card.test.js +44 -0
- package/core/workspace-app/tests/unit/plugin-catalog.test.js +31 -0
- package/core/workspace-app/tests/unit/plugin-system.test.js +251 -0
- package/core/workspace-app/tests/unit/plugins-page.test.js +28 -0
- package/core/workspace-app/tests/unit/plugins.test.js +58 -0
- package/core/workspace-app/tests/unit/project-activity-filter.test.js +180 -0
- package/core/workspace-app/tests/unit/project-make.test.js +143 -0
- package/core/workspace-app/tests/unit/project-name.test.js +202 -0
- package/core/workspace-app/tests/unit/reader.test.js +62 -0
- package/core/workspace-app/tests/unit/release.test.js +92 -0
- package/core/workspace-app/tests/unit/remove-confirm.test.js +37 -0
- package/core/workspace-app/tests/unit/report-pdf.test.js +171 -0
- package/core/workspace-app/tests/unit/round-11.test.js +31 -0
- package/core/workspace-app/tests/unit/round-12.test.js +37 -0
- package/core/workspace-app/tests/unit/row-layout.test.js +585 -0
- package/core/workspace-app/tests/unit/row-menus-fold.test.js +29 -0
- package/core/workspace-app/tests/unit/rows-add-modal.test.js +68 -0
- package/core/workspace-app/tests/unit/screen-runner-queue.test.js +41 -0
- package/core/workspace-app/tests/unit/screen-window.test.js +116 -0
- package/core/workspace-app/tests/unit/screens-beside-running.test.js +19 -0
- package/core/workspace-app/tests/unit/screens-columns.test.js +79 -0
- package/core/workspace-app/tests/unit/screens-menu.test.js +84 -0
- package/core/workspace-app/tests/unit/screens-modal-overlay.test.js +14 -0
- package/core/workspace-app/tests/unit/screens-waiting.test.js +129 -0
- package/core/workspace-app/tests/unit/screens.test.js +74 -0
- package/core/workspace-app/tests/unit/second-storage.test.js +218 -0
- package/core/workspace-app/tests/unit/session-name.test.js +64 -0
- package/core/workspace-app/tests/unit/settings-file.test.js +173 -0
- package/core/workspace-app/tests/unit/settings-nested-list.test.js +54 -0
- package/core/workspace-app/tests/unit/settings-raw.test.js +177 -0
- package/core/workspace-app/tests/unit/shared-prefs.test.js +49 -0
- package/core/workspace-app/tests/unit/speech.test.js +290 -0
- package/core/workspace-app/tests/unit/static-caching.test.js +39 -0
- package/core/workspace-app/tests/unit/status-language.test.js +47 -0
- package/core/workspace-app/tests/unit/tab-modal.test.js +69 -0
- package/core/workspace-app/tests/unit/tab-title.test.js +37 -0
- package/core/workspace-app/tests/unit/template-literals.test.js +52 -0
- package/core/workspace-app/tests/unit/terminal-scrollback.test.js +61 -0
- package/core/workspace-app/tests/unit/terminal-size.test.js +103 -0
- package/core/workspace-app/tests/unit/terminal-style.test.js +84 -0
- package/core/workspace-app/tests/unit/terminal-windows.test.js +154 -0
- package/core/workspace-app/tests/unit/themes.test.js +453 -0
- package/core/workspace-app/tests/unit/tool-labels.test.js +34 -0
- package/core/workspace-app/tests/unit/topbar-icons.test.js +47 -0
- package/core/workspace-app/tests/unit/update-docker-gid.test.js +51 -0
- package/core/workspace-app/tests/unit/user-guide.test.js +60 -0
- package/core/workspace-app/tests/unit/version-check.test.js +98 -0
- package/core/workspace-app/tests/unit/version-link.test.js +50 -0
- package/core/workspace-app/tests/unit/video-borrow.test.js +198 -0
- package/core/workspace-app/tests/unit/video-edit-ask.test.js +93 -0
- package/core/workspace-app/tests/unit/video-edit-short.test.js +42 -0
- package/core/workspace-app/tests/unit/video-edit.test.js +417 -0
- package/core/workspace-app/tests/unit/video-transcript.test.js +237 -0
- package/core/workspace-app/tests/unit/waiting.test.js +48 -0
- package/core/workspace-app/tests/unit/wordpress-odoo-builders.test.js +38 -0
- package/core/workspace-app/tests/unit/workspace-bin.test.js +48 -0
- package/core/workspace-app/tests/unit/workspace-card-tools.test.js +30 -0
- package/core/workspace-app/tests/unit/workspace-delete.test.js +77 -0
- package/core/workspace-app/tests/unit/workspace-types.test.js +68 -0
- package/core/workspace-app/tests/unit/worktree-clone.test.js +250 -0
- package/{workspace-types.js → core/workspace-app/workspace-types.js} +2 -2
- package/{workspaces.js → core/workspace-app/workspaces.js} +1 -5
- package/package.json +38 -36
- package/actions/graphs.js +0 -107
- package/actions/obsidian.js +0 -59
- package/graphs.js +0 -104
- package/obsidian.js +0 -405
- /package/{WORKSPACES.md → core/workspace-app/WORKSPACES.md} +0 -0
- /package/{actions → core/workspace-app/actions}/ai-items.js +0 -0
- /package/{actions → core/workspace-app/actions}/audio.js +0 -0
- /package/{actions → core/workspace-app/actions}/build-order.js +0 -0
- /package/{actions → core/workspace-app/actions}/checks.js +0 -0
- /package/{actions → core/workspace-app/actions}/claude-session.js +0 -0
- /package/{actions → core/workspace-app/actions}/commands-center.js +0 -0
- /package/{actions → core/workspace-app/actions}/composer.js +0 -0
- /package/{actions → core/workspace-app/actions}/ddev-addons.js +0 -0
- /package/{actions → core/workspace-app/actions}/ddev-mail.js +0 -0
- /package/{actions → core/workspace-app/actions}/folders.js +0 -0
- /package/{actions → core/workspace-app/actions}/images-svg.js +0 -0
- /package/{actions → core/workspace-app/actions}/images.js +0 -0
- /package/{actions → core/workspace-app/actions}/navigation.js +0 -0
- /package/{actions → core/workspace-app/actions}/node.js +0 -0
- /package/{actions → core/workspace-app/actions}/notes.js +0 -0
- /package/{actions → core/workspace-app/actions}/plugins.js +0 -0
- /package/{actions → core/workspace-app/actions}/project-make.js +0 -0
- /package/{actions → core/workspace-app/actions}/row-actions.js +0 -0
- /package/{actions → core/workspace-app/actions}/screens.js +0 -0
- /package/{actions → core/workspace-app/actions}/video-edit.js +0 -0
- /package/{ai-inventory.js → core/workspace-app/ai-inventory.js} +0 -0
- /package/{ai-items.js → core/workspace-app/ai-items.js} +0 -0
- /package/{assistant-cast.js → core/workspace-app/assistant-cast.js} +0 -0
- /package/{assistant-suggestions.js → core/workspace-app/assistant-suggestions.js} +0 -0
- /package/{audio-voice.js → core/workspace-app/audio-voice.js} +0 -0
- /package/{auth-google.js → core/workspace-app/auth-google.js} +0 -0
- /package/{build-ai.js → core/workspace-app/build-ai.js} +0 -0
- /package/{build-order-page.js → core/workspace-app/build-order-page.js} +0 -0
- /package/{build-order.js → core/workspace-app/build-order.js} +0 -0
- /package/{builder-args.js → core/workspace-app/builder-args.js} +0 -0
- /package/{changelog.js → core/workspace-app/changelog.js} +0 -0
- /package/{chat-threads.js → core/workspace-app/chat-threads.js} +0 -0
- /package/{checks.js → core/workspace-app/checks.js} +0 -0
- /package/{claude-args.js → core/workspace-app/claude-args.js} +0 -0
- /package/{claude-sessions.js → core/workspace-app/claude-sessions.js} +0 -0
- /package/{command-author.js → core/workspace-app/command-author.js} +0 -0
- /package/{command-block.js → core/workspace-app/command-block.js} +0 -0
- /package/{commands → core/workspace-app/commands}/defaults.yml +0 -0
- /package/{commands-page.js → core/workspace-app/commands-page.js} +0 -0
- /package/{commands.js → core/workspace-app/commands.js} +0 -0
- /package/{cucumber.js → core/workspace-app/cucumber.js} +0 -0
- /package/{ddev-addons-page.js → core/workspace-app/ddev-addons-page.js} +0 -0
- /package/{ddev-addons.js → core/workspace-app/ddev-addons.js} +0 -0
- /package/{ddev-custom-commands.js → core/workspace-app/ddev-custom-commands.js} +0 -0
- /package/{ddev-domains.js → core/workspace-app/ddev-domains.js} +0 -0
- /package/{ddev-import.js → core/workspace-app/ddev-import.js} +0 -0
- /package/{ddev-mail-page.js → core/workspace-app/ddev-mail-page.js} +0 -0
- /package/{ddev-mail.js → core/workspace-app/ddev-mail.js} +0 -0
- /package/{ddev-options.js → core/workspace-app/ddev-options.js} +0 -0
- /package/{ddev-snapshots.js → core/workspace-app/ddev-snapshots.js} +0 -0
- /package/{ddev.js → core/workspace-app/ddev.js} +0 -0
- /package/{docs → core/workspace-app/docs}/DEVELOPER-GUIDE.md +0 -0
- /package/{docs → core/workspace-app/docs}/README.md +0 -0
- /package/{docs → core/workspace-app/docs}/REFERENCE.md +0 -0
- /package/{docs → core/workspace-app/docs}/USER-GUIDE.md +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-board.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-coffee.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-colours.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-icons.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-moves.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-pick-cookieman.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-settings-voices.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-status.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/create-card/create-card.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/create-card/start-ai.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-address.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-worktree-off.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-worktree-on.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-ddev-menu.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-domains.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-home.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-ide-menu.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-remove-refusal.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-rows-worktree.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-screens.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-settings.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-workspace-page.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/home/card-settings.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/home/drag-reorder.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/home/edit-card.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/claude-code-image.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/edit-with-ai.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/gallery.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/generate-description.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/generate-plan.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/providers.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/svg-form.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/svg-result.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/upload.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/new-folder/2-form.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/new-folder/8-ddev-options.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/new-folder/files-folder.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/projects/ddev-custom-commands.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/projects/state-chip-stop.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/dashboard-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/dashboard-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/dev-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/dev-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/docs-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/docs-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/ai.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/code.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/docs.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/services.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/sites.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/test-report-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/test-report-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/test-scenarios.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/test-steps.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/videos-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/videos-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/screens-menu.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/screens-new.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/auth-google-lists.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-1-row.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-2-confirm.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-3-type-name.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-4-type-yes.png +0 -0
- /package/{event-log.js → core/workspace-app/event-log.js} +0 -0
- /package/{files-browser.js → core/workspace-app/files-browser.js} +0 -0
- /package/{folders.js → core/workspace-app/folders.js} +0 -0
- /package/{format.js → core/workspace-app/format.js} +0 -0
- /package/{github-auth.js → core/workspace-app/github-auth.js} +0 -0
- /package/{html.js → core/workspace-app/html.js} +0 -0
- /package/{icons.js → core/workspace-app/icons.js} +0 -0
- /package/{images-ai.js → core/workspace-app/images-ai.js} +0 -0
- /package/{images-create.js → core/workspace-app/images-create.js} +0 -0
- /package/{images-page.js → core/workspace-app/images-page.js} +0 -0
- /package/{images-records.js → core/workspace-app/images-records.js} +0 -0
- /package/{images-render.js → core/workspace-app/images-render.js} +0 -0
- /package/{images-svg-core.js → core/workspace-app/images-svg-core.js} +0 -0
- /package/{images-svg-sanitize.js → core/workspace-app/images-svg-sanitize.js} +0 -0
- /package/{images-svg.js → core/workspace-app/images-svg.js} +0 -0
- /package/{images.js → core/workspace-app/images.js} +0 -0
- /package/{jobs.js → core/workspace-app/jobs.js} +0 -0
- /package/{linger.js → core/workspace-app/linger.js} +0 -0
- /package/{lists.js → core/workspace-app/lists.js} +0 -0
- /package/{media-info.js → core/workspace-app/media-info.js} +0 -0
- /package/{navigation-page.js → core/workspace-app/navigation-page.js} +0 -0
- /package/{navigation.js → core/workspace-app/navigation.js} +0 -0
- /package/{notes.js → core/workspace-app/notes.js} +0 -0
- /package/{palette-index.js → core/workspace-app/palette-index.js} +0 -0
- /package/{playwright.config.js → core/workspace-app/playwright.config.js} +0 -0
- /package/{plugin-install.js → core/workspace-app/plugin-install.js} +0 -0
- /package/{plugin-manifest.js → core/workspace-app/plugin-manifest.js} +0 -0
- /package/{plugin-settings.js → core/workspace-app/plugin-settings.js} +0 -0
- /package/{plugins → core/workspace-app/plugins}/workspace-notes/index.js +0 -0
- /package/{project-make.js → core/workspace-app/project-make.js} +0 -0
- /package/{project-name.js → core/workspace-app/project-name.js} +0 -0
- /package/{public → core/workspace-app/public}/assistant-avatar-moves.js +0 -0
- /package/{public → core/workspace-app/public}/assistant-avatar-ui.js +0 -0
- /package/{public → core/workspace-app/public}/assistant-avatar.js +0 -0
- /package/{public → core/workspace-app/public}/avatar/druplicon.vrm +0 -0
- /package/{public → core/workspace-app/public}/css/base.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/ai-assistant.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/assistant-avatar.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/assistant-views.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/build-order.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/clone-as-a-git-worktree.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/command-palette.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/commands-center.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/confirm-dialog.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/create-card.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/ddev-menu.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/deep-chat.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/density.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/floating-assistant-workspace-pages.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/folders.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/full-height-left-assistant-sidebar-all-pages.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/full-height-right-actions-rail-pages-that-have-actions.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/grid-and-list.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/help-page.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/hero.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/images.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/layout-rhythm-and-spacing-polish.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/mic-on-any-field-that-wants-typing.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/modal-fit.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/page-width.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/plugins-page.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/project-cards.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/project-rows.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/reordering-the-workspace-cards.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/responsive-home-and-the-workspace-pages.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/running-commands-as-toasts.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/settings-editor-core-config-yml.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/short-results-as-a-toast-at-the-top.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/sound-player.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/suggest-agents-skills-commands.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/tab-modal.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/terminals.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/test-report-media-one-file-per-row-paged.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/top-toolbar-logo-breadcrumb.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/video-edit.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/web-ide-open-with.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/working-indicators.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/workspace-cards.css +0 -0
- /package/{public → core/workspace-app/public}/favicon.ico +0 -0
- /package/{public → core/workspace-app/public}/favicon.png +0 -0
- /package/{public → core/workspace-app/public}/htmx.min.js +0 -0
- /package/{public → core/workspace-app/public}/logo.png +0 -0
- /package/{public → core/workspace-app/public}/media-player.js +0 -0
- /package/{public → core/workspace-app/public}/mic.js +0 -0
- /package/{public → core/workspace-app/public}/narration.js +0 -0
- /package/{public → core/workspace-app/public}/palette.js +0 -0
- /package/{public → core/workspace-app/public}/sortable.js +0 -0
- /package/{public → core/workspace-app/public}/suggest.js +0 -0
- /package/{public → core/workspace-app/public}/terminal.js +0 -0
- /package/{public → core/workspace-app/public}/themes/default/theme.css +0 -0
- /package/{public → core/workspace-app/public}/themes/ember/theme.css +0 -0
- /package/{public → core/workspace-app/public}/themes/press/theme.css +0 -0
- /package/{public → core/workspace-app/public}/themes/slate/theme.css +0 -0
- /package/{public → core/workspace-app/public}/touch-icon.png +0 -0
- /package/{public → core/workspace-app/public}/ui.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/ace.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/ext-language_tools.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/ext-searchbox.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-css.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-html.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-javascript.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-markdown.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-sh.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-yaml.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/theme-textmate.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/theme-tomorrow_night.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/worker-yaml.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/deep-chat.LICENSE +0 -0
- /package/{public → core/workspace-app/public}/vendor/deep-chat.bundle.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-latin-400-italic.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-latin-400-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-400-italic.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-400-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-600-italic.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-600-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/jetbrains-mono-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/ubuntu-mono-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/ubuntu-mono-latin-wght-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/tabler-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/tabler-sprite.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/LICENSE +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/addons/loaders/GLTFLoader.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/addons/utils/BufferGeometryUtils.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/addons/utils/SkeletonUtils.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/three.core.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/three.module.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three-vrm/LICENSE +0 -0
- /package/{public → core/workspace-app/public}/vendor/three-vrm/three-vrm.module.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/uikit-icons.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/uikit.min.css +0 -0
- /package/{public → core/workspace-app/public}/vendor/uikit.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/bookmark-outlined.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/headset.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/menu.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/pause.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/play.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/share.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/sound-off.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/sound-on.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/stop.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/addon-fit.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/addon-unicode11.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/addon-web-links.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/xterm.css +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/xterm.js +0 -0
- /package/{rag.js → core/workspace-app/rag.js} +0 -0
- /package/{reader.js → core/workspace-app/reader.js} +0 -0
- /package/{repo-blobs.js → core/workspace-app/repo-blobs.js} +0 -0
- /package/{report-pdf.js → core/workspace-app/report-pdf.js} +0 -0
- /package/{screenrc → core/workspace-app/screenrc} +0 -0
- /package/{screens.js → core/workspace-app/screens.js} +0 -0
- /package/{scripts → core/workspace-app/scripts}/code-server-start.sh +0 -0
- /package/{scripts → core/workspace-app/scripts}/images-claude-finish.js +0 -0
- /package/{scripts → core/workspace-app/scripts}/screen-host.sh +0 -0
- /package/{scripts → core/workspace-app/scripts}/screen-runner.js +0 -0
- /package/{scripts → core/workspace-app/scripts}/screen-then.js +0 -0
- /package/{scripts → core/workspace-app/scripts}/update.sh +0 -0
- /package/{settings-file.js → core/workspace-app/settings-file.js} +0 -0
- /package/{speech.js → core/workspace-app/speech.js} +0 -0
- /package/{tab-modal.js → core/workspace-app/tab-modal.js} +0 -0
- /package/{test-reports.js → core/workspace-app/test-reports.js} +0 -0
- /package/{themes.js → core/workspace-app/themes.js} +0 -0
- /package/{transcripts.js → core/workspace-app/transcripts.js} +0 -0
- /package/{urls.js → core/workspace-app/urls.js} +0 -0
- /package/{validate.js → core/workspace-app/validate.js} +0 -0
- /package/{version-check.js → core/workspace-app/version-check.js} +0 -0
- /package/{video-edit.js → core/workspace-app/video-edit.js} +0 -0
- /package/{waiting.js → core/workspace-app/waiting.js} +0 -0
- /package/{workspace-card-tools.js → core/workspace-app/workspace-card-tools.js} +0 -0
- /package/{workspace-delete.js → core/workspace-app/workspace-delete.js} +0 -0
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Steps for the assistant's voice configuration.
|
|
3
|
+
*
|
|
4
|
+
* These read the LIVE properties off the deep-chat element rather than the page source, because the
|
|
5
|
+
* page source cannot tell you whether the component accepted anything. deep-chat is configured with
|
|
6
|
+
* JavaScript properties (the objects cannot survive an HTML attribute), and it silently ignores keys
|
|
7
|
+
* it does not recognise — so "the config is in ui.js" and "the component is using it" are different
|
|
8
|
+
* facts, and only the second one matters.
|
|
9
|
+
*
|
|
10
|
+
* Nothing here speaks or listens. An automated browser is not granted a microphone, and a scenario
|
|
11
|
+
* cannot talk. What CAN break without anyone noticing is the microphone being absent, or present
|
|
12
|
+
* with a configuration deep-chat quietly dropped, and that is what these assert.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const { Then } = require('@cucumber/cucumber');
|
|
18
|
+
const assert = require('assert');
|
|
19
|
+
|
|
20
|
+
/** The properties deep-chat is actually holding, read from inside the page. */
|
|
21
|
+
async function speechConfig(page) {
|
|
22
|
+
return page.evaluate(() => {
|
|
23
|
+
const el = document.querySelector('deep-chat');
|
|
24
|
+
if (!el) return null;
|
|
25
|
+
return {
|
|
26
|
+
speechToText: el.speechToText === undefined ? 'unset' : el.speechToText,
|
|
27
|
+
textToSpeech: el.textToSpeech === undefined ? 'unset' : el.textToSpeech,
|
|
28
|
+
placeholder: (el.textInput && el.textInput.placeholder && el.textInput.placeholder.text) || '',
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Then(/^the assistant should offer voice input$/, async function () {
|
|
34
|
+
const cfg = await speechConfig(this.page);
|
|
35
|
+
assert.ok(cfg, 'there is no deep-chat element on this page');
|
|
36
|
+
assert.notStrictEqual(cfg.speechToText, 'unset', 'deep-chat was never given a speechToText config');
|
|
37
|
+
assert.notStrictEqual(cfg.speechToText, false, 'voice input is switched off');
|
|
38
|
+
assert.ok(cfg.speechToText.webSpeech, 'no speech backend is configured, so the microphone does nothing');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
Then(/^the assistant should read its replies aloud$/, async function () {
|
|
42
|
+
const cfg = await speechConfig(this.page);
|
|
43
|
+
assert.ok(cfg, 'there is no deep-chat element on this page');
|
|
44
|
+
assert.notStrictEqual(cfg.textToSpeech, 'unset', 'deep-chat was never given a textToSpeech config');
|
|
45
|
+
assert.notStrictEqual(cfg.textToSpeech, false, 'voice output is switched off');
|
|
46
|
+
// Its presence IS the read-aloud behaviour; there is no separate switch to check.
|
|
47
|
+
assert.ok(Number.isFinite(cfg.textToSpeech.rate), 'no speech rate, so the config is not the resolved one');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* What the composer LOOKS like, from inside deep-chat's shadow root.
|
|
52
|
+
*
|
|
53
|
+
* Its input lives in that shadow root, and so does the microphone, so neither is reachable from the
|
|
54
|
+
* page's own DOM — and the placeholder is drawn as a pseudo-element, which has no node at all. The
|
|
55
|
+
* only honest way to ask "is anything drawn there" is the computed `content`, which is why this
|
|
56
|
+
* reads styles rather than text.
|
|
57
|
+
*/
|
|
58
|
+
async function composer(page) {
|
|
59
|
+
return page.evaluate(() => {
|
|
60
|
+
const el = document.querySelector('deep-chat');
|
|
61
|
+
const root = el && el.shadowRoot;
|
|
62
|
+
if (!root) return null;
|
|
63
|
+
const input = root.querySelector('#text-input');
|
|
64
|
+
const mic = root.querySelector('#microphone-button');
|
|
65
|
+
return {
|
|
66
|
+
drawn: input ? getComputedStyle(input, '::before').content : null,
|
|
67
|
+
name: input ? input.getAttribute('aria-label') : null,
|
|
68
|
+
mic: !!mic,
|
|
69
|
+
micName: mic ? (mic.getAttribute('aria-label') || '') : '',
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
Then(/^the assistant should show a named microphone button$/, async function () {
|
|
75
|
+
const c = await composer(this.page);
|
|
76
|
+
assert.ok(c, 'there is no deep-chat element on this page');
|
|
77
|
+
assert.ok(c.mic, 'there is no microphone in the composer, so nothing says voice is available');
|
|
78
|
+
// deep-chat's own buttons are role="button" with an SVG inside and no accessible name, so this is
|
|
79
|
+
// a name ui.js puts on. Without it a screen reader announces an unnamed button.
|
|
80
|
+
assert.ok(c.micName.trim(), 'the microphone has no accessible name');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
Then(/^the assistant composer should draw no placeholder$/, async function () {
|
|
84
|
+
const c = await composer(this.page);
|
|
85
|
+
assert.ok(c, 'there is no deep-chat element on this page');
|
|
86
|
+
// An empty `content` is the only thing that means nothing is drawn. "none" would mean the
|
|
87
|
+
// pseudo-element is absent, which is also fine; a string means deep-chat's "Ask me anything!" is
|
|
88
|
+
// back, which is what an empty placeholder.text silently restores.
|
|
89
|
+
assert.ok(c.drawn === '""' || c.drawn === 'none' || c.drawn === '',
|
|
90
|
+
`the composer is drawing a placeholder: ${c.drawn}`);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
Then(/^the assistant composer should have an accessible name$/, async function () {
|
|
94
|
+
const c = await composer(this.page);
|
|
95
|
+
assert.ok(c, 'there is no deep-chat element on this page');
|
|
96
|
+
assert.ok(c.name && c.name.trim(),
|
|
97
|
+
'the composer has no accessible name, so a screen reader announces an unlabelled text box');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
Then(/^the assistant speech language should be pinned$/, async function () {
|
|
101
|
+
const cfg = await speechConfig(this.page);
|
|
102
|
+
// A pinned language is the shipped default (en-US), because a recogniser left on the browser's
|
|
103
|
+
// language does not fail on the wrong one — it returns confident nonsense. `true` here would mean
|
|
104
|
+
// nothing is pinned, which is a valid choice but not what ships.
|
|
105
|
+
const ws = cfg.speechToText.webSpeech;
|
|
106
|
+
assert.ok(ws && typeof ws === 'object' && ws.language,
|
|
107
|
+
`no language is pinned (webSpeech is ${JSON.stringify(ws)}); the shipped default is en-US`);
|
|
108
|
+
assert.match(ws.language, /^[a-z]{2}-[A-Z]{2}$/, `"${ws.language}" is not a BCP-47 tag`);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
Then(/^the assistant should have no voice commands$/, async function () {
|
|
112
|
+
const cfg = await speechConfig(this.page);
|
|
113
|
+
// Absent, not empty. An empty phrase is not a disabled command — it is one that fires on anything.
|
|
114
|
+
assert.ok(!('commands' in cfg.speechToText),
|
|
115
|
+
`voice commands are armed with nothing configured: ${JSON.stringify(cfg.speechToText.commands)}`);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
Then(/^the assistant speech colours should be design tokens$/, async function () {
|
|
119
|
+
const cfg = await speechConfig(this.page);
|
|
120
|
+
const { textColor } = cfg.speechToText;
|
|
121
|
+
assert.ok(textColor, 'interim and final speech text have no colours set');
|
|
122
|
+
for (const key of ['interim', 'final']) {
|
|
123
|
+
assert.match(textColor[key], /^var\(--/,
|
|
124
|
+
`speech ${key} colour is "${textColor[key]}", a literal that cannot follow the theme`);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
Then(/^the voice list should report what this browser has$/, async function () {
|
|
129
|
+
// The reading voice is a dropdown the server cannot fill in: which voices exist belongs to the
|
|
130
|
+
// browser and the OS. Either it gained real options, or it says there are none — an empty select
|
|
131
|
+
// with no explanation is the failure this guards, because that reads as "still loading" forever.
|
|
132
|
+
const state = await this.page.evaluate(async () => {
|
|
133
|
+
const select = document.querySelector('select[data-voice-name]');
|
|
134
|
+
const note = document.querySelector('[data-voice-list]');
|
|
135
|
+
if (!select) return { missing: true };
|
|
136
|
+
for (let i = 0; i < 20 && select.dataset.done !== '1'; i += 1) {
|
|
137
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
resolved: select.dataset.done === '1',
|
|
141
|
+
options: select.options.length,
|
|
142
|
+
hasDefault: [...select.options].some((o) => o.value === 'default'),
|
|
143
|
+
warns: !!(note && note.querySelector('.uk-text-danger')),
|
|
144
|
+
note: (note ? note.textContent : '').trim().slice(0, 80),
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
assert.ok(!state.missing, 'the reading voice is not a dropdown');
|
|
148
|
+
assert.ok(state.resolved, 'the voice list never resolved — it waits for voiceschanged with a timeout');
|
|
149
|
+
assert.ok(state.hasDefault, 'there is no "default" option, so the browser default is unreachable');
|
|
150
|
+
assert.ok(state.options > 1 || state.warns,
|
|
151
|
+
`only the default option and no explanation of why: "${state.note}"`);
|
|
152
|
+
});
|