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.
Files changed (279) hide show
  1. package/README.md +12 -0
  2. package/dist/cli.js +21 -18
  3. package/dist/help-text.d.ts +2 -0
  4. package/dist/help-text.js +47 -0
  5. package/dist/loader.js +2 -16
  6. package/dist/mcp-server.d.ts +18 -0
  7. package/dist/mcp-server.js +53 -0
  8. package/dist/onboarding.d.ts +0 -6
  9. package/dist/onboarding.js +0 -28
  10. package/dist/resources/agents/javascript-pro.md +280 -0
  11. package/dist/resources/agents/typescript-pro.md +255 -0
  12. package/dist/resources/extensions/bg-shell/index.ts +14 -2
  13. package/dist/resources/extensions/bg-shell/utilities.ts +14 -0
  14. package/dist/resources/extensions/browser-tools/{core.js → core.ts} +329 -190
  15. package/dist/resources/extensions/gsd/auto-dashboard.ts +2 -1
  16. package/dist/resources/extensions/gsd/auto-prompts.ts +42 -1
  17. package/dist/resources/extensions/gsd/auto-worktree.ts +35 -2
  18. package/dist/resources/extensions/gsd/auto.ts +116 -10
  19. package/dist/resources/extensions/gsd/claude-import.ts +656 -0
  20. package/dist/resources/extensions/gsd/collision-diagnostics.ts +332 -0
  21. package/dist/resources/extensions/gsd/commands.ts +60 -7
  22. package/dist/resources/extensions/gsd/diff-context.ts +220 -0
  23. package/dist/resources/extensions/gsd/docs/claude-marketplace-import.md +214 -0
  24. package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -1
  25. package/dist/resources/extensions/gsd/doctor.ts +12 -4
  26. package/dist/resources/extensions/gsd/file-watcher.ts +97 -0
  27. package/dist/resources/extensions/gsd/files.ts +1 -1
  28. package/dist/resources/extensions/gsd/forensics.ts +596 -0
  29. package/dist/resources/extensions/gsd/git-service.ts +2 -1
  30. package/dist/resources/extensions/gsd/github-client.ts +235 -0
  31. package/dist/resources/extensions/gsd/gitignore.ts +1 -0
  32. package/dist/resources/extensions/gsd/marketplace-discovery.ts +507 -0
  33. package/dist/resources/extensions/gsd/mcp-server.ts +87 -0
  34. package/dist/resources/extensions/gsd/namespaced-registry.ts +467 -0
  35. package/dist/resources/extensions/gsd/namespaced-resolver.ts +307 -0
  36. package/dist/resources/extensions/gsd/plugin-importer.ts +410 -0
  37. package/dist/resources/extensions/gsd/preferences.ts +14 -3
  38. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
  39. package/dist/resources/extensions/gsd/prompts/forensics.md +71 -0
  40. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  41. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  42. package/dist/resources/extensions/gsd/prompts/system.md +12 -3
  43. package/dist/resources/extensions/gsd/roadmap-slices.ts +1 -1
  44. package/dist/resources/extensions/gsd/session-forensics.ts +5 -5
  45. package/dist/resources/extensions/gsd/tests/claude-import-tui.test.ts +351 -0
  46. package/dist/resources/extensions/gsd/tests/collision-diagnostics.test.ts +705 -0
  47. package/dist/resources/extensions/gsd/tests/context-compression.test.ts +13 -0
  48. package/dist/resources/extensions/gsd/tests/diff-context.test.ts +136 -0
  49. package/dist/resources/extensions/gsd/tests/doctor-git.test.ts +118 -0
  50. package/dist/resources/extensions/gsd/tests/marketplace-discovery.test.ts +202 -0
  51. package/dist/resources/extensions/gsd/tests/marketplace-test-fixtures.ts +91 -0
  52. package/dist/resources/extensions/gsd/tests/namespaced-registry.test.ts +1027 -0
  53. package/dist/resources/extensions/gsd/tests/namespaced-resolver.test.ts +671 -0
  54. package/dist/resources/extensions/gsd/tests/none-mode-gates.test.ts +105 -0
  55. package/dist/resources/extensions/gsd/tests/plugin-importer-live.test.ts +481 -0
  56. package/dist/resources/extensions/gsd/tests/plugin-importer.test.ts +1383 -0
  57. package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +21 -2
  58. package/dist/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +8 -1
  59. package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +11 -0
  60. package/dist/resources/extensions/gsd/tests/worktree-bugfix.test.ts +120 -0
  61. package/dist/resources/extensions/gsd/token-counter.ts +45 -0
  62. package/dist/resources/extensions/gsd/visualizer-data.ts +2 -2
  63. package/dist/resources/extensions/gsd/worktree-manager.ts +29 -1
  64. package/dist/resources/extensions/gsd/worktree.ts +3 -0
  65. package/dist/resources/extensions/mcporter/index.ts +90 -7
  66. package/dist/resources/extensions/search-the-web/native-search.ts +2 -0
  67. package/dist/resources/extensions/search-the-web/tool-fetch-page.ts +9 -1
  68. package/dist/resources/extensions/search-the-web/url-utils.ts +35 -1
  69. package/dist/resources/extensions/shared/terminal.ts +1 -1
  70. package/dist/resources/extensions/universal-config/discovery.ts +4 -0
  71. package/dist/resources/extensions/universal-config/format.ts +35 -4
  72. package/dist/resources/extensions/universal-config/index.ts +5 -3
  73. package/dist/resources/extensions/universal-config/scanners.ts +65 -2
  74. package/dist/resources/extensions/universal-config/tests/discovery.test.ts +9 -1
  75. package/dist/resources/extensions/universal-config/tests/format.test.ts +22 -6
  76. package/dist/resources/extensions/universal-config/tests/scanners.test.ts +18 -0
  77. package/dist/resources/extensions/universal-config/types.ts +20 -1
  78. package/dist/resources/skills/lint/SKILL.md +141 -0
  79. package/dist/resources/skills/review/SKILL.md +214 -0
  80. package/dist/resources/skills/test/SKILL.md +201 -0
  81. package/dist/tool-bootstrap.js +2 -1
  82. package/dist/wizard.js +2 -0
  83. package/package.json +12 -7
  84. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  85. package/packages/pi-ai/dist/providers/azure-openai-responses.js +12 -1
  86. package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  87. package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  88. package/packages/pi-ai/dist/providers/openai-responses.js +12 -1
  89. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  90. package/packages/pi-ai/node_modules/@smithy/node-http-handler/LICENSE +201 -0
  91. package/packages/pi-ai/node_modules/@smithy/node-http-handler/README.md +9 -0
  92. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-cjs/index.js +762 -0
  93. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/build-abort-error.js +19 -0
  94. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/constants.js +1 -0
  95. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/get-transformed-headers.js +9 -0
  96. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/index.js +3 -0
  97. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http-handler.js +230 -0
  98. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-manager.js +87 -0
  99. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-pool.js +32 -0
  100. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-handler.js +169 -0
  101. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/readable.mock.js +21 -0
  102. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/server.mock.js +88 -0
  103. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-connection-timeout.js +36 -0
  104. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-request-timeout.js +21 -0
  105. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-socket-keep-alive.js +22 -0
  106. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-socket-timeout.js +23 -0
  107. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/collector.js +8 -0
  108. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/index.js +41 -0
  109. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/readable.mock.js +21 -0
  110. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/timing.js +4 -0
  111. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/write-request-body.js +63 -0
  112. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/build-abort-error.d.ts +10 -0
  113. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/constants.d.ts +5 -0
  114. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/get-transformed-headers.d.ts +4 -0
  115. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/index.d.ts +3 -0
  116. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http-handler.d.ts +46 -0
  117. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-connection-manager.d.ts +24 -0
  118. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-connection-pool.d.ts +12 -0
  119. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-handler.d.ts +63 -0
  120. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/readable.mock.d.ts +13 -0
  121. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/server.mock.d.ts +12 -0
  122. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-connection-timeout.d.ts +2 -0
  123. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-request-timeout.d.ts +6 -0
  124. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-socket-keep-alive.d.ts +6 -0
  125. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-socket-timeout.d.ts +2 -0
  126. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/collector.d.ts +5 -0
  127. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/index.d.ts +6 -0
  128. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/readable.mock.d.ts +13 -0
  129. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/timing.d.ts +8 -0
  130. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/build-abort-error.d.ts +10 -0
  131. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/constants.d.ts +5 -0
  132. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/get-transformed-headers.d.ts +4 -0
  133. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/index.d.ts +3 -0
  134. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http-handler.d.ts +46 -0
  135. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-connection-manager.d.ts +24 -0
  136. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-connection-pool.d.ts +12 -0
  137. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-handler.d.ts +63 -0
  138. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/readable.mock.d.ts +13 -0
  139. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/server.mock.d.ts +12 -0
  140. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-connection-timeout.d.ts +2 -0
  141. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-request-timeout.d.ts +6 -0
  142. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-socket-keep-alive.d.ts +6 -0
  143. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-socket-timeout.d.ts +2 -0
  144. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/collector.d.ts +5 -0
  145. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/index.d.ts +6 -0
  146. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/readable.mock.d.ts +13 -0
  147. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/timing.d.ts +8 -0
  148. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/write-request-body.d.ts +12 -0
  149. package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/write-request-body.d.ts +12 -0
  150. package/packages/pi-ai/node_modules/@smithy/node-http-handler/package.json +68 -0
  151. package/packages/pi-ai/package.json +3 -0
  152. package/packages/pi-ai/pnpm-lock.yaml +2022 -0
  153. package/packages/pi-ai/src/providers/azure-openai-responses.ts +12 -1
  154. package/packages/pi-ai/src/providers/openai-responses.ts +12 -1
  155. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  156. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  157. package/packages/pi-coding-agent/dist/core/extensions/index.js +1 -1
  158. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  159. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +1 -0
  160. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  161. package/packages/pi-coding-agent/dist/core/extensions/loader.js +12 -1
  162. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/core/extensions/loader.test.d.ts +2 -0
  164. package/packages/pi-coding-agent/dist/core/extensions/loader.test.d.ts.map +1 -0
  165. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +113 -0
  166. package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -0
  167. package/packages/pi-coding-agent/dist/core/extensions/project-trust.d.ts +4 -0
  168. package/packages/pi-coding-agent/dist/core/extensions/project-trust.d.ts.map +1 -0
  169. package/packages/pi-coding-agent/dist/core/extensions/project-trust.js +42 -0
  170. package/packages/pi-coding-agent/dist/core/extensions/project-trust.js.map +1 -0
  171. package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts +1 -0
  172. package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts.map +1 -1
  173. package/packages/pi-coding-agent/dist/core/resolve-config-value.js +18 -0
  174. package/packages/pi-coding-agent/dist/core/resolve-config-value.js.map +1 -1
  175. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.d.ts +2 -0
  176. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.d.ts.map +1 -0
  177. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +114 -0
  178. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -0
  179. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  180. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +8 -2
  181. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  182. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts +2 -0
  183. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  184. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +23 -9
  185. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.d.ts +2 -0
  187. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.d.ts.map +1 -0
  188. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +67 -0
  189. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -0
  190. package/packages/pi-coding-agent/package.json +1 -1
  191. package/packages/pi-coding-agent/pnpm-lock.yaml +454 -0
  192. package/packages/pi-coding-agent/scripts/copy-assets.cjs +24 -0
  193. package/packages/pi-coding-agent/src/core/extensions/index.ts +3 -0
  194. package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +141 -0
  195. package/packages/pi-coding-agent/src/core/extensions/loader.ts +14 -1
  196. package/packages/pi-coding-agent/src/core/extensions/project-trust.ts +51 -0
  197. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +132 -0
  198. package/packages/pi-coding-agent/src/core/resolve-config-value.ts +20 -0
  199. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +7 -2
  200. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +98 -0
  201. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +24 -9
  202. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  203. package/packages/pi-tui/dist/tui.js +2 -2
  204. package/packages/pi-tui/dist/tui.js.map +1 -1
  205. package/packages/pi-tui/package.json +3 -1
  206. package/packages/pi-tui/src/tui.ts +2 -2
  207. package/src/resources/agents/javascript-pro.md +280 -0
  208. package/src/resources/agents/typescript-pro.md +255 -0
  209. package/src/resources/extensions/bg-shell/index.ts +14 -2
  210. package/src/resources/extensions/bg-shell/utilities.ts +14 -0
  211. package/src/resources/extensions/browser-tools/{core.js → core.ts} +329 -190
  212. package/src/resources/extensions/gsd/auto-dashboard.ts +2 -1
  213. package/src/resources/extensions/gsd/auto-prompts.ts +42 -1
  214. package/src/resources/extensions/gsd/auto-worktree.ts +35 -2
  215. package/src/resources/extensions/gsd/auto.ts +116 -10
  216. package/src/resources/extensions/gsd/claude-import.ts +656 -0
  217. package/src/resources/extensions/gsd/collision-diagnostics.ts +332 -0
  218. package/src/resources/extensions/gsd/commands.ts +60 -7
  219. package/src/resources/extensions/gsd/diff-context.ts +220 -0
  220. package/src/resources/extensions/gsd/docs/claude-marketplace-import.md +214 -0
  221. package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -1
  222. package/src/resources/extensions/gsd/doctor.ts +12 -4
  223. package/src/resources/extensions/gsd/file-watcher.ts +97 -0
  224. package/src/resources/extensions/gsd/files.ts +1 -1
  225. package/src/resources/extensions/gsd/forensics.ts +596 -0
  226. package/src/resources/extensions/gsd/git-service.ts +2 -1
  227. package/src/resources/extensions/gsd/github-client.ts +235 -0
  228. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  229. package/src/resources/extensions/gsd/marketplace-discovery.ts +507 -0
  230. package/src/resources/extensions/gsd/mcp-server.ts +87 -0
  231. package/src/resources/extensions/gsd/namespaced-registry.ts +467 -0
  232. package/src/resources/extensions/gsd/namespaced-resolver.ts +307 -0
  233. package/src/resources/extensions/gsd/plugin-importer.ts +410 -0
  234. package/src/resources/extensions/gsd/preferences.ts +14 -3
  235. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
  236. package/src/resources/extensions/gsd/prompts/forensics.md +71 -0
  237. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  238. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  239. package/src/resources/extensions/gsd/prompts/system.md +12 -3
  240. package/src/resources/extensions/gsd/roadmap-slices.ts +1 -1
  241. package/src/resources/extensions/gsd/session-forensics.ts +5 -5
  242. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +351 -0
  243. package/src/resources/extensions/gsd/tests/collision-diagnostics.test.ts +705 -0
  244. package/src/resources/extensions/gsd/tests/context-compression.test.ts +13 -0
  245. package/src/resources/extensions/gsd/tests/diff-context.test.ts +136 -0
  246. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +118 -0
  247. package/src/resources/extensions/gsd/tests/marketplace-discovery.test.ts +202 -0
  248. package/src/resources/extensions/gsd/tests/marketplace-test-fixtures.ts +91 -0
  249. package/src/resources/extensions/gsd/tests/namespaced-registry.test.ts +1027 -0
  250. package/src/resources/extensions/gsd/tests/namespaced-resolver.test.ts +671 -0
  251. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +105 -0
  252. package/src/resources/extensions/gsd/tests/plugin-importer-live.test.ts +481 -0
  253. package/src/resources/extensions/gsd/tests/plugin-importer.test.ts +1383 -0
  254. package/src/resources/extensions/gsd/tests/preferences-git.test.ts +21 -2
  255. package/src/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +8 -1
  256. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +11 -0
  257. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +120 -0
  258. package/src/resources/extensions/gsd/token-counter.ts +45 -0
  259. package/src/resources/extensions/gsd/visualizer-data.ts +2 -2
  260. package/src/resources/extensions/gsd/worktree-manager.ts +29 -1
  261. package/src/resources/extensions/gsd/worktree.ts +3 -0
  262. package/src/resources/extensions/mcporter/index.ts +90 -7
  263. package/src/resources/extensions/search-the-web/native-search.ts +2 -0
  264. package/src/resources/extensions/search-the-web/tool-fetch-page.ts +9 -1
  265. package/src/resources/extensions/search-the-web/url-utils.ts +35 -1
  266. package/src/resources/extensions/shared/terminal.ts +1 -1
  267. package/src/resources/extensions/universal-config/discovery.ts +4 -0
  268. package/src/resources/extensions/universal-config/format.ts +35 -4
  269. package/src/resources/extensions/universal-config/index.ts +5 -3
  270. package/src/resources/extensions/universal-config/scanners.ts +65 -2
  271. package/src/resources/extensions/universal-config/tests/discovery.test.ts +9 -1
  272. package/src/resources/extensions/universal-config/tests/format.test.ts +22 -6
  273. package/src/resources/extensions/universal-config/tests/scanners.test.ts +18 -0
  274. package/src/resources/extensions/universal-config/types.ts +20 -1
  275. package/src/resources/skills/lint/SKILL.md +141 -0
  276. package/src/resources/skills/review/SKILL.md +214 -0
  277. package/src/resources/skills/test/SKILL.md +201 -0
  278. package/dist/resources/extensions/browser-tools/core.d.ts +0 -205
  279. package/src/resources/extensions/browser-tools/core.d.ts +0 -205
@@ -0,0 +1,507 @@
1
+ /**
2
+ * Marketplace Discovery Module
3
+ *
4
+ * Reads marketplace.json from Claude marketplace repos, resolves plugin source paths,
5
+ * parses plugin.json manifests, and inventories available components (skills, agents, commands, MCP servers, LSP servers, hooks).
6
+ *
7
+ * Marketplace roots should reflect the Claude Code model documented by Anthropic:
8
+ * users add a marketplace source with `/plugin marketplace add ...`, Claude stores
9
+ * marketplace sources under `~/.claude/plugins/marketplaces/`, and installed plugin
10
+ * payloads are copied into `~/.claude/plugins/cache/`.
11
+ *
12
+ * Handles two marketplace catalog shapes observed in the wild:
13
+ * 1. jamie-style: marketplace.json has {name, source} entries; plugins have .claude-plugin/plugin.json
14
+ * 2. official-style: marketplace.json entries contain inline metadata
15
+ */
16
+
17
+ import * as fs from 'node:fs';
18
+ import * as path from 'node:path';
19
+
20
+ // ============================================================================
21
+ // Type Definitions
22
+ // ============================================================================
23
+
24
+ /** Owner information in marketplace manifest */
25
+ export interface MarketplaceOwner {
26
+ name: string;
27
+ email?: string;
28
+ url?: string;
29
+ }
30
+
31
+ /** Marketplace metadata */
32
+ export interface MarketplaceMetadata {
33
+ description?: string;
34
+ version?: string;
35
+ }
36
+
37
+ /** Source can be a relative path or a complex object (github, url, git-subdir) */
38
+ export type PluginSource = string | {
39
+ source?: string;
40
+ repo?: string;
41
+ url?: string;
42
+ path?: string;
43
+ sha?: string;
44
+ ref?: string;
45
+ };
46
+
47
+ /** Marketplace plugin entry - minimal info from marketplace.json */
48
+ export interface MarketplacePluginEntry {
49
+ name: string;
50
+ source: PluginSource;
51
+ // Optional inline metadata (official-style)
52
+ description?: string;
53
+ version?: string;
54
+ author?: MarketplaceOwner;
55
+ category?: string;
56
+ homepage?: string;
57
+ strict?: boolean;
58
+ mcpServers?: Record<string, unknown>;
59
+ lspServers?: Record<string, unknown>;
60
+ tags?: string[];
61
+ }
62
+
63
+ /** Complete marketplace manifest */
64
+ export interface MarketplaceManifest {
65
+ $schema?: string;
66
+ name: string;
67
+ description?: string;
68
+ owner?: MarketplaceOwner;
69
+ metadata?: MarketplaceMetadata;
70
+ plugins: MarketplacePluginEntry[];
71
+ }
72
+
73
+ /** Plugin manifest from .claude-plugin/plugin.json */
74
+ export interface PluginManifest {
75
+ name: string;
76
+ description?: string;
77
+ version?: string;
78
+ author?: MarketplaceOwner;
79
+ homepage?: string;
80
+ mcpServers?: Record<string, unknown>;
81
+ lspServers?: Record<string, unknown>;
82
+ // Additional fields that might be present
83
+ [key: string]: unknown;
84
+ }
85
+
86
+ /** Inventory of components in a plugin */
87
+ export interface PluginComponentInventory {
88
+ skills: string[];
89
+ agents: string[];
90
+ commands: string[];
91
+ mcpServers: Record<string, unknown>;
92
+ lspServers: Record<string, unknown>;
93
+ hooks?: string[];
94
+ }
95
+
96
+ /** Discovered plugin with all metadata and inventory */
97
+ export interface DiscoveredPlugin {
98
+ name: string;
99
+ canonicalName: string;
100
+ source: PluginSource;
101
+ resolvedPath: string | null;
102
+ status: 'ok' | 'error';
103
+ error?: string;
104
+ // Metadata sources
105
+ manifestSource: 'plugin.json' | 'marketplace-inline' | 'derived';
106
+ description?: string;
107
+ version?: string;
108
+ author?: MarketplaceOwner;
109
+ category?: string;
110
+ homepage?: string;
111
+ // Component inventory
112
+ inventory: PluginComponentInventory;
113
+ }
114
+
115
+ /** Result of marketplace discovery */
116
+ export interface MarketplaceDiscoveryResult {
117
+ status: 'ok' | 'error';
118
+ error?: string;
119
+ marketplacePath: string;
120
+ marketplaceName: string;
121
+ pluginFormat: 'jamie-style' | 'official-style' | 'unknown';
122
+ plugins: DiscoveredPlugin[];
123
+ summary: {
124
+ total: number;
125
+ ok: number;
126
+ error: number;
127
+ };
128
+ }
129
+
130
+ // ============================================================================
131
+ // Helper Functions
132
+ // ============================================================================
133
+
134
+ /**
135
+ * Check if a source path is a relative local path (not a URL or complex source)
136
+ */
137
+ function isLocalSource(source: PluginSource): source is string {
138
+ if (typeof source === 'string') {
139
+ return !source.startsWith('http://') &&
140
+ !source.startsWith('https://') &&
141
+ !source.startsWith('git@') &&
142
+ !source.includes('://');
143
+ }
144
+ return false;
145
+ }
146
+
147
+ /**
148
+ * Resolve a relative source path to an absolute directory path
149
+ */
150
+ export function resolvePluginRoot(repoRoot: string, source: PluginSource): string | null {
151
+ if (!isLocalSource(source)) {
152
+ // External source (URL, git repo) - can't resolve locally
153
+ return null;
154
+ }
155
+
156
+ // Handle both ./plugins/name and plugins/name formats
157
+ let resolvedPath = source;
158
+ if (source.startsWith('./')) {
159
+ resolvedPath = source.slice(2);
160
+ }
161
+
162
+ const absolutePath = path.resolve(repoRoot, resolvedPath);
163
+ return absolutePath;
164
+ }
165
+
166
+ // ============================================================================
167
+ // Core Functions
168
+ // ============================================================================
169
+
170
+ /**
171
+ * Parse marketplace.json from a marketplace repository root
172
+ *
173
+ * @param repoRoot - Absolute path to the marketplace repository root
174
+ * @returns Parsed marketplace manifest or error
175
+ */
176
+ export function parseMarketplaceJson(repoRoot: string):
177
+ | { success: true; manifest: MarketplaceManifest }
178
+ | { success: false; error: string } {
179
+
180
+ const marketplacePath = path.join(repoRoot, '.claude-plugin', 'marketplace.json');
181
+
182
+ // Check if file exists
183
+ if (!fs.existsSync(marketplacePath)) {
184
+ return {
185
+ success: false,
186
+ error: `marketplace.json not found at ${marketplacePath}`
187
+ };
188
+ }
189
+
190
+ // Read and parse JSON
191
+ let content: string;
192
+ try {
193
+ content = fs.readFileSync(marketplacePath, 'utf-8');
194
+ } catch (err) {
195
+ return {
196
+ success: false,
197
+ error: `Failed to read marketplace.json: ${err instanceof Error ? err.message : String(err)}`
198
+ };
199
+ }
200
+
201
+ let parsed: unknown;
202
+ try {
203
+ parsed = JSON.parse(content);
204
+ } catch (err) {
205
+ return {
206
+ success: false,
207
+ error: `Failed to parse marketplace.json: ${err instanceof Error ? err.message : String(err)}`
208
+ };
209
+ }
210
+
211
+ // Validate structure
212
+ if (!parsed || typeof parsed !== 'object') {
213
+ return {
214
+ success: false,
215
+ error: 'marketplace.json is not a valid JSON object'
216
+ };
217
+ }
218
+
219
+ const manifest = parsed as MarketplaceManifest;
220
+
221
+ if (!manifest.name) {
222
+ return {
223
+ success: false,
224
+ error: 'marketplace.json missing required field: name'
225
+ };
226
+ }
227
+
228
+ if (!Array.isArray(manifest.plugins)) {
229
+ return {
230
+ success: false,
231
+ error: 'marketplace.json missing or invalid field: plugins (must be array)'
232
+ };
233
+ }
234
+
235
+ return { success: true, manifest };
236
+ }
237
+
238
+ /**
239
+ * Inspect a plugin directory to extract metadata and inventory
240
+ *
241
+ * @param pluginDir - Absolute path to the plugin directory
242
+ * @param marketplaceEntry - Optional marketplace entry for inline metadata fallback
243
+ * @returns Discovered plugin information
244
+ */
245
+ export function inspectPlugin(
246
+ pluginDir: string,
247
+ marketplaceEntry?: MarketplacePluginEntry
248
+ ): DiscoveredPlugin {
249
+ const result: DiscoveredPlugin = {
250
+ name: marketplaceEntry?.name || path.basename(pluginDir),
251
+ canonicalName: marketplaceEntry?.name || path.basename(pluginDir),
252
+ source: marketplaceEntry?.source || './',
253
+ resolvedPath: pluginDir,
254
+ status: 'ok',
255
+ manifestSource: 'derived',
256
+ inventory: {
257
+ skills: [],
258
+ agents: [],
259
+ commands: [],
260
+ mcpServers: {},
261
+ lspServers: {},
262
+ hooks: []
263
+ }
264
+ };
265
+
266
+ // Check if directory exists
267
+ if (!fs.existsSync(pluginDir)) {
268
+ result.status = 'error';
269
+ result.error = `Plugin directory not found: ${pluginDir}`;
270
+ return result;
271
+ }
272
+
273
+ // Try to read plugin.json from .claude-plugin/
274
+ const pluginJsonPath = path.join(pluginDir, '.claude-plugin', 'plugin.json');
275
+
276
+ if (fs.existsSync(pluginJsonPath)) {
277
+ try {
278
+ const content = fs.readFileSync(pluginJsonPath, 'utf-8');
279
+ const manifest = JSON.parse(content) as PluginManifest;
280
+
281
+ // Extract metadata from plugin.json
282
+ result.manifestSource = 'plugin.json';
283
+ result.description = manifest.description;
284
+ result.version = manifest.version;
285
+ result.author = manifest.author;
286
+ result.homepage = manifest.homepage;
287
+
288
+ if (manifest.mcpServers) {
289
+ result.inventory.mcpServers = manifest.mcpServers;
290
+ }
291
+ if (manifest.lspServers) {
292
+ result.inventory.lspServers = manifest.lspServers;
293
+ }
294
+ } catch (err) {
295
+ // Fall back to marketplace inline or derived
296
+ result.error = `Failed to parse plugin.json: ${err instanceof Error ? err.message : String(err)}`;
297
+ }
298
+ }
299
+
300
+ // If no plugin.json, use marketplace inline metadata
301
+ if (result.manifestSource === 'derived' && marketplaceEntry) {
302
+ result.manifestSource = 'marketplace-inline';
303
+ result.description = marketplaceEntry.description;
304
+ result.version = marketplaceEntry.version;
305
+ result.author = marketplaceEntry.author;
306
+ result.category = marketplaceEntry.category;
307
+ result.homepage = marketplaceEntry.homepage;
308
+
309
+ if (marketplaceEntry.mcpServers) {
310
+ result.inventory.mcpServers = marketplaceEntry.mcpServers;
311
+ }
312
+ if (marketplaceEntry.lspServers) {
313
+ result.inventory.lspServers = marketplaceEntry.lspServers;
314
+ }
315
+ }
316
+
317
+ // Try to read plugin.json in root (alternative location)
318
+ const altPluginJsonPath = path.join(pluginDir, 'plugin.json');
319
+ if (fs.existsSync(altPluginJsonPath) && result.manifestSource === 'derived') {
320
+ try {
321
+ const content = fs.readFileSync(altPluginJsonPath, 'utf-8');
322
+ const manifest = JSON.parse(content) as PluginManifest;
323
+
324
+ result.manifestSource = 'plugin.json';
325
+ if (!result.description && manifest.description) {
326
+ result.description = manifest.description;
327
+ }
328
+ if (!result.version && manifest.version) {
329
+ result.version = manifest.version;
330
+ }
331
+ if (!result.author && manifest.author) {
332
+ result.author = manifest.author;
333
+ }
334
+ } catch {
335
+ // Ignore parse errors for alternative location
336
+ }
337
+ }
338
+
339
+ // Inventory component directories
340
+ const skillsDir = path.join(pluginDir, 'skills');
341
+ if (fs.existsSync(skillsDir) && fs.statSync(skillsDir).isDirectory()) {
342
+ try {
343
+ result.inventory.skills = fs.readdirSync(skillsDir)
344
+ .filter(item => {
345
+ const itemPath = path.join(skillsDir, item);
346
+ return fs.statSync(itemPath).isDirectory() || item.endsWith('.md');
347
+ });
348
+ } catch {
349
+ // Ignore read errors
350
+ }
351
+ }
352
+
353
+ const agentsDir = path.join(pluginDir, 'agents');
354
+ if (fs.existsSync(agentsDir) && fs.statSync(agentsDir).isDirectory()) {
355
+ try {
356
+ result.inventory.agents = fs.readdirSync(agentsDir)
357
+ .filter(item => {
358
+ const itemPath = path.join(agentsDir, item);
359
+ return fs.statSync(itemPath).isDirectory() || item.endsWith('.md');
360
+ });
361
+ } catch {
362
+ // Ignore read errors
363
+ }
364
+ }
365
+
366
+ const commandsDir = path.join(pluginDir, 'commands');
367
+ if (fs.existsSync(commandsDir) && fs.statSync(commandsDir).isDirectory()) {
368
+ try {
369
+ result.inventory.commands = fs.readdirSync(commandsDir)
370
+ .filter(item => {
371
+ const itemPath = path.join(commandsDir, item);
372
+ return fs.statSync(itemPath).isDirectory() || item.endsWith('.md');
373
+ });
374
+ } catch {
375
+ // Ignore read errors
376
+ }
377
+ }
378
+
379
+ // Also check for hooks at root level (jamie-style uses 'hooks/', not '.claude-plugin/hooks')
380
+ const rootHooksDir = path.join(pluginDir, 'hooks');
381
+ if (fs.existsSync(rootHooksDir) && fs.statSync(rootHooksDir).isDirectory()) {
382
+ try {
383
+ const rootHooks = fs.readdirSync(rootHooksDir)
384
+ .filter(item => {
385
+ const itemPath = path.join(rootHooksDir, item);
386
+ return fs.statSync(itemPath).isDirectory() || item.endsWith('.md') || item.endsWith('.json');
387
+ });
388
+ const mergedHooks = [...(result.inventory.hooks || []), ...rootHooks];
389
+ result.inventory.hooks = Array.from(new Set(mergedHooks));
390
+ } catch {
391
+ // Ignore read errors
392
+ }
393
+ }
394
+
395
+ // Also check .claude-plugin/hooks (official-style)
396
+ const hooksDir = path.join(pluginDir, '.claude-plugin', 'hooks');
397
+ if (fs.existsSync(hooksDir) && fs.statSync(hooksDir).isDirectory()) {
398
+ try {
399
+ const pluginHooks = fs.readdirSync(hooksDir)
400
+ .filter(item => {
401
+ const itemPath = path.join(hooksDir, item);
402
+ return fs.statSync(itemPath).isDirectory() || item.endsWith('.md');
403
+ });
404
+ const mergedHooks = [...(result.inventory.hooks || []), ...pluginHooks];
405
+ result.inventory.hooks = Array.from(new Set(mergedHooks));
406
+ } catch {
407
+ // Ignore read errors
408
+ }
409
+ }
410
+
411
+ return result;
412
+ }
413
+
414
+ /**
415
+ * Discover all plugins in a marketplace repository
416
+ *
417
+ * @param repoRoot - Absolute or relative path to the marketplace repository
418
+ * @returns Marketplace discovery result with all plugins
419
+ */
420
+ export function discoverMarketplace(repoRoot: string): MarketplaceDiscoveryResult {
421
+ // Resolve to absolute path
422
+ const absoluteRepoRoot = path.resolve(repoRoot);
423
+
424
+ // Parse marketplace.json
425
+ const parseResult = parseMarketplaceJson(absoluteRepoRoot);
426
+
427
+ if (parseResult.success === false) {
428
+ return {
429
+ status: 'error',
430
+ error: parseResult.error,
431
+ marketplacePath: path.join(absoluteRepoRoot, '.claude-plugin', 'marketplace.json'),
432
+ marketplaceName: path.basename(absoluteRepoRoot),
433
+ pluginFormat: 'unknown',
434
+ plugins: [],
435
+ summary: { total: 0, ok: 0, error: 0 }
436
+ };
437
+ }
438
+
439
+ const manifest = parseResult.manifest;
440
+
441
+ // Determine plugin format based on structure
442
+ const pluginFormat: 'jamie-style' | 'official-style' | 'unknown' =
443
+ manifest.plugins.every(p => p.source && !p.description && !p.version && !p.lspServers)
444
+ ? 'jamie-style'
445
+ : manifest.plugins.every(p => p.source && (p.description || p.version || p.lspServers))
446
+ ? 'official-style'
447
+ : 'unknown';
448
+
449
+ // Discover each plugin
450
+ const plugins: DiscoveredPlugin[] = manifest.plugins.map(entry => {
451
+ const resolvedPath = resolvePluginRoot(absoluteRepoRoot, entry.source);
452
+
453
+ if (!resolvedPath) {
454
+ // External source - can't resolve locally
455
+ return {
456
+ name: entry.name,
457
+ canonicalName: entry.name,
458
+ source: entry.source,
459
+ resolvedPath: null,
460
+ status: 'ok',
461
+ manifestSource: 'marketplace-inline',
462
+ description: entry.description,
463
+ version: entry.version,
464
+ author: entry.author,
465
+ category: entry.category,
466
+ homepage: entry.homepage,
467
+ inventory: {
468
+ skills: [],
469
+ agents: [],
470
+ commands: [],
471
+ mcpServers: entry.mcpServers || {},
472
+ lspServers: entry.lspServers || {},
473
+ hooks: []
474
+ }
475
+ };
476
+ }
477
+
478
+ return inspectPlugin(resolvedPath, entry);
479
+ });
480
+
481
+ // Calculate summary
482
+ const summary = {
483
+ total: plugins.length,
484
+ ok: plugins.filter(p => p.status === 'ok').length,
485
+ error: plugins.filter(p => p.status === 'error').length
486
+ };
487
+
488
+ return {
489
+ status: summary.error > 0 ? 'error' : 'ok',
490
+ marketplacePath: path.join(absoluteRepoRoot, '.claude-plugin', 'marketplace.json'),
491
+ marketplaceName: manifest.name,
492
+ pluginFormat,
493
+ plugins,
494
+ summary
495
+ };
496
+ }
497
+
498
+ // ============================================================================
499
+ // Export all types and functions
500
+ // ============================================================================
501
+
502
+ export default {
503
+ parseMarketplaceJson,
504
+ inspectPlugin,
505
+ discoverMarketplace,
506
+ resolvePluginRoot
507
+ };
@@ -0,0 +1,87 @@
1
+ // @ts-ignore — @modelcontextprotocol/sdk types may not be in extensions tsconfig
2
+ import { Server } from '@modelcontextprotocol/sdk/server'
3
+ // @ts-ignore
4
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio'
5
+ // @ts-ignore
6
+ import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types'
7
+
8
+ interface McpTool {
9
+ name: string
10
+ description: string
11
+ parameters: Record<string, unknown>
12
+ execute(toolCallId: string, params: Record<string, unknown>, signal?: AbortSignal, onUpdate?: unknown): Promise<{ content: Array<{ type: string; text?: string; data?: string; mimeType?: string }> }>
13
+ }
14
+
15
+ export async function startMcpServer(options: {
16
+ tools: McpTool[]
17
+ version?: string
18
+ }): Promise<void> {
19
+ const { tools, version = '0.0.0' } = options
20
+
21
+ const toolMap = new Map<string, McpTool>()
22
+ for (const tool of tools) {
23
+ toolMap.set(tool.name, tool)
24
+ }
25
+
26
+ const server = new Server(
27
+ { name: 'gsd', version },
28
+ { capabilities: { tools: {} } },
29
+ )
30
+
31
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
32
+ return {
33
+ tools: tools.map((t) => ({
34
+ name: t.name,
35
+ description: t.description,
36
+ inputSchema: t.parameters,
37
+ })),
38
+ }
39
+ })
40
+
41
+ server.setRequestHandler(CallToolRequestSchema, async (request: any) => {
42
+ const { name, arguments: args } = request.params
43
+ const tool = toolMap.get(name)
44
+ if (!tool) {
45
+ return {
46
+ isError: true,
47
+ content: [{ type: 'text' as const, text: `Unknown tool: ${name}` }],
48
+ }
49
+ }
50
+
51
+ try {
52
+ const result = await tool.execute(
53
+ `mcp-${Date.now()}`,
54
+ args ?? {},
55
+ undefined,
56
+ undefined,
57
+ )
58
+
59
+ const content = result.content.map((block) => {
60
+ if (block.type === 'text') {
61
+ return { type: 'text' as const, text: block.text }
62
+ }
63
+ if (block.type === 'image') {
64
+ return {
65
+ type: 'image' as const,
66
+ data: block.data,
67
+ mimeType: block.mimeType,
68
+ }
69
+ }
70
+ return { type: 'text' as const, text: JSON.stringify(block) }
71
+ })
72
+
73
+ return { content }
74
+ } catch (err: unknown) {
75
+ const message = err instanceof Error ? err.message : String(err)
76
+ return {
77
+ isError: true,
78
+ content: [{ type: 'text' as const, text: message }],
79
+ }
80
+ }
81
+ })
82
+
83
+ const transport = new StdioServerTransport()
84
+ await server.connect(transport)
85
+
86
+ process.stderr.write(`[gsd] MCP server started (v${version})\n`)
87
+ }