gsd-pi 2.20.0 → 2.22.0
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/README.md +12 -0
- package/dist/cli.js +21 -18
- package/dist/help-text.d.ts +2 -0
- package/dist/help-text.js +47 -0
- package/dist/loader.js +2 -16
- package/dist/mcp-server.d.ts +18 -0
- package/dist/mcp-server.js +53 -0
- package/dist/onboarding.d.ts +0 -6
- package/dist/onboarding.js +0 -28
- package/dist/resources/agents/javascript-pro.md +280 -0
- package/dist/resources/agents/typescript-pro.md +255 -0
- package/dist/resources/extensions/bg-shell/index.ts +14 -2
- package/dist/resources/extensions/bg-shell/utilities.ts +14 -0
- package/dist/resources/extensions/browser-tools/{core.js → core.ts} +329 -190
- package/dist/resources/extensions/gsd/auto-dashboard.ts +2 -1
- package/dist/resources/extensions/gsd/auto-prompts.ts +42 -1
- package/dist/resources/extensions/gsd/auto-worktree.ts +35 -2
- package/dist/resources/extensions/gsd/auto.ts +116 -10
- package/dist/resources/extensions/gsd/claude-import.ts +656 -0
- package/dist/resources/extensions/gsd/collision-diagnostics.ts +332 -0
- package/dist/resources/extensions/gsd/commands.ts +60 -7
- package/dist/resources/extensions/gsd/diff-context.ts +220 -0
- package/dist/resources/extensions/gsd/docs/claude-marketplace-import.md +214 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -1
- package/dist/resources/extensions/gsd/doctor.ts +12 -4
- package/dist/resources/extensions/gsd/file-watcher.ts +97 -0
- package/dist/resources/extensions/gsd/files.ts +1 -1
- package/dist/resources/extensions/gsd/forensics.ts +596 -0
- package/dist/resources/extensions/gsd/git-service.ts +2 -1
- package/dist/resources/extensions/gsd/github-client.ts +235 -0
- package/dist/resources/extensions/gsd/gitignore.ts +1 -0
- package/dist/resources/extensions/gsd/marketplace-discovery.ts +507 -0
- package/dist/resources/extensions/gsd/mcp-server.ts +87 -0
- package/dist/resources/extensions/gsd/namespaced-registry.ts +467 -0
- package/dist/resources/extensions/gsd/namespaced-resolver.ts +307 -0
- package/dist/resources/extensions/gsd/plugin-importer.ts +410 -0
- package/dist/resources/extensions/gsd/preferences.ts +14 -3
- package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/forensics.md +71 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/system.md +12 -3
- package/dist/resources/extensions/gsd/roadmap-slices.ts +1 -1
- package/dist/resources/extensions/gsd/session-forensics.ts +5 -5
- package/dist/resources/extensions/gsd/tests/claude-import-tui.test.ts +351 -0
- package/dist/resources/extensions/gsd/tests/collision-diagnostics.test.ts +705 -0
- package/dist/resources/extensions/gsd/tests/context-compression.test.ts +13 -0
- package/dist/resources/extensions/gsd/tests/diff-context.test.ts +136 -0
- package/dist/resources/extensions/gsd/tests/doctor-git.test.ts +118 -0
- package/dist/resources/extensions/gsd/tests/marketplace-discovery.test.ts +202 -0
- package/dist/resources/extensions/gsd/tests/marketplace-test-fixtures.ts +91 -0
- package/dist/resources/extensions/gsd/tests/namespaced-registry.test.ts +1027 -0
- package/dist/resources/extensions/gsd/tests/namespaced-resolver.test.ts +671 -0
- package/dist/resources/extensions/gsd/tests/none-mode-gates.test.ts +105 -0
- package/dist/resources/extensions/gsd/tests/plugin-importer-live.test.ts +481 -0
- package/dist/resources/extensions/gsd/tests/plugin-importer.test.ts +1383 -0
- package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +21 -2
- package/dist/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +8 -1
- package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +11 -0
- package/dist/resources/extensions/gsd/tests/worktree-bugfix.test.ts +120 -0
- package/dist/resources/extensions/gsd/token-counter.ts +45 -0
- package/dist/resources/extensions/gsd/visualizer-data.ts +2 -2
- package/dist/resources/extensions/gsd/worktree-manager.ts +29 -1
- package/dist/resources/extensions/gsd/worktree.ts +3 -0
- package/dist/resources/extensions/mcporter/index.ts +90 -7
- package/dist/resources/extensions/search-the-web/native-search.ts +2 -0
- package/dist/resources/extensions/search-the-web/tool-fetch-page.ts +9 -1
- package/dist/resources/extensions/search-the-web/url-utils.ts +35 -1
- package/dist/resources/extensions/shared/terminal.ts +1 -1
- package/dist/resources/extensions/universal-config/discovery.ts +4 -0
- package/dist/resources/extensions/universal-config/format.ts +35 -4
- package/dist/resources/extensions/universal-config/index.ts +5 -3
- package/dist/resources/extensions/universal-config/scanners.ts +65 -2
- package/dist/resources/extensions/universal-config/tests/discovery.test.ts +9 -1
- package/dist/resources/extensions/universal-config/tests/format.test.ts +22 -6
- package/dist/resources/extensions/universal-config/tests/scanners.test.ts +18 -0
- package/dist/resources/extensions/universal-config/types.ts +20 -1
- package/dist/resources/skills/lint/SKILL.md +141 -0
- package/dist/resources/skills/review/SKILL.md +214 -0
- package/dist/resources/skills/test/SKILL.md +201 -0
- package/dist/tool-bootstrap.js +2 -1
- package/dist/wizard.js +2 -0
- package/package.json +12 -7
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js +12 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js +12 -1
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/LICENSE +201 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/README.md +9 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-cjs/index.js +762 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/build-abort-error.js +19 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/constants.js +1 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/get-transformed-headers.js +9 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/index.js +3 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http-handler.js +230 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-manager.js +87 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-pool.js +32 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-handler.js +169 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/readable.mock.js +21 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/server.mock.js +88 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-connection-timeout.js +36 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-request-timeout.js +21 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-socket-keep-alive.js +22 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-socket-timeout.js +23 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/collector.js +8 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/index.js +41 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/readable.mock.js +21 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/timing.js +4 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/write-request-body.js +63 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/build-abort-error.d.ts +10 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/constants.d.ts +5 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/get-transformed-headers.d.ts +4 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/index.d.ts +3 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http-handler.d.ts +46 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-connection-manager.d.ts +24 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-connection-pool.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-handler.d.ts +63 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/readable.mock.d.ts +13 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/server.mock.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-connection-timeout.d.ts +2 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-request-timeout.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-socket-keep-alive.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-socket-timeout.d.ts +2 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/collector.d.ts +5 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/index.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/readable.mock.d.ts +13 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/timing.d.ts +8 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/build-abort-error.d.ts +10 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/constants.d.ts +5 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/get-transformed-headers.d.ts +4 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/index.d.ts +3 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http-handler.d.ts +46 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-connection-manager.d.ts +24 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-connection-pool.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-handler.d.ts +63 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/readable.mock.d.ts +13 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/server.mock.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-connection-timeout.d.ts +2 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-request-timeout.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-socket-keep-alive.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-socket-timeout.d.ts +2 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/collector.d.ts +5 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/index.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/readable.mock.d.ts +13 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/timing.d.ts +8 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/write-request-body.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/write-request-body.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/package.json +68 -0
- package/packages/pi-ai/package.json +3 -0
- package/packages/pi-ai/pnpm-lock.yaml +2022 -0
- package/packages/pi-ai/src/providers/azure-openai-responses.ts +12 -1
- package/packages/pi-ai/src/providers/openai-responses.ts +12 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +12 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +113 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/project-trust.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/project-trust.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/project-trust.js +42 -0
- package/packages/pi-coding-agent/dist/core/extensions/project-trust.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.js +18 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +114 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +8 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +23 -9
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +67 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/pnpm-lock.yaml +454 -0
- package/packages/pi-coding-agent/scripts/copy-assets.cjs +24 -0
- package/packages/pi-coding-agent/src/core/extensions/index.ts +3 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +141 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +14 -1
- package/packages/pi-coding-agent/src/core/extensions/project-trust.ts +51 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +132 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.ts +20 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +7 -2
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +98 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +24 -9
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +2 -2
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +3 -1
- package/packages/pi-tui/src/tui.ts +2 -2
- package/src/resources/agents/javascript-pro.md +280 -0
- package/src/resources/agents/typescript-pro.md +255 -0
- package/src/resources/extensions/bg-shell/index.ts +14 -2
- package/src/resources/extensions/bg-shell/utilities.ts +14 -0
- package/src/resources/extensions/browser-tools/{core.js → core.ts} +329 -190
- package/src/resources/extensions/gsd/auto-dashboard.ts +2 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +42 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +35 -2
- package/src/resources/extensions/gsd/auto.ts +116 -10
- package/src/resources/extensions/gsd/claude-import.ts +656 -0
- package/src/resources/extensions/gsd/collision-diagnostics.ts +332 -0
- package/src/resources/extensions/gsd/commands.ts +60 -7
- package/src/resources/extensions/gsd/diff-context.ts +220 -0
- package/src/resources/extensions/gsd/docs/claude-marketplace-import.md +214 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -1
- package/src/resources/extensions/gsd/doctor.ts +12 -4
- package/src/resources/extensions/gsd/file-watcher.ts +97 -0
- package/src/resources/extensions/gsd/files.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +596 -0
- package/src/resources/extensions/gsd/git-service.ts +2 -1
- package/src/resources/extensions/gsd/github-client.ts +235 -0
- package/src/resources/extensions/gsd/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/marketplace-discovery.ts +507 -0
- package/src/resources/extensions/gsd/mcp-server.ts +87 -0
- package/src/resources/extensions/gsd/namespaced-registry.ts +467 -0
- package/src/resources/extensions/gsd/namespaced-resolver.ts +307 -0
- package/src/resources/extensions/gsd/plugin-importer.ts +410 -0
- package/src/resources/extensions/gsd/preferences.ts +14 -3
- package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/forensics.md +71 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/system.md +12 -3
- package/src/resources/extensions/gsd/roadmap-slices.ts +1 -1
- package/src/resources/extensions/gsd/session-forensics.ts +5 -5
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/collision-diagnostics.test.ts +705 -0
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +13 -0
- package/src/resources/extensions/gsd/tests/diff-context.test.ts +136 -0
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/marketplace-discovery.test.ts +202 -0
- package/src/resources/extensions/gsd/tests/marketplace-test-fixtures.ts +91 -0
- package/src/resources/extensions/gsd/tests/namespaced-registry.test.ts +1027 -0
- package/src/resources/extensions/gsd/tests/namespaced-resolver.test.ts +671 -0
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/plugin-importer-live.test.ts +481 -0
- package/src/resources/extensions/gsd/tests/plugin-importer.test.ts +1383 -0
- package/src/resources/extensions/gsd/tests/preferences-git.test.ts +21 -2
- package/src/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +120 -0
- package/src/resources/extensions/gsd/token-counter.ts +45 -0
- package/src/resources/extensions/gsd/visualizer-data.ts +2 -2
- package/src/resources/extensions/gsd/worktree-manager.ts +29 -1
- package/src/resources/extensions/gsd/worktree.ts +3 -0
- package/src/resources/extensions/mcporter/index.ts +90 -7
- package/src/resources/extensions/search-the-web/native-search.ts +2 -0
- package/src/resources/extensions/search-the-web/tool-fetch-page.ts +9 -1
- package/src/resources/extensions/search-the-web/url-utils.ts +35 -1
- package/src/resources/extensions/shared/terminal.ts +1 -1
- package/src/resources/extensions/universal-config/discovery.ts +4 -0
- package/src/resources/extensions/universal-config/format.ts +35 -4
- package/src/resources/extensions/universal-config/index.ts +5 -3
- package/src/resources/extensions/universal-config/scanners.ts +65 -2
- package/src/resources/extensions/universal-config/tests/discovery.test.ts +9 -1
- package/src/resources/extensions/universal-config/tests/format.test.ts +22 -6
- package/src/resources/extensions/universal-config/tests/scanners.test.ts +18 -0
- package/src/resources/extensions/universal-config/types.ts +20 -1
- package/src/resources/skills/lint/SKILL.md +141 -0
- package/src/resources/skills/review/SKILL.md +214 -0
- package/src/resources/skills/test/SKILL.md +201 -0
- package/dist/resources/extensions/browser-tools/core.d.ts +0 -205
- package/src/resources/extensions/browser-tools/core.d.ts +0 -205
|
@@ -525,6 +525,17 @@ export function resolveSkillStalenessDays(): number {
|
|
|
525
525
|
return prefs?.preferences.skill_staleness_days ?? 60;
|
|
526
526
|
}
|
|
527
527
|
|
|
528
|
+
/**
|
|
529
|
+
* Resolve the effective git isolation mode from preferences.
|
|
530
|
+
* Returns "worktree" (default), "branch", or "none".
|
|
531
|
+
*/
|
|
532
|
+
export function getIsolationMode(): "none" | "worktree" | "branch" {
|
|
533
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences?.git;
|
|
534
|
+
if (prefs?.isolation === "none") return "none";
|
|
535
|
+
if (prefs?.isolation === "branch") return "branch";
|
|
536
|
+
return "worktree"; // default
|
|
537
|
+
}
|
|
538
|
+
|
|
528
539
|
/**
|
|
529
540
|
* Resolve which model ID to use for a given auto-mode unit type.
|
|
530
541
|
* Returns undefined if no model preference is set for this unit type.
|
|
@@ -1197,11 +1208,11 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
1197
1208
|
}
|
|
1198
1209
|
}
|
|
1199
1210
|
if (g.isolation !== undefined) {
|
|
1200
|
-
const validIsolation = new Set(["worktree", "branch"]);
|
|
1211
|
+
const validIsolation = new Set(["worktree", "branch", "none"]);
|
|
1201
1212
|
if (typeof g.isolation === "string" && validIsolation.has(g.isolation)) {
|
|
1202
|
-
git.isolation = g.isolation as "worktree" | "branch";
|
|
1213
|
+
git.isolation = g.isolation as "worktree" | "branch" | "none";
|
|
1203
1214
|
} else {
|
|
1204
|
-
errors.push("git.isolation must be one of: worktree, branch");
|
|
1215
|
+
errors.push("git.isolation must be one of: worktree, branch, none");
|
|
1205
1216
|
}
|
|
1206
1217
|
}
|
|
1207
1218
|
if (g.commit_docs !== undefined) {
|
|
@@ -26,7 +26,7 @@ A researcher explored the codebase and a planner decomposed the work — you are
|
|
|
26
26
|
|
|
27
27
|
Then:
|
|
28
28
|
0. Narrate step transitions, key implementation decisions, and verification outcomes as you work. Keep it terse — one line between tool-call clusters, not between every call.
|
|
29
|
-
1.
|
|
29
|
+
1. **Load relevant skills before writing code.** Check the `GSD Skill Preferences` block in system context and the `<available_skills>` catalog in your system prompt. For each skill that matches this task's technology stack (e.g., React, Next.js, accessibility, component design), `read` its SKILL.md file now. Skills contain implementation rules and patterns that should guide your code. If no skills match this task, skip this step.
|
|
30
30
|
2. Execute the steps in the inlined task plan
|
|
31
31
|
3. Build the real thing. If the task plan says "create login endpoint", build an endpoint that actually authenticates against a real store, not one that returns a hardcoded success response. If the task plan says "create dashboard page", build a page that renders real data from the API, not a component with hardcoded props. Stubs and mocks are for tests, not for the shipped feature.
|
|
32
32
|
4. Write or update tests as part of execution — tests are verification, not an afterthought. If the slice plan defines test files in its Verification section and this is the first task, create them (they should initially fail).
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
You are investigating a GSD auto-mode failure. The user has described their problem and a structured forensic report has been gathered automatically.
|
|
2
|
+
|
|
3
|
+
## User's Problem
|
|
4
|
+
|
|
5
|
+
{{problemDescription}}
|
|
6
|
+
|
|
7
|
+
## Forensic Report
|
|
8
|
+
|
|
9
|
+
{{forensicData}}
|
|
10
|
+
|
|
11
|
+
## GSD Source Location
|
|
12
|
+
|
|
13
|
+
GSD extension source code is at: {{gsdSourceDir}}
|
|
14
|
+
Key files for understanding failures:
|
|
15
|
+
- auto.ts — unit dispatch loop, stuck detection, timeout recovery
|
|
16
|
+
- session-forensics.ts — trace extraction from activity logs
|
|
17
|
+
- auto-recovery.ts — artifact verification, skip logic
|
|
18
|
+
- crash-recovery.ts — crash lock lifecycle
|
|
19
|
+
- doctor.ts — state integrity checks
|
|
20
|
+
|
|
21
|
+
You may read these files to identify the specific code path that caused the failure.
|
|
22
|
+
|
|
23
|
+
## Your Task
|
|
24
|
+
|
|
25
|
+
1. **Analyze** the forensic report. Identify the root cause of the user's problem.
|
|
26
|
+
|
|
27
|
+
2. **Clarify** if needed. Use ask_user_questions (max 2 questions) to narrow down ambiguity. Only ask if the report is genuinely insufficient — do not ask questions you can answer from the data.
|
|
28
|
+
|
|
29
|
+
3. **Explain** your findings clearly:
|
|
30
|
+
- What happened (the failure sequence)
|
|
31
|
+
- Why it happened (root cause in GSD's logic)
|
|
32
|
+
- What the user can do to recover (immediate fix)
|
|
33
|
+
|
|
34
|
+
4. **Offer GitHub issue creation.** Ask the user:
|
|
35
|
+
"Would you like me to create a GitHub issue for this on gsd-build/gsd-2?"
|
|
36
|
+
|
|
37
|
+
If yes, create the issue using bash with `gh issue create`:
|
|
38
|
+
- Repository: gsd-build/gsd-2
|
|
39
|
+
- Labels: bug, auto-generated
|
|
40
|
+
- Title: concise description of the failure
|
|
41
|
+
- Body format:
|
|
42
|
+
```
|
|
43
|
+
## Problem
|
|
44
|
+
[1-2 sentence summary]
|
|
45
|
+
|
|
46
|
+
## Environment
|
|
47
|
+
- GSD version: [from report]
|
|
48
|
+
- Model: [from report]
|
|
49
|
+
- Unit: [type/id that failed]
|
|
50
|
+
|
|
51
|
+
## Reproduction Context
|
|
52
|
+
[What was happening when it failed — phase, milestone, slice]
|
|
53
|
+
|
|
54
|
+
## Forensic Findings
|
|
55
|
+
[Key anomalies detected, error traces, relevant tool call sequences]
|
|
56
|
+
|
|
57
|
+
## Suggested Fix Area
|
|
58
|
+
[File:line references in GSD source if identified]
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
*Auto-generated by `/gsd forensics`*
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**CRITICAL REDACTION RULES** before creating the issue:
|
|
65
|
+
- Replace all absolute paths with relative paths
|
|
66
|
+
- Remove any API keys, tokens, or credentials
|
|
67
|
+
- Remove any environment variable values
|
|
68
|
+
- Do not include file content (code written by the user)
|
|
69
|
+
- Only include GSD structural information (tool names, file names, error messages)
|
|
70
|
+
|
|
71
|
+
5. **Report saved.** Remind the user that the full forensic report was saved locally (the path will be in the notification).
|
|
@@ -33,7 +33,7 @@ Then:
|
|
|
33
33
|
1. Read the templates:
|
|
34
34
|
- `~/.gsd/agent/extensions/gsd/templates/plan.md`
|
|
35
35
|
- `~/.gsd/agent/extensions/gsd/templates/task-plan.md`
|
|
36
|
-
2.
|
|
36
|
+
2. **Load relevant skills.** Check the `GSD Skill Preferences` block in system context and the `<available_skills>` catalog in your system prompt. `read` any skill files relevant to this slice's technology stack before decomposing. When writing task plans, note which installed skills are relevant in the task description so executors know which to load.
|
|
37
37
|
3. Define slice-level verification — the objective stopping condition for this slice:
|
|
38
38
|
- For non-trivial slices: plan actual test files with real assertions. Name the files.
|
|
39
39
|
- For simple slices: executable commands or script assertions are fine.
|
|
@@ -42,7 +42,7 @@ An honest "this is straightforward, here's the pattern to follow" is more valuab
|
|
|
42
42
|
|
|
43
43
|
Research what this slice needs. Narrate key findings and surprises as you go — what exists, what's missing, what constrains the approach.
|
|
44
44
|
0. If `REQUIREMENTS.md` was preloaded above, identify which Active requirements this slice owns or supports. Research should target these requirements — surfacing risks, unknowns, and implementation constraints that could affect whether the slice actually delivers them.
|
|
45
|
-
1.
|
|
45
|
+
1. **Load relevant skills.** Check the `GSD Skill Preferences` block in system context and the `<available_skills>` catalog in your system prompt. `read` any skill files relevant to this slice's technology stack before exploring code. Reference specific rules from loaded skills in your findings where they inform the implementation approach.
|
|
46
46
|
2. **Skill Discovery ({{skillDiscoveryMode}}):**{{skillDiscoveryInstructions}}
|
|
47
47
|
3. Explore relevant code for this slice's scope. For targeted exploration, use `rg`, `find`, and reads. For broad or unfamiliar subsystems, use `scout` to map the relevant area first.
|
|
48
48
|
4. Use `resolve_library` / `get_library_docs` for unfamiliar libraries — skip this for libraries already used in the codebase
|
|
@@ -90,11 +90,17 @@ Titles live inside file content (headings, frontmatter), not in file or director
|
|
|
90
90
|
T01-SUMMARY.md
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
###
|
|
93
|
+
### Isolation Model
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
Auto-mode supports three isolation modes (configured in `.gsd/preferences.md` under `taskIsolation.mode`):
|
|
96
96
|
|
|
97
|
-
**
|
|
97
|
+
- **worktree** (default): Work happens in `.gsd/worktrees/<MID>/`, a full git worktree on the `milestone/<MID>` branch. Each worktree has its own working copy and `.gsd/` directory. Squash-merged back to the integration branch on milestone completion.
|
|
98
|
+
- **branch**: Work happens in the project root on a `milestone/<MID>` branch. No worktree directory — files are checked out in-place.
|
|
99
|
+
- **none**: Work happens directly on the current branch. No worktree, no milestone branch. Commits land in-place.
|
|
100
|
+
|
|
101
|
+
In all modes, slices commit sequentially on the active branch; there are no per-slice branches.
|
|
102
|
+
|
|
103
|
+
**If you are executing in auto-mode, your working directory is shown in the Working Directory section of your prompt.** Use relative paths. Do not navigate to any other copy of the project.
|
|
98
104
|
|
|
99
105
|
### Conventions
|
|
100
106
|
|
|
@@ -152,6 +158,8 @@ Templates showing the expected format for each artifact type are in:
|
|
|
152
158
|
|
|
153
159
|
**One-shot commands:** Use `async_bash` for builds, tests, and installs. The result is pushed to you when the command exits — no polling needed. Use `await_job` to block on a specific job.
|
|
154
160
|
|
|
161
|
+
**Stale job hygiene:** After editing source files to address a failure, `cancel_job` every in-flight `async_bash` job before re-running. If the inputs changed, in-flight outputs are untrusted.
|
|
162
|
+
|
|
155
163
|
**Secrets:** Use `secure_env_collect`. Never ask the user to edit `.env` files or paste secrets.
|
|
156
164
|
|
|
157
165
|
**Browser verification:** Verify frontend work against a running app. Discovery: `browser_find`/`browser_snapshot_refs`. Action: refs/selectors → `browser_batch` for obvious sequences. Verification: `browser_assert` for explicit pass/fail. Diagnostics: `browser_diff` for ambiguous outcomes → console/network logs when assertions fail → full page inspection as last resort. Debug in order: failing assertion → diff → diagnostics → element state → broader inspection. Retry only with a new hypothesis.
|
|
@@ -165,6 +173,7 @@ Templates showing the expected format for each artifact type are in:
|
|
|
165
173
|
- Never read files one-by-one to understand a subsystem — use `rg` or `scout` first.
|
|
166
174
|
- Never guess at library APIs from training data — use `get_library_docs`.
|
|
167
175
|
- Never ask the user to run a command, set a variable, or check something you can check yourself.
|
|
176
|
+
- Never await stale async jobs after editing source — `cancel_job` them first, then re-run.
|
|
168
177
|
|
|
169
178
|
### Ask vs infer
|
|
170
179
|
|
|
@@ -19,7 +19,7 @@ export function parseRoadmapSlices(content: string): RoadmapSliceEntry[] {
|
|
|
19
19
|
let currentSlice: RoadmapSliceEntry | null = null;
|
|
20
20
|
|
|
21
21
|
for (const line of checkboxItems) {
|
|
22
|
-
const cbMatch = line.match(/^\s*-\s+\[([ xX])\]\s+\*\*(\w+):\s+(.+?)\*\*\s*(.*)/);
|
|
22
|
+
const cbMatch = line.match(/^\s*-\s+\[([ xX])\]\s+\*\*([\w.]+):\s+(.+?)\*\*\s*(.*)/);
|
|
23
23
|
if (cbMatch) {
|
|
24
24
|
if (currentSlice) slices.push(currentSlice);
|
|
25
25
|
|
|
@@ -313,10 +313,10 @@ function formatRecoveryPrompt(
|
|
|
313
313
|
const sections: string[] = [];
|
|
314
314
|
|
|
315
315
|
sections.push(
|
|
316
|
-
"##
|
|
316
|
+
"## Recovery Briefing",
|
|
317
317
|
"",
|
|
318
|
-
`You are resuming \`${unitType}\` for \`${unitId}\` after
|
|
319
|
-
`The previous session completed **${trace.toolCallCount} tool calls** before
|
|
318
|
+
`You are resuming \`${unitType}\` for \`${unitId}\` after an interruption.`,
|
|
319
|
+
`The previous session completed **${trace.toolCallCount} tool calls** before stopping.`,
|
|
320
320
|
"Use this briefing to pick up exactly where it left off. Do NOT redo completed work.",
|
|
321
321
|
);
|
|
322
322
|
|
|
@@ -352,7 +352,7 @@ function formatRecoveryPrompt(
|
|
|
352
352
|
// Errors
|
|
353
353
|
if (trace.errors.length > 0) {
|
|
354
354
|
sections.push(
|
|
355
|
-
"", "### Errors Before
|
|
355
|
+
"", "### Errors Before Interruption",
|
|
356
356
|
...trace.errors.slice(-3).map(e => `- ${truncate(e, 200)}`),
|
|
357
357
|
);
|
|
358
358
|
}
|
|
@@ -368,7 +368,7 @@ function formatRecoveryPrompt(
|
|
|
368
368
|
// Last reasoning
|
|
369
369
|
if (trace.lastReasoning) {
|
|
370
370
|
sections.push(
|
|
371
|
-
"", "### Last Agent Reasoning Before
|
|
371
|
+
"", "### Last Agent Reasoning Before Interruption",
|
|
372
372
|
`> ${trace.lastReasoning.replace(/\n/g, "\n> ")}`,
|
|
373
373
|
);
|
|
374
374
|
}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUI Command Flow Tests for import-claude
|
|
3
|
+
*
|
|
4
|
+
* Tests R015: validates the TUI command flow for /gsd prefs import-claude.
|
|
5
|
+
* These tests currently use mock UI, and marketplace availability is still
|
|
6
|
+
* derived from real/local marketplace roots. Follow-up work should route these
|
|
7
|
+
* through portable marketplace fixtures that mirror Claude Code's
|
|
8
|
+
* `/plugin marketplace add ...` source model.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
import { describe, it, before, after, mock } from 'node:test';
|
|
13
|
+
import assert from 'node:assert';
|
|
14
|
+
import { existsSync, mkdtempSync, rmSync, writeFileSync, readFileSync, mkdirSync } from 'node:fs';
|
|
15
|
+
import { tmpdir } from 'node:os';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
import type { ExtensionCommandContext } from '@gsd/pi-coding-agent';
|
|
18
|
+
import { runClaudeImportFlow, getClaudeSearchRoots, discoverClaudeSkills, discoverClaudePlugins } from '../claude-import.js';
|
|
19
|
+
import { getMarketplaceFixtures } from './marketplace-test-fixtures.js';
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Test Configuration
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
const fixtureSetup = getMarketplaceFixtures(import.meta.dirname);
|
|
26
|
+
const fixtures = fixtureSetup.fixtures;
|
|
27
|
+
const CLAUDE_SKILLS_PATH = fixtures?.claudeSkillsPath;
|
|
28
|
+
const CLAUDE_PLUGINS_OFFICIAL_PATH = fixtures?.claudePluginsOfficialPath;
|
|
29
|
+
|
|
30
|
+
function marketplacesAvailable(): boolean {
|
|
31
|
+
return Boolean(fixtures);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// Mock UI Context
|
|
36
|
+
// ============================================================================
|
|
37
|
+
|
|
38
|
+
interface MockUISelectCall {
|
|
39
|
+
prompt: string;
|
|
40
|
+
options: string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function createMockContext(selections: string[]): {
|
|
44
|
+
ctx: ExtensionCommandContext;
|
|
45
|
+
selectCalls: MockUISelectCall[];
|
|
46
|
+
} {
|
|
47
|
+
const selectCalls: MockUISelectCall[] = [];
|
|
48
|
+
|
|
49
|
+
const selectMock = mock.fn(async (prompt: string, options: string[]) => {
|
|
50
|
+
selectCalls.push({ prompt, options });
|
|
51
|
+
const next = selections.shift();
|
|
52
|
+
if (next && options.includes(next)) {
|
|
53
|
+
return next;
|
|
54
|
+
}
|
|
55
|
+
// Default: cancel or first option
|
|
56
|
+
return options.find(o => o.toLowerCase().includes('cancel')) || options[0];
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const notifyMock = mock.fn();
|
|
60
|
+
|
|
61
|
+
// Create a mock that satisfies ExtensionCommandContext
|
|
62
|
+
// Using type assertion since we only use select, notify, waitForIdle, reload in the tests
|
|
63
|
+
const ctx = {
|
|
64
|
+
ui: {
|
|
65
|
+
select: selectMock,
|
|
66
|
+
notify: notifyMock,
|
|
67
|
+
confirm: async () => false,
|
|
68
|
+
input: async () => undefined,
|
|
69
|
+
onTerminalInput: () => () => {},
|
|
70
|
+
setStatus: () => {},
|
|
71
|
+
setWorkingMessage: () => {},
|
|
72
|
+
setWidget: () => {},
|
|
73
|
+
setFooter: () => {},
|
|
74
|
+
setHeader: () => {},
|
|
75
|
+
setTitle: () => {},
|
|
76
|
+
custom: async () => { throw new Error('Not implemented'); },
|
|
77
|
+
pasteToEditor: () => {},
|
|
78
|
+
setEditorText: () => {},
|
|
79
|
+
getEditorText: () => '',
|
|
80
|
+
editor: async () => undefined,
|
|
81
|
+
setEditorComponent: () => {},
|
|
82
|
+
theme: {},
|
|
83
|
+
getAllThemes: () => [],
|
|
84
|
+
getTheme: () => undefined,
|
|
85
|
+
setTheme: () => ({ success: false }),
|
|
86
|
+
getToolsExpanded: () => true,
|
|
87
|
+
setToolsExpanded: () => {},
|
|
88
|
+
},
|
|
89
|
+
hasUI: true,
|
|
90
|
+
cwd: process.cwd(),
|
|
91
|
+
sessionManager: {} as unknown,
|
|
92
|
+
modelRegistry: {} as unknown,
|
|
93
|
+
model: undefined,
|
|
94
|
+
isIdle: () => true,
|
|
95
|
+
abort: () => {},
|
|
96
|
+
hasPendingMessages: () => false,
|
|
97
|
+
shutdown: () => {},
|
|
98
|
+
getContextUsage: () => undefined,
|
|
99
|
+
compact: () => {},
|
|
100
|
+
getSystemPrompt: () => '',
|
|
101
|
+
waitForIdle: mock.fn(async () => {}),
|
|
102
|
+
newSession: async () => ({ cancelled: false }),
|
|
103
|
+
fork: async () => ({ cancelled: false }),
|
|
104
|
+
navigateTree: async () => ({ cancelled: false }),
|
|
105
|
+
switchSession: async () => ({ cancelled: false }),
|
|
106
|
+
reload: mock.fn(async () => {}),
|
|
107
|
+
} as unknown as ExtensionCommandContext;
|
|
108
|
+
|
|
109
|
+
return { ctx, selectCalls };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// Tests
|
|
114
|
+
// ============================================================================
|
|
115
|
+
|
|
116
|
+
const skipReason = !marketplacesAvailable()
|
|
117
|
+
? fixtureSetup.skipReason ?? 'Marketplace repos not found for TUI testing'
|
|
118
|
+
: undefined;
|
|
119
|
+
|
|
120
|
+
describe(
|
|
121
|
+
'TUI Command Flow Tests',
|
|
122
|
+
{ skip: skipReason },
|
|
123
|
+
() => {
|
|
124
|
+
let tempDir: string;
|
|
125
|
+
let prefsPath: string;
|
|
126
|
+
let prefs: Record<string, unknown>;
|
|
127
|
+
|
|
128
|
+
before(() => {
|
|
129
|
+
tempDir = mkdtempSync(join(tmpdir(), 'gsd-tui-test-'));
|
|
130
|
+
prefsPath = join(tempDir, 'preferences.md');
|
|
131
|
+
prefs = { version: 1 };
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
after(() => {
|
|
135
|
+
fixtures?.cleanup();
|
|
136
|
+
if (existsSync(tempDir)) {
|
|
137
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('getClaudeSearchRoots()', () => {
|
|
142
|
+
it('should return existing skill and plugin roots', () => {
|
|
143
|
+
const cwd = process.cwd();
|
|
144
|
+
const { skillRoots, pluginRoots } = getClaudeSearchRoots(cwd);
|
|
145
|
+
|
|
146
|
+
// At least one root should exist in our test environment
|
|
147
|
+
assert.ok(
|
|
148
|
+
skillRoots.length > 0 || pluginRoots.length > 0,
|
|
149
|
+
'Should find at least one search root'
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// All returned roots should exist
|
|
153
|
+
for (const root of [...skillRoots, ...pluginRoots]) {
|
|
154
|
+
assert.ok(existsSync(root), `Root should exist: ${root}`);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe('discoverClaudeSkills()', () => {
|
|
160
|
+
it('should discover skills without crashing', () => {
|
|
161
|
+
const cwd = process.cwd();
|
|
162
|
+
const skills = discoverClaudeSkills(cwd);
|
|
163
|
+
|
|
164
|
+
assert.ok(Array.isArray(skills), 'Should return an array');
|
|
165
|
+
|
|
166
|
+
// Log for observability
|
|
167
|
+
console.log(`\nDiscovered ${skills.length} skills`);
|
|
168
|
+
|
|
169
|
+
if (skills.length > 0) {
|
|
170
|
+
console.log('Sample skills:');
|
|
171
|
+
skills.slice(0, 3).forEach(s => {
|
|
172
|
+
console.log(` - ${s.name} (${s.sourceLabel})`);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Verify structure
|
|
176
|
+
const sample = skills[0]!;
|
|
177
|
+
assert.ok(sample.name, 'Skill should have name');
|
|
178
|
+
assert.ok(sample.path, 'Skill should have path');
|
|
179
|
+
assert.ok(sample.root, 'Skill should have root');
|
|
180
|
+
assert.strictEqual(sample.type, 'skill');
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('discoverClaudePlugins()', () => {
|
|
186
|
+
it('should discover plugins without crashing', () => {
|
|
187
|
+
const cwd = process.cwd();
|
|
188
|
+
const plugins = discoverClaudePlugins(cwd);
|
|
189
|
+
|
|
190
|
+
assert.ok(Array.isArray(plugins), 'Should return an array');
|
|
191
|
+
|
|
192
|
+
// Log for observability
|
|
193
|
+
console.log(`\nDiscovered ${plugins.length} plugins`);
|
|
194
|
+
|
|
195
|
+
if (plugins.length > 0) {
|
|
196
|
+
console.log('Sample plugins:');
|
|
197
|
+
plugins.slice(0, 3).forEach(p => {
|
|
198
|
+
console.log(` - ${p.name} (${p.sourceLabel})`);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Verify structure
|
|
202
|
+
const sample = plugins[0]!;
|
|
203
|
+
assert.ok(sample.name, 'Plugin should have name');
|
|
204
|
+
assert.ok(sample.path, 'Plugin should have path');
|
|
205
|
+
assert.strictEqual(sample.type, 'plugin');
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe('runClaudeImportFlow()', () => {
|
|
211
|
+
it('should not crash when user cancels at first prompt', async () => {
|
|
212
|
+
const { ctx, selectCalls } = createMockContext(['Cancel']);
|
|
213
|
+
|
|
214
|
+
const readPrefs = () => ({ ...prefs });
|
|
215
|
+
const writePrefs = async (p: Record<string, unknown>) => {
|
|
216
|
+
Object.assign(prefs, p);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// Should complete without throwing
|
|
220
|
+
await runClaudeImportFlow(ctx, 'global', readPrefs, writePrefs);
|
|
221
|
+
|
|
222
|
+
// Should have asked about asset type
|
|
223
|
+
assert.ok(selectCalls.length >= 1, 'Should have at least one select call');
|
|
224
|
+
assert.ok(
|
|
225
|
+
selectCalls[0]!.prompt.includes('Import Claude assets'),
|
|
226
|
+
'First prompt should be about asset selection'
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should not crash when selecting skills only with cancel at next step', async () => {
|
|
231
|
+
const { ctx, selectCalls } = createMockContext([
|
|
232
|
+
'Skills only', // Select skills only
|
|
233
|
+
'Cancel', // Cancel at skill selection
|
|
234
|
+
]);
|
|
235
|
+
|
|
236
|
+
const readPrefs = () => ({ ...prefs });
|
|
237
|
+
const writePrefs = async (p: Record<string, unknown>) => {
|
|
238
|
+
Object.assign(prefs, p);
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// Should complete without throwing
|
|
242
|
+
await runClaudeImportFlow(ctx, 'global', readPrefs, writePrefs);
|
|
243
|
+
|
|
244
|
+
// Log interaction flow
|
|
245
|
+
console.log('\nSelect calls made:');
|
|
246
|
+
selectCalls.forEach((call, i) => {
|
|
247
|
+
console.log(` ${i + 1}. "${call.prompt}"`);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should handle marketplace flow when user selects plugins', async () => {
|
|
252
|
+
const { ctx, selectCalls } = createMockContext([
|
|
253
|
+
'Plugins only', // Select plugins only
|
|
254
|
+
'Yes - discover plugins and select components', // Marketplace prompt
|
|
255
|
+
'Cancel', // Cancel at component selection
|
|
256
|
+
]);
|
|
257
|
+
|
|
258
|
+
const readPrefs = () => ({ ...prefs });
|
|
259
|
+
const writePrefs = async (p: Record<string, unknown>) => {
|
|
260
|
+
Object.assign(prefs, p);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// Should complete without throwing
|
|
264
|
+
await runClaudeImportFlow(ctx, 'global', readPrefs, writePrefs);
|
|
265
|
+
|
|
266
|
+
// Log interaction flow
|
|
267
|
+
console.log('\nMarketplace flow select calls:');
|
|
268
|
+
selectCalls.forEach((call, i) => {
|
|
269
|
+
console.log(` ${i + 1}. "${call.prompt}"`);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it('should complete import-all flow with mock UI', async () => {
|
|
274
|
+
// This tests the happy path where user selects "Import all"
|
|
275
|
+
const { ctx, selectCalls } = createMockContext([
|
|
276
|
+
'Skills + plugins', // Select both
|
|
277
|
+
'Cancel', // Cancel at skill selection (no skills to import)
|
|
278
|
+
'Yes - discover plugins and select components', // Marketplace prompt
|
|
279
|
+
'Import all components', // Import all
|
|
280
|
+
'Yes, continue', // Continue with warnings (if any)
|
|
281
|
+
]);
|
|
282
|
+
|
|
283
|
+
const readPrefs = () => ({ ...prefs });
|
|
284
|
+
const writePrefs = async (p: Record<string, unknown>) => {
|
|
285
|
+
Object.assign(prefs, p);
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// Should complete without throwing
|
|
289
|
+
await runClaudeImportFlow(ctx, 'global', readPrefs, writePrefs);
|
|
290
|
+
|
|
291
|
+
// Log interaction flow
|
|
292
|
+
console.log('\nImport-all flow select calls:');
|
|
293
|
+
selectCalls.forEach((call, i) => {
|
|
294
|
+
console.log(` ${i + 1}. "${call.prompt}"`);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// Verify notification was called
|
|
298
|
+
const notifyCalls = (ctx.ui.notify as unknown as ReturnType<typeof mock.fn>).mock.calls;
|
|
299
|
+
assert.ok(notifyCalls.length > 0, 'Should have shown notification');
|
|
300
|
+
|
|
301
|
+
console.log('\nNotifications shown:');
|
|
302
|
+
notifyCalls.forEach((call, i) => {
|
|
303
|
+
const msg = call.arguments[0];
|
|
304
|
+
const level = call.arguments[1];
|
|
305
|
+
console.log(` ${i + 1}. [${level}]: ${String(msg).split('\n')[0]}`);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('should not persist marketplace agent directories into package sources', async () => {
|
|
310
|
+
const isolatedAgentDir = join(tempDir, '.gsd', 'agent');
|
|
311
|
+
const settingsPath = join(isolatedAgentDir, 'settings.json');
|
|
312
|
+
rmSync(isolatedAgentDir, { recursive: true, force: true });
|
|
313
|
+
process.env.GSD_CODING_AGENT_DIR = isolatedAgentDir;
|
|
314
|
+
|
|
315
|
+
try {
|
|
316
|
+
mkdirSync(isolatedAgentDir, { recursive: true });
|
|
317
|
+
const tempSettings: Record<string, unknown> = { packages: [] };
|
|
318
|
+
writeFileSync(settingsPath, JSON.stringify(tempSettings, null, 2));
|
|
319
|
+
|
|
320
|
+
const { ctx } = createMockContext([
|
|
321
|
+
'Plugins only',
|
|
322
|
+
'Yes - discover plugins and select components',
|
|
323
|
+
'Import all components',
|
|
324
|
+
'Yes, continue',
|
|
325
|
+
]);
|
|
326
|
+
|
|
327
|
+
const readPrefs = () => ({ ...prefs });
|
|
328
|
+
const writePrefs = async (p: Record<string, unknown>) => {
|
|
329
|
+
Object.assign(prefs, p);
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
await runClaudeImportFlow(ctx, 'global', readPrefs, writePrefs);
|
|
333
|
+
|
|
334
|
+
const settings = JSON.parse(readFileSync(settingsPath, 'utf8')) as { packages?: unknown[] };
|
|
335
|
+
const packageEntries = Array.isArray(settings.packages) ? settings.packages : [];
|
|
336
|
+
const hasAgentsDirPackage = packageEntries.some((entry) => {
|
|
337
|
+
const source = typeof entry === 'string'
|
|
338
|
+
? entry
|
|
339
|
+
: (entry && typeof entry === 'object' ? (entry as { source?: unknown }).source : undefined);
|
|
340
|
+
return typeof source === 'string' && source.endsWith('/agents');
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
assert.strictEqual(hasAgentsDirPackage, false, 'Marketplace agent directories should not be persisted as package sources');
|
|
344
|
+
} finally {
|
|
345
|
+
delete process.env.GSD_CODING_AGENT_DIR;
|
|
346
|
+
rmSync(isolatedAgentDir, { recursive: true, force: true });
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
);
|