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
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* none-mode-gates.test.ts — Tests for isolation-mode gate functions.
|
|
3
|
+
*
|
|
4
|
+
* Verifies that shouldUseWorktreeIsolation(), getIsolationMode(), and
|
|
5
|
+
* getActiveAutoWorktreeContext() behave correctly across all three
|
|
6
|
+
* isolation modes (none, branch, worktree) and at baseline (no prefs).
|
|
7
|
+
*
|
|
8
|
+
* Uses the writeRunnerPreferences pattern from doctor-git.test.ts:
|
|
9
|
+
* PROJECT_PREFERENCES_PATH is a module-level constant frozen at import
|
|
10
|
+
* time, so process.chdir() won't redirect preference loading. We write
|
|
11
|
+
* prefs to the runner's cwd .gsd/preferences.md and clean up in finally.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
|
|
17
|
+
import { shouldUseWorktreeIsolation } from "../auto.ts";
|
|
18
|
+
import { getIsolationMode } from "../preferences.ts";
|
|
19
|
+
import { getActiveAutoWorktreeContext } from "../auto-worktree.ts";
|
|
20
|
+
import { invalidateAllCaches } from "../cache.ts";
|
|
21
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
22
|
+
|
|
23
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
24
|
+
|
|
25
|
+
// --- Preferences helpers (same pattern as doctor-git.test.ts K001) ---
|
|
26
|
+
|
|
27
|
+
const RUNNER_PREFS_PATH = join(process.cwd(), ".gsd", "preferences.md");
|
|
28
|
+
|
|
29
|
+
function writeRunnerPreferences(isolation: "none" | "worktree" | "branch"): void {
|
|
30
|
+
mkdirSync(join(process.cwd(), ".gsd"), { recursive: true });
|
|
31
|
+
writeFileSync(RUNNER_PREFS_PATH, `---\ngit:\n isolation: "${isolation}"\n---\n`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function removeRunnerPreferences(): void {
|
|
35
|
+
try { rmSync(RUNNER_PREFS_PATH); } catch { /* ignore if already gone */ }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// --- Tests ---
|
|
39
|
+
|
|
40
|
+
// Test 1: shouldUseWorktreeIsolation returns false for none
|
|
41
|
+
console.log("Test 1: shouldUseWorktreeIsolation returns false for none");
|
|
42
|
+
try {
|
|
43
|
+
writeRunnerPreferences("none");
|
|
44
|
+
invalidateAllCaches();
|
|
45
|
+
assertEq(shouldUseWorktreeIsolation(), false, "shouldUseWorktreeIsolation() with none prefs");
|
|
46
|
+
} finally {
|
|
47
|
+
removeRunnerPreferences();
|
|
48
|
+
invalidateAllCaches();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Test 2: shouldUseWorktreeIsolation returns false for branch
|
|
52
|
+
console.log("Test 2: shouldUseWorktreeIsolation returns false for branch");
|
|
53
|
+
try {
|
|
54
|
+
writeRunnerPreferences("branch");
|
|
55
|
+
invalidateAllCaches();
|
|
56
|
+
assertEq(shouldUseWorktreeIsolation(), false, "shouldUseWorktreeIsolation() with branch prefs");
|
|
57
|
+
} finally {
|
|
58
|
+
removeRunnerPreferences();
|
|
59
|
+
invalidateAllCaches();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Test 3: shouldUseWorktreeIsolation returns true for worktree
|
|
63
|
+
console.log("Test 3: shouldUseWorktreeIsolation returns true for worktree");
|
|
64
|
+
try {
|
|
65
|
+
writeRunnerPreferences("worktree");
|
|
66
|
+
invalidateAllCaches();
|
|
67
|
+
assertEq(shouldUseWorktreeIsolation(), true, "shouldUseWorktreeIsolation() with worktree prefs");
|
|
68
|
+
} finally {
|
|
69
|
+
removeRunnerPreferences();
|
|
70
|
+
invalidateAllCaches();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Test 4: shouldUseWorktreeIsolation returns true for no prefs (default)
|
|
74
|
+
console.log("Test 4: shouldUseWorktreeIsolation returns true for no prefs (default)");
|
|
75
|
+
try {
|
|
76
|
+
removeRunnerPreferences(); // ensure no prefs file
|
|
77
|
+
invalidateAllCaches();
|
|
78
|
+
assertEq(shouldUseWorktreeIsolation(), true, "shouldUseWorktreeIsolation() with no prefs (default worktree)");
|
|
79
|
+
} finally {
|
|
80
|
+
invalidateAllCaches();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Test 5: getIsolationMode returns "none" with none prefs
|
|
84
|
+
console.log("Test 5: getIsolationMode returns 'none' with none prefs");
|
|
85
|
+
try {
|
|
86
|
+
writeRunnerPreferences("none");
|
|
87
|
+
invalidateAllCaches();
|
|
88
|
+
assertEq(getIsolationMode(), "none", "getIsolationMode() with none prefs");
|
|
89
|
+
} finally {
|
|
90
|
+
removeRunnerPreferences();
|
|
91
|
+
invalidateAllCaches();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Test 6: getActiveAutoWorktreeContext returns null at baseline
|
|
95
|
+
console.log("Test 6: getActiveAutoWorktreeContext returns null at baseline");
|
|
96
|
+
assertEq(getActiveAutoWorktreeContext(), null, "getActiveAutoWorktreeContext() returns null without enterAutoWorktree()");
|
|
97
|
+
|
|
98
|
+
// Test 7: System prompt worktree block absent without active worktree
|
|
99
|
+
console.log("Test 7: System prompt worktree block absent without active worktree");
|
|
100
|
+
{
|
|
101
|
+
const ctx = getActiveAutoWorktreeContext();
|
|
102
|
+
assertTrue(ctx === null, "getActiveAutoWorktreeContext() null confirms system prompt worktree block will not be injected");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
report();
|
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live E2E Tests Against Real Marketplace Repos
|
|
3
|
+
*
|
|
4
|
+
* Tests R014: validates PluginImporter against real marketplace data.
|
|
5
|
+
*
|
|
6
|
+
* Source model alignment:
|
|
7
|
+
* - Prefer Claude Code managed marketplace locations when available
|
|
8
|
+
* - Fall back to cloned fixture repos for portability
|
|
9
|
+
* - Never require a contributor's personal sibling repo layout
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { describe, it, before, after } from 'node:test';
|
|
13
|
+
import assert from 'node:assert';
|
|
14
|
+
import { PluginImporter, type DiscoveryResult, type ImportManifest } from '../plugin-importer.js';
|
|
15
|
+
import { getMarketplaceFixtures } from './marketplace-test-fixtures.js';
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Live Test Configuration
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Canonical name format regex: namespace:name or bare name
|
|
23
|
+
* Allows alphanumeric, underscore, hyphen, and dot in names.
|
|
24
|
+
* Real marketplace data has names like "ecosystem-researcher-v1.1-rt-ica".
|
|
25
|
+
*/
|
|
26
|
+
const CANONICAL_NAME_REGEX = /^[a-zA-Z0-9_.-]+(?::[a-zA-Z0-9_.-]+)?$/;
|
|
27
|
+
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Live E2E Tests
|
|
30
|
+
// ============================================================================
|
|
31
|
+
|
|
32
|
+
const fixtureSetup = getMarketplaceFixtures(import.meta.dirname);
|
|
33
|
+
const fixtures = fixtureSetup.fixtures;
|
|
34
|
+
const CLAUDE_SKILLS_PATH = fixtures?.claudeSkillsPath;
|
|
35
|
+
const CLAUDE_PLUGINS_OFFICIAL_PATH = fixtures?.claudePluginsOfficialPath;
|
|
36
|
+
|
|
37
|
+
// Log marketplace status for observability
|
|
38
|
+
console.log('Live E2E Test Configuration:');
|
|
39
|
+
console.log(` source: ${fixtures?.source ?? 'unavailable'}`);
|
|
40
|
+
if (CLAUDE_SKILLS_PATH) {
|
|
41
|
+
console.log(` claude_skills: FOUND at ${CLAUDE_SKILLS_PATH}`);
|
|
42
|
+
}
|
|
43
|
+
if (CLAUDE_PLUGINS_OFFICIAL_PATH) {
|
|
44
|
+
console.log(` claude-plugins-official: FOUND at ${CLAUDE_PLUGINS_OFFICIAL_PATH}`);
|
|
45
|
+
}
|
|
46
|
+
if (!fixtureSetup.available) {
|
|
47
|
+
console.log(` unavailable: ${fixtureSetup.skipReason}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const skipReason = !fixtureSetup.available ? fixtureSetup.skipReason : undefined;
|
|
51
|
+
|
|
52
|
+
describe(
|
|
53
|
+
'Live E2E Tests',
|
|
54
|
+
{ skip: skipReason },
|
|
55
|
+
() => {
|
|
56
|
+
let importer: PluginImporter;
|
|
57
|
+
let discoveryResult: DiscoveryResult;
|
|
58
|
+
|
|
59
|
+
before(() => {
|
|
60
|
+
importer = new PluginImporter();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
after(() => {
|
|
64
|
+
fixtures?.cleanup();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('Step 2: discover() against real marketplaces', () => {
|
|
68
|
+
it('should discover plugins from both marketplaces with no fatal errors', () => {
|
|
69
|
+
// Stage 1: Discover
|
|
70
|
+
discoveryResult = importer.discover([
|
|
71
|
+
CLAUDE_SKILLS_PATH!,
|
|
72
|
+
CLAUDE_PLUGINS_OFFICIAL_PATH!,
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
// Log discovery summary for observability
|
|
76
|
+
console.log('\nDiscovery Summary:');
|
|
77
|
+
console.log(` Marketplaces processed: ${discoveryResult.summary.marketplacesProcessed}`);
|
|
78
|
+
console.log(` Total plugins: ${discoveryResult.summary.totalPlugins}`);
|
|
79
|
+
console.log(` Total components: ${discoveryResult.summary.totalComponents}`);
|
|
80
|
+
console.log(` Marketplaces with errors: ${discoveryResult.summary.marketplacesWithErrors}`);
|
|
81
|
+
|
|
82
|
+
// Assert positive counts
|
|
83
|
+
assert.ok(
|
|
84
|
+
discoveryResult.summary.totalPlugins > 0,
|
|
85
|
+
'Should find at least one plugin across both marketplaces'
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
assert.ok(
|
|
89
|
+
discoveryResult.summary.totalComponents > 0,
|
|
90
|
+
'Should discover at least one component across both marketplaces'
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// No fatal errors should crash the pipeline
|
|
94
|
+
assert.strictEqual(
|
|
95
|
+
discoveryResult.summary.marketplacesProcessed,
|
|
96
|
+
2,
|
|
97
|
+
'Should process both marketplace paths'
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should have processed both marketplace.json files', () => {
|
|
102
|
+
assert.ok(discoveryResult, 'Discovery must run first');
|
|
103
|
+
|
|
104
|
+
// Both marketplaces should have been attempted
|
|
105
|
+
assert.strictEqual(
|
|
106
|
+
discoveryResult.marketplaceResults.length,
|
|
107
|
+
2,
|
|
108
|
+
'Should have results for both marketplaces'
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// At least one should have succeeded (they're real repos)
|
|
112
|
+
const successfulMarketplaces = discoveryResult.marketplaceResults.filter(
|
|
113
|
+
(m) => m.status === 'ok'
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
assert.ok(
|
|
117
|
+
successfulMarketplaces.length >= 1,
|
|
118
|
+
'At least one marketplace should have loaded successfully'
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('Step 3: canonical name format validation', () => {
|
|
124
|
+
it('should have valid canonical names matching namespace:component format', () => {
|
|
125
|
+
assert.ok(discoveryResult, 'Discovery must run first');
|
|
126
|
+
|
|
127
|
+
const registry = importer.getRegistry();
|
|
128
|
+
assert.ok(registry, 'Registry should be populated');
|
|
129
|
+
|
|
130
|
+
const allComponents = registry.getAll();
|
|
131
|
+
|
|
132
|
+
// Should have components from real plugins
|
|
133
|
+
assert.ok(
|
|
134
|
+
allComponents.length > 0,
|
|
135
|
+
'Should have discovered components to validate'
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
// Log sample canonical names for observability
|
|
139
|
+
const sampleNames = allComponents.slice(0, 5).map((c) => c.canonicalName);
|
|
140
|
+
console.log('\nSample canonical names from discovered components:');
|
|
141
|
+
sampleNames.forEach((name) => console.log(` - ${name}`));
|
|
142
|
+
|
|
143
|
+
// Validate each canonical name
|
|
144
|
+
for (const component of allComponents) {
|
|
145
|
+
assert.ok(
|
|
146
|
+
CANONICAL_NAME_REGEX.test(component.canonicalName),
|
|
147
|
+
`Canonical name "${component.canonicalName}" should match format "namespace:name" or bare "name"`
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// Namespaced components should have colon in canonical name
|
|
151
|
+
if (component.namespace) {
|
|
152
|
+
assert.ok(
|
|
153
|
+
component.canonicalName.includes(':'),
|
|
154
|
+
`Namespaced component "${component.canonicalName}" should contain colon`
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// Canonical should be namespace:name
|
|
158
|
+
const expected = `${component.namespace}:${component.name}`;
|
|
159
|
+
assert.strictEqual(
|
|
160
|
+
component.canonicalName,
|
|
161
|
+
expected,
|
|
162
|
+
`Canonical name should equal namespace:name`
|
|
163
|
+
);
|
|
164
|
+
} else {
|
|
165
|
+
// Flat components should NOT have colon
|
|
166
|
+
assert.ok(
|
|
167
|
+
!component.canonicalName.includes(':'),
|
|
168
|
+
`Flat component "${component.canonicalName}" should not contain colon`
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
assert.strictEqual(
|
|
172
|
+
component.canonicalName,
|
|
173
|
+
component.name,
|
|
174
|
+
`Flat component canonical should equal bare name`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe('Step 4: selectComponents() filtering', () => {
|
|
182
|
+
it('should filter components by type and return non-empty results', () => {
|
|
183
|
+
assert.ok(discoveryResult, 'Discovery must run first');
|
|
184
|
+
|
|
185
|
+
// Filter by skills
|
|
186
|
+
const skills = importer.selectComponents((c) => c.type === 'skill');
|
|
187
|
+
|
|
188
|
+
// Filter by agents
|
|
189
|
+
const agents = importer.selectComponents((c) => c.type === 'agent');
|
|
190
|
+
|
|
191
|
+
console.log('\nComponent type counts:');
|
|
192
|
+
console.log(` Skills: ${skills.length}`);
|
|
193
|
+
console.log(` Agents: ${agents.length}`);
|
|
194
|
+
|
|
195
|
+
// At least one type should have components (real marketplaces have plugins)
|
|
196
|
+
assert.ok(
|
|
197
|
+
skills.length > 0 || agents.length > 0,
|
|
198
|
+
'At least one component type should have results from real marketplaces'
|
|
199
|
+
);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('should filter by namespace correctly', () => {
|
|
203
|
+
assert.ok(discoveryResult, 'Discovery must run first');
|
|
204
|
+
|
|
205
|
+
const registry = importer.getRegistry();
|
|
206
|
+
const allComponents = registry!.getAll();
|
|
207
|
+
|
|
208
|
+
// Get unique namespaces
|
|
209
|
+
const namespaces = new Set(
|
|
210
|
+
allComponents.map((c) => c.namespace).filter((n): n is string => n !== undefined)
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
console.log('\nDiscovered namespaces:');
|
|
214
|
+
namespaces.forEach((ns) => console.log(` - ${ns}`));
|
|
215
|
+
|
|
216
|
+
if (namespaces.size > 0) {
|
|
217
|
+
// Pick a namespace and filter
|
|
218
|
+
const testNamespace = Array.from(namespaces)[0]!;
|
|
219
|
+
const filtered = importer.selectComponents(
|
|
220
|
+
(c) => c.namespace === testNamespace
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
assert.ok(
|
|
224
|
+
filtered.length > 0,
|
|
225
|
+
`Should find components for namespace "${testNamespace}"`
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
// All results should match the filter
|
|
229
|
+
for (const comp of filtered) {
|
|
230
|
+
assert.strictEqual(
|
|
231
|
+
comp.namespace,
|
|
232
|
+
testNamespace,
|
|
233
|
+
'Filtered components should have correct namespace'
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe('Step 5: validateImport() on real data', () => {
|
|
241
|
+
it('should run validation on all discovered components without crash', () => {
|
|
242
|
+
assert.ok(discoveryResult, 'Discovery must run first');
|
|
243
|
+
|
|
244
|
+
const registry = importer.getRegistry();
|
|
245
|
+
const allComponents = registry!.getAll();
|
|
246
|
+
|
|
247
|
+
// Run validation on all discovered components
|
|
248
|
+
const validation = importer.validateImport(allComponents);
|
|
249
|
+
|
|
250
|
+
console.log('\nValidation result:');
|
|
251
|
+
console.log(` Can proceed: ${validation.canProceed}`);
|
|
252
|
+
console.log(` Total diagnostics: ${validation.summary.total}`);
|
|
253
|
+
console.log(` Errors: ${validation.summary.errors}`);
|
|
254
|
+
console.log(` Warnings: ${validation.summary.warnings}`);
|
|
255
|
+
|
|
256
|
+
if (validation.diagnostics.length > 0) {
|
|
257
|
+
console.log('\nDiagnostics:');
|
|
258
|
+
validation.diagnostics.forEach((d) => {
|
|
259
|
+
console.log(` [${d.severity}] ${d.class}: ${d.remediation}`);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Validation should complete without throwing
|
|
264
|
+
assert.ok(validation, 'Validation should return a result');
|
|
265
|
+
assert.ok(
|
|
266
|
+
typeof validation.canProceed === 'boolean',
|
|
267
|
+
'canProceed should be boolean'
|
|
268
|
+
);
|
|
269
|
+
assert.ok(
|
|
270
|
+
Array.isArray(validation.diagnostics),
|
|
271
|
+
'diagnostics should be an array'
|
|
272
|
+
);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('should have valid diagnostic structure if warnings exist', () => {
|
|
276
|
+
const validation = importer.getLastValidation();
|
|
277
|
+
assert.ok(validation, 'Validation should have run');
|
|
278
|
+
|
|
279
|
+
for (const diag of validation.diagnostics) {
|
|
280
|
+
// Verify diagnostic structure
|
|
281
|
+
assert.ok(diag.class, 'Diagnostic should have class');
|
|
282
|
+
assert.ok(
|
|
283
|
+
['error', 'warning'].includes(diag.severity),
|
|
284
|
+
'Diagnostic severity should be error or warning'
|
|
285
|
+
);
|
|
286
|
+
assert.ok(diag.remediation, 'Diagnostic should have remediation');
|
|
287
|
+
assert.ok(
|
|
288
|
+
Array.isArray(diag.involvedCanonicalNames),
|
|
289
|
+
'Diagnostic should have involvedCanonicalNames array'
|
|
290
|
+
);
|
|
291
|
+
assert.ok(
|
|
292
|
+
Array.isArray(diag.filePaths),
|
|
293
|
+
'Diagnostic should have filePaths array'
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('should not have error-severity diagnostics blocking on real data (data quality check)', () => {
|
|
299
|
+
const validation = importer.getLastValidation();
|
|
300
|
+
assert.ok(validation, 'Validation should have run');
|
|
301
|
+
|
|
302
|
+
// Real marketplace data should not have fatal canonical collisions
|
|
303
|
+
// (this is a data quality assertion)
|
|
304
|
+
if (validation.summary.errors > 0) {
|
|
305
|
+
console.log('\nWARNING: Real marketplace data has error-severity diagnostics!');
|
|
306
|
+
console.log('This may indicate duplicate canonical names in the marketplace.');
|
|
307
|
+
|
|
308
|
+
// Log the errors for investigation
|
|
309
|
+
validation.diagnostics
|
|
310
|
+
.filter((d) => d.severity === 'error')
|
|
311
|
+
.forEach((d) => {
|
|
312
|
+
console.log(` ERROR: ${d.class}`);
|
|
313
|
+
console.log(` Involved: ${d.involvedCanonicalNames.join(', ')}`);
|
|
314
|
+
console.log(` Files: ${d.filePaths.join(', ')}`);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Note: We allow errors in assertion but log them for visibility
|
|
319
|
+
// Real data might have collisions, but the pipeline should handle them
|
|
320
|
+
assert.strictEqual(typeof validation.canProceed, 'boolean');
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
describe('Step 6: getImportManifest() with canonical names', () => {
|
|
325
|
+
it('should generate manifest preserving canonical names from real plugins', () => {
|
|
326
|
+
assert.ok(discoveryResult, 'Discovery must run first');
|
|
327
|
+
|
|
328
|
+
const registry = importer.getRegistry();
|
|
329
|
+
const allComponents = registry!.getAll();
|
|
330
|
+
|
|
331
|
+
// Generate manifest for all components
|
|
332
|
+
const manifest = importer.getImportManifest(allComponents);
|
|
333
|
+
|
|
334
|
+
console.log('\nManifest summary:');
|
|
335
|
+
console.log(` Schema version: ${manifest.schemaVersion}`);
|
|
336
|
+
console.log(` Total entries: ${manifest.summary.total}`);
|
|
337
|
+
console.log(` Skills: ${manifest.summary.skills}`);
|
|
338
|
+
console.log(` Agents: ${manifest.summary.agents}`);
|
|
339
|
+
console.log(` Namespaces: ${manifest.summary.namespaces.length}`);
|
|
340
|
+
|
|
341
|
+
// Verify manifest structure
|
|
342
|
+
assert.strictEqual(manifest.schemaVersion, '1.0');
|
|
343
|
+
assert.strictEqual(
|
|
344
|
+
manifest.entries.length,
|
|
345
|
+
allComponents.length,
|
|
346
|
+
'Manifest should have entry for each component'
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
// Verify canonical names preserved
|
|
350
|
+
for (const entry of manifest.entries) {
|
|
351
|
+
// Find matching component
|
|
352
|
+
const component = allComponents.find(
|
|
353
|
+
(c) => c.canonicalName === entry.canonicalName
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
assert.ok(
|
|
357
|
+
component,
|
|
358
|
+
`Manifest entry should match component: ${entry.canonicalName}`
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
// Canonical name should match exactly
|
|
362
|
+
assert.strictEqual(
|
|
363
|
+
entry.canonicalName,
|
|
364
|
+
component.canonicalName,
|
|
365
|
+
'Canonical name should be preserved in manifest'
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
// Type should match
|
|
369
|
+
assert.strictEqual(entry.type, component.type);
|
|
370
|
+
|
|
371
|
+
// Namespace should match
|
|
372
|
+
assert.strictEqual(entry.namespace, component.namespace);
|
|
373
|
+
|
|
374
|
+
// Name should match
|
|
375
|
+
assert.strictEqual(entry.name, component.name);
|
|
376
|
+
|
|
377
|
+
// File path should be preserved
|
|
378
|
+
assert.strictEqual(entry.filePath, component.filePath);
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it('should produce JSON-serializable manifest', () => {
|
|
383
|
+
const registry = importer.getRegistry();
|
|
384
|
+
const allComponents = registry!.getAll();
|
|
385
|
+
|
|
386
|
+
const manifest = importer.getImportManifest(allComponents);
|
|
387
|
+
|
|
388
|
+
// Should be JSON serializable
|
|
389
|
+
const json = JSON.stringify(manifest, null, 2);
|
|
390
|
+
|
|
391
|
+
// Should parse back correctly
|
|
392
|
+
const parsed: ImportManifest = JSON.parse(json);
|
|
393
|
+
|
|
394
|
+
assert.strictEqual(parsed.schemaVersion, manifest.schemaVersion);
|
|
395
|
+
assert.strictEqual(parsed.entries.length, manifest.entries.length);
|
|
396
|
+
|
|
397
|
+
// Sample entries should match after round-trip
|
|
398
|
+
const sampleEntry = parsed.entries[0];
|
|
399
|
+
if (sampleEntry) {
|
|
400
|
+
const original = manifest.entries[0]!;
|
|
401
|
+
assert.strictEqual(sampleEntry.canonicalName, original.canonicalName);
|
|
402
|
+
assert.strictEqual(sampleEntry.type, original.type);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
it('should have correct summary counts', () => {
|
|
407
|
+
const registry = importer.getRegistry();
|
|
408
|
+
const allComponents = registry!.getAll();
|
|
409
|
+
|
|
410
|
+
const manifest = importer.getImportManifest(allComponents);
|
|
411
|
+
|
|
412
|
+
// Count skills and agents
|
|
413
|
+
const skillCount = manifest.entries.filter((e) => e.type === 'skill').length;
|
|
414
|
+
const agentCount = manifest.entries.filter((e) => e.type === 'agent').length;
|
|
415
|
+
|
|
416
|
+
assert.strictEqual(
|
|
417
|
+
manifest.summary.skills,
|
|
418
|
+
skillCount,
|
|
419
|
+
'Skill count should match entries'
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
assert.strictEqual(
|
|
423
|
+
manifest.summary.agents,
|
|
424
|
+
agentCount,
|
|
425
|
+
'Agent count should match entries'
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
assert.strictEqual(
|
|
429
|
+
manifest.summary.total,
|
|
430
|
+
manifest.entries.length,
|
|
431
|
+
'Total should match entry count'
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
// Namespaces should be unique and sorted
|
|
435
|
+
const uniqueNamespaces = new Set(
|
|
436
|
+
manifest.entries
|
|
437
|
+
.map((e) => e.namespace)
|
|
438
|
+
.filter((n): n is string => n !== undefined)
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
assert.deepStrictEqual(
|
|
442
|
+
manifest.summary.namespaces,
|
|
443
|
+
Array.from(uniqueNamespaces).sort(),
|
|
444
|
+
'Namespaces should be unique and sorted'
|
|
445
|
+
);
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
describe('Full pipeline verification', () => {
|
|
450
|
+
it('should execute discover → select → validate → manifest without error', () => {
|
|
451
|
+
// This test verifies the full pipeline works end-to-end
|
|
452
|
+
|
|
453
|
+
// Already have discovery from before()
|
|
454
|
+
assert.ok(discoveryResult, 'Discovery should have completed');
|
|
455
|
+
|
|
456
|
+
// Select subset
|
|
457
|
+
const skills = importer.selectComponents((c) => c.type === 'skill');
|
|
458
|
+
|
|
459
|
+
// Validate
|
|
460
|
+
const validation = importer.validateImport(skills);
|
|
461
|
+
assert.ok(validation, 'Validation should complete');
|
|
462
|
+
|
|
463
|
+
// Generate manifest
|
|
464
|
+
const manifest = importer.getImportManifest(skills);
|
|
465
|
+
assert.ok(manifest, 'Manifest generation should complete');
|
|
466
|
+
|
|
467
|
+
// All skills should be in manifest
|
|
468
|
+
assert.strictEqual(
|
|
469
|
+
manifest.summary.skills,
|
|
470
|
+
skills.length,
|
|
471
|
+
'All selected skills should be in manifest'
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
console.log('\nFull pipeline verification:');
|
|
475
|
+
console.log(` Selected: ${skills.length} skills`);
|
|
476
|
+
console.log(` Validated: canProceed=${validation.canProceed}`);
|
|
477
|
+
console.log(` Manifest: ${manifest.summary.total} entries`);
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
);
|