gsd-pi 2.78.0-dev.aeeb2ca00 → 2.78.1-dev.84a383f51

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 (383) hide show
  1. package/README.md +7 -7
  2. package/dist/claude-cli-check.js +64 -37
  3. package/dist/cli-policy.d.ts +13 -0
  4. package/dist/cli-policy.js +17 -0
  5. package/dist/cli.js +95 -55
  6. package/dist/headless-query.d.ts +22 -0
  7. package/dist/headless-query.js +24 -4
  8. package/dist/headless.d.ts +10 -0
  9. package/dist/headless.js +16 -1
  10. package/dist/loader.js +7 -10
  11. package/dist/onboarding.d.ts +10 -0
  12. package/dist/onboarding.js +2 -2
  13. package/dist/provider-migrations.d.ts +2 -2
  14. package/dist/provider-migrations.js +5 -2
  15. package/dist/resource-loader.d.ts +5 -2
  16. package/dist/resource-loader.js +28 -5
  17. package/dist/resources/.managed-resources-content-hash +1 -0
  18. package/dist/resources/extensions/claude-code-cli/readiness.js +77 -45
  19. package/dist/resources/extensions/gsd/auto/loop.js +23 -0
  20. package/dist/resources/extensions/gsd/auto/phases.js +2 -2
  21. package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
  22. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  23. package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
  24. package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
  25. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  26. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
  27. package/dist/resources/extensions/gsd/auto-worktree.js +30 -0
  28. package/dist/resources/extensions/gsd/auto.js +14 -5
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
  30. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  32. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
  33. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +94 -31
  34. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
  35. package/dist/resources/extensions/gsd/bootstrap/system-context.js +34 -8
  36. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +38 -2
  37. package/dist/resources/extensions/gsd/commands/catalog.js +69 -5
  38. package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
  39. package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
  40. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
  41. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  42. package/dist/resources/extensions/gsd/docs/preferences-reference.md +4 -0
  43. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
  44. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  45. package/dist/resources/extensions/gsd/forensics.js +2 -2
  46. package/dist/resources/extensions/gsd/git-service.js +12 -5
  47. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  48. package/dist/resources/extensions/gsd/guided-flow.js +23 -23
  49. package/dist/resources/extensions/gsd/memory-store.js +66 -31
  50. package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
  51. package/dist/resources/extensions/gsd/model-router.js +114 -9
  52. package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
  53. package/dist/resources/extensions/gsd/preferences-models.js +91 -15
  54. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  55. package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
  56. package/dist/resources/extensions/gsd/preferences.js +5 -3
  57. package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
  58. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
  59. package/dist/resources/extensions/gsd/state.js +42 -0
  60. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  61. package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
  62. package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
  63. package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
  64. package/dist/resources/extensions/gsd/worktree-command.js +26 -46
  65. package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
  66. package/dist/resources/extensions/mcp-client/index.js +6 -3
  67. package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
  68. package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
  69. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  70. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  71. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  72. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  73. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  74. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  75. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  76. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  77. package/dist/rtk-shared.d.ts +3 -0
  78. package/dist/rtk-shared.js +17 -0
  79. package/dist/rtk.d.ts +2 -5
  80. package/dist/rtk.js +3 -20
  81. package/dist/runtime-checks.d.ts +27 -0
  82. package/dist/runtime-checks.js +38 -0
  83. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  84. package/dist/web/standalone/.next/BUILD_ID +1 -1
  85. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  86. package/dist/web/standalone/.next/build-manifest.json +3 -3
  87. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  88. package/dist/web/standalone/.next/react-loadable-manifest.json +44 -4
  89. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
  110. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/index.html +1 -1
  112. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  113. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  114. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  115. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  120. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  122. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  124. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  125. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  126. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  127. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
  128. package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
  129. package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
  130. package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
  131. package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
  132. package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
  133. package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
  134. package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
  135. package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
  136. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
  137. package/dist/web/standalone/.next/static/chunks/app/{page-5b113fd32bc2a1c3.js → page-9bf2e0c50fb2ca05.js} +1 -1
  138. package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
  139. package/dist/web/standalone/package.json +2 -1
  140. package/dist/worktree-status-banner.d.ts +1 -0
  141. package/dist/worktree-status-banner.js +132 -0
  142. package/package.json +1 -1
  143. package/packages/daemon/package.json +2 -2
  144. package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
  145. package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
  146. package/packages/mcp-server/dist/alias-telemetry.js +30 -0
  147. package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
  148. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  149. package/packages/mcp-server/dist/workflow-tools.js +74 -46
  150. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  151. package/packages/mcp-server/package.json +2 -2
  152. package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
  153. package/packages/mcp-server/src/alias-telemetry.ts +30 -0
  154. package/packages/mcp-server/src/workflow-tools.test.ts +26 -0
  155. package/packages/mcp-server/src/workflow-tools.ts +93 -58
  156. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  157. package/packages/native/package.json +1 -1
  158. package/packages/pi-agent-core/package.json +1 -1
  159. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  160. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
  161. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
  162. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
  163. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
  164. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  165. package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
  166. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  167. package/packages/pi-ai/dist/types.d.ts +13 -0
  168. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  169. package/packages/pi-ai/dist/types.js.map +1 -1
  170. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
  171. package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
  172. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
  173. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
  174. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
  175. package/packages/pi-ai/package.json +1 -1
  176. package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
  177. package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
  178. package/packages/pi-ai/src/types.ts +13 -0
  179. package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
  180. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
  181. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  182. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
  184. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/messages.js +4 -0
  187. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  188. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
  189. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  190. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
  191. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
  193. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
  195. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
  197. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
  199. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
  201. package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
  202. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
  203. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
  204. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
  205. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
  206. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
  207. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
  209. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
  211. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
  212. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
  213. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
  214. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
  215. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
  216. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
  217. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
  218. package/packages/pi-coding-agent/package.json +1 -1
  219. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
  220. package/packages/pi-coding-agent/src/core/messages.ts +4 -0
  221. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
  222. package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
  223. package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
  224. package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
  225. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
  226. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
  227. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
  228. package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
  229. package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
  230. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  231. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
  232. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  233. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
  234. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
  235. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
  236. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
  237. package/packages/pi-tui/package.json +1 -1
  238. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
  239. package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
  240. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  241. package/packages/rpc-client/package.json +1 -1
  242. package/pkg/package.json +1 -1
  243. package/src/resources/extensions/claude-code-cli/readiness.ts +78 -46
  244. package/src/resources/extensions/gsd/auto/loop.ts +24 -2
  245. package/src/resources/extensions/gsd/auto/phases.ts +3 -3
  246. package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
  247. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  248. package/src/resources/extensions/gsd/auto/types.ts +1 -0
  249. package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
  250. package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
  251. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  252. package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
  253. package/src/resources/extensions/gsd/auto-worktree.ts +38 -0
  254. package/src/resources/extensions/gsd/auto.ts +14 -4
  255. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
  256. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
  257. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  258. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
  259. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +102 -31
  260. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
  261. package/src/resources/extensions/gsd/bootstrap/system-context.ts +39 -8
  262. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +39 -11
  263. package/src/resources/extensions/gsd/commands/catalog.ts +75 -5
  264. package/src/resources/extensions/gsd/commands/handlers/core.ts +22 -1
  265. package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
  266. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
  267. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  268. package/src/resources/extensions/gsd/docs/preferences-reference.md +4 -0
  269. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
  270. package/src/resources/extensions/gsd/doctor-types.ts +3 -1
  271. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  272. package/src/resources/extensions/gsd/forensics.ts +2 -2
  273. package/src/resources/extensions/gsd/git-service.ts +13 -5
  274. package/src/resources/extensions/gsd/gsd-db.ts +12 -2
  275. package/src/resources/extensions/gsd/guided-flow.ts +25 -25
  276. package/src/resources/extensions/gsd/memory-store.ts +81 -28
  277. package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
  278. package/src/resources/extensions/gsd/model-router.ts +172 -9
  279. package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
  280. package/src/resources/extensions/gsd/preferences-models.ts +101 -15
  281. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  282. package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
  283. package/src/resources/extensions/gsd/preferences.ts +16 -2
  284. package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
  285. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
  286. package/src/resources/extensions/gsd/state.ts +42 -0
  287. package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  288. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
  289. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
  290. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +9 -5
  291. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
  292. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
  293. package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
  294. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
  295. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
  296. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
  297. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
  298. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
  299. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
  300. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
  301. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
  302. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
  303. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
  304. package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
  305. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
  306. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
  307. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
  308. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
  309. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
  310. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
  311. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
  312. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
  313. package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
  314. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
  315. package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
  316. package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
  317. package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
  318. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
  319. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +22 -0
  320. package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
  321. package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
  322. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
  323. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
  324. package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
  325. package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
  326. package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
  327. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
  328. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
  329. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
  330. package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
  331. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
  332. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
  333. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
  334. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
  335. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
  336. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
  337. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
  338. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
  339. package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
  340. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
  341. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
  342. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
  343. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
  344. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -0
  345. package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
  346. package/src/resources/extensions/gsd/unit-context-manifest.ts +8 -8
  347. package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
  348. package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
  349. package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
  350. package/src/resources/extensions/gsd/worktree-command.ts +31 -44
  351. package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
  352. package/src/resources/extensions/mcp-client/index.ts +6 -3
  353. package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
  354. package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
  355. package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
  356. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  357. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  358. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  359. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  360. package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  361. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  362. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  363. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
  364. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
  365. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
  366. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
  367. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
  368. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
  369. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
  370. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
  371. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
  372. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
  373. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
  374. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  375. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
  376. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
  377. package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
  378. package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
  379. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
  380. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
  381. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
  382. /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → UF5VF4F1tB0miEtJS7LyX}/_buildManifest.js +0 -0
  383. /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → UF5VF4F1tB0miEtJS7LyX}/_ssgManifest.js +0 -0
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Regression test for #4757 — readConfigs() must also read the global
3
+ * ~/.gsd/mcp.json (resolved as $GSD_HOME/mcp.json when GSD_HOME is set).
4
+ *
5
+ * Behaviour test against the exported getServerConfig — no source grep.
6
+ * The fixture is anchored via $GSD_HOME so the test never touches the
7
+ * developer's real ~/.gsd directory.
8
+ */
9
+
10
+ import test, { before, after } from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { writeFileSync, mkdtempSync, realpathSync, rmSync } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { join } from "node:path";
15
+
16
+ import { getServerConfig } from "../index.js";
17
+
18
+ let cwdDir: string;
19
+ let gsdHomeDir: string;
20
+ let originalCwd: string;
21
+ let originalGsdHome: string | undefined;
22
+
23
+ before(() => {
24
+ originalCwd = process.cwd();
25
+ originalGsdHome = process.env.GSD_HOME;
26
+
27
+ // realpathSync resolves any symlink in tmpdir() — on macOS /var → /private/var
28
+ // so process.cwd() after chdir matches what mkdtempSync returned.
29
+ cwdDir = realpathSync(mkdtempSync(join(tmpdir(), "mcp-cwd-")));
30
+ gsdHomeDir = realpathSync(mkdtempSync(join(tmpdir(), "mcp-gsdhome-")));
31
+
32
+ // Project-local fixture (also defines `shared-server` for the precedence test)
33
+ writeFileSync(
34
+ join(cwdDir, ".mcp.json"),
35
+ JSON.stringify({
36
+ mcpServers: {
37
+ "project-server": { command: "echo", args: ["proj"] },
38
+ "shared-server": { command: "echo", args: ["from-project"] },
39
+ },
40
+ }),
41
+ "utf-8",
42
+ );
43
+
44
+ // Global fixture rooted at $GSD_HOME (also defines `shared-server` to test
45
+ // that project-local takes precedence on name collision)
46
+ writeFileSync(
47
+ join(gsdHomeDir, "mcp.json"),
48
+ JSON.stringify({
49
+ mcpServers: {
50
+ "global-server": { command: "echo", args: ["glob"] },
51
+ "shared-server": { command: "echo", args: ["from-global"] },
52
+ },
53
+ }),
54
+ "utf-8",
55
+ );
56
+
57
+ process.chdir(cwdDir);
58
+ process.env.GSD_HOME = gsdHomeDir;
59
+ });
60
+
61
+ after(() => {
62
+ process.chdir(originalCwd);
63
+ if (originalGsdHome === undefined) delete process.env.GSD_HOME;
64
+ else process.env.GSD_HOME = originalGsdHome;
65
+ try { rmSync(cwdDir, { recursive: true, force: true }); } catch { /* best-effort */ }
66
+ try { rmSync(gsdHomeDir, { recursive: true, force: true }); } catch { /* best-effort */ }
67
+ });
68
+
69
+ test("#4757: getServerConfig resolves servers declared in $GSD_HOME/mcp.json", () => {
70
+ const cfg = getServerConfig("global-server");
71
+ assert.ok(cfg, "server defined in $GSD_HOME/mcp.json must resolve");
72
+ assert.equal(cfg?.name, "global-server");
73
+ assert.equal(cfg?.sourcePath, join(gsdHomeDir, "mcp.json"));
74
+ });
75
+
76
+ test("#4757: project-local servers still resolve when global config exists", () => {
77
+ const cfg = getServerConfig("project-server");
78
+ assert.ok(cfg, "project-local server must continue to resolve");
79
+ assert.equal(cfg?.sourcePath, join(cwdDir, ".mcp.json"));
80
+ });
81
+
82
+ test("#4757: project-local config wins on server-name collision", () => {
83
+ const cfg = getServerConfig("shared-server");
84
+ assert.ok(cfg, "shared server must resolve");
85
+ assert.equal(
86
+ cfg?.sourcePath,
87
+ join(cwdDir, ".mcp.json"),
88
+ "project-local config must take precedence over $GSD_HOME on name collision",
89
+ );
90
+ assert.deepEqual(cfg?.args, ["from-project"]);
91
+ });
@@ -221,41 +221,38 @@ function sendPrompt(description: string, result: RoundResult, pi: ExtensionAPI):
221
221
  : "";
222
222
 
223
223
  const docHints: string[] = [
224
- "- `~/.gsd/agent/docs/extending-pi/01-what-are-extensions.md` — capabilities overview",
225
- "- `~/.gsd/agent/docs/extending-pi/03-getting-started.md` — minimal extension, hot reload",
226
- "- `~/.gsd/agent/docs/extending-pi/08-extensioncontext-what-you-can-access.md` — ExtensionContext API",
227
- "- `~/.gsd/agent/docs/extending-pi/09-extensionapi-what-you-can-do.md` — ExtensionAPI: registration, messaging",
228
- "- `~/.gsd/agent/docs/extending-pi/22-key-rules-gotchas.md` — must-read rules before shipping",
224
+ "- `docs/extension-sdk/README.md` — overview, quick start, directory layout",
225
+ "- `docs/extension-sdk/api-reference.md` — ExtensionAPI and ExtensionContext surfaces",
226
+ "- `docs/extension-sdk/building-extensions.md` — tools, commands, events, UI, state",
227
+ "- `docs/extension-sdk/rules.md` — non-negotiable rules and gotchas",
229
228
  ];
230
229
 
231
230
  if (uiSelected.includes("custom component")) {
232
- docHints.push("- `~/.gsd/agent/docs/extending-pi/12-custom-ui-visual-components.md` — dialogs, widgets, overlays");
233
- docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/06-ctx-ui-custom-full-custom-components.md` — ctx.ui.custom() API");
234
- docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/07-built-in-components-the-building-blocks.md` — Text, Box, SelectList");
235
- docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/09-keyboard-input-how-to-handle-keys.md` — Key, matchesKey");
236
- docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/10-line-width-the-cardinal-rule.md` — truncation, width rules");
237
- docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/19-building-a-complete-component-step-by-step.md` — step-by-step guide");
238
- docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/21-common-mistakes-and-how-to-avoid-them.md` — pitfalls");
231
+ docHints.push("- `docs/extension-sdk/building-extensions.md#custom-components` — ctx.ui.custom() API");
232
+ docHints.push("- `docs/dev/pi-ui-tui/06-ctx-ui-custom-full-custom-components.md` — step-by-step component guide");
233
+ docHints.push("- `docs/dev/pi-ui-tui/07-built-in-components-the-building-blocks.md` — Text, Box, SelectList");
234
+ docHints.push("- `docs/dev/pi-ui-tui/09-keyboard-input-how-to-handle-keys.md` — Key, matchesKey");
235
+ docHints.push("- `docs/dev/pi-ui-tui/10-line-width-the-cardinal-rule.md` — truncation, width rules");
239
236
  } else if (uiSelected.includes("Dialogs")) {
240
- docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/04-built-in-dialog-methods.md` — select, confirm, input, editor");
237
+ docHints.push("- `docs/extension-sdk/building-extensions.md#built-in-dialogs` — select, confirm, input");
241
238
  } else if (uiSelected.includes("Status")) {
242
- docHints.push("- `~/.gsd/agent/docs/pi-ui-tui/05-persistent-ui-elements.md` — status, widgets, footer, header");
239
+ docHints.push("- `docs/extension-sdk/building-extensions.md#persistent-ui-elements` — status, widgets");
243
240
  }
244
241
 
245
242
  if (uiSelected.includes("tool") || result.answers["purpose"]) {
246
- docHints.push("- `~/.gsd/agent/docs/extending-pi/14-custom-rendering-controlling-what-the-user-sees.md` — renderCall / renderResult");
243
+ docHints.push("- `docs/dev/extending-pi/14-custom-rendering-controlling-what-the-user-sees.md` — renderCall / renderResult");
247
244
  }
248
245
 
249
246
  if (eventsSelected && !eventsSelected.includes("standalone")) {
250
- docHints.push("- `~/.gsd/agent/docs/extending-pi/07-events-the-nervous-system.md` — all events reference");
247
+ docHints.push("- `docs/dev/extending-pi/07-events-the-nervous-system.md` — all events reference");
251
248
  }
252
249
 
253
250
  if (eventsSelected.includes("context / prompt")) {
254
- docHints.push("- `~/.gsd/agent/docs/extending-pi/15-system-prompt-modification.md` — system prompt hooks");
251
+ docHints.push("- `docs/dev/extending-pi/15-system-prompt-modification.md` — system prompt hooks");
255
252
  }
256
253
 
257
254
  if (persistenceSelected.includes("session")) {
258
- docHints.push("- `~/.gsd/agent/docs/extending-pi/13-state-management-persistence.md` — pi.appendEntry, session state");
255
+ docHints.push("- `docs/extension-sdk/building-extensions.md#state-management` — state reconstruction, appendEntry");
259
256
  }
260
257
 
261
258
  const prompt = `Create a new pi extension based on this description:
@@ -270,13 +267,30 @@ ${docHints.join("\n")}
270
267
 
271
268
  ## Output
272
269
 
273
- Write the complete implementation as a single self-contained extension file:
274
-
275
- \`~/.gsd/agent/extensions/<kebab-case-name>.ts\`
276
-
277
- Then register it in the main extensions index:
270
+ Write the complete implementation as a directory-based extension:
271
+
272
+ \`~/.gsd/agent/extensions/<kebab-case-name>/index.ts\`
273
+ \`~/.gsd/agent/extensions/<kebab-case-name>/extension-manifest.json\`
274
+
275
+ The manifest must follow this format:
276
+ \`\`\`json
277
+ {
278
+ "id": "<kebab-case-name>",
279
+ "name": "<Human Name>",
280
+ "version": "1.0.0",
281
+ "description": "<one-line description>",
282
+ "tier": "community",
283
+ "requires": { "platform": ">=2.29.0" },
284
+ "provides": {
285
+ "tools": ["<tool_names_registered>"],
286
+ "commands": ["<command_names_registered>"],
287
+ "hooks": ["<event_names_subscribed>"],
288
+ "shortcuts": ["<shortcut_keys_registered>"]
289
+ }
290
+ }
291
+ \`\`\`
278
292
 
279
- \`~/.gsd/agent/extensions/index.ts\` import and call the new extension's default export alongside existing ones
293
+ Only include non-empty arrays in \`provides\`. See \`docs/extension-sdk/manifest-spec.md\` for the full spec.
280
294
 
281
295
  ## Rules you must follow exactly
282
296
 
@@ -19,8 +19,8 @@ Note: `~/.gsd/agent/extensions/` is reserved for bundled extensions synced from
19
19
  3. **Commands** — Give users slash commands (`pi.registerCommand()`). Users type `/mycommand`.
20
20
 
21
21
  **Non-negotiable rules:**
22
- - Use `StringEnum` from `@mariozechner/pi-ai` for string enum params (NOT `Type.Union`/`Type.Literal` — breaks Google's API)
23
- - Truncate tool output to 50KB / 2000 lines max (use `truncateHead`/`truncateTail` from `@mariozechner/pi-coding-agent`)
22
+ - Use `StringEnum` from `@gsd/pi-ai` for string enum params (NOT `Type.Union`/`Type.Literal` — breaks Google's API)
23
+ - Truncate tool output to 50KB / 2000 lines max (use `truncateHead`/`truncateTail` from `@gsd/pi-coding-agent`)
24
24
  - Store stateful tool state in `details` for branching support
25
25
  - Check `signal?.aborted` in long-running tool executions
26
26
  - Use `pi.exec()` not `child_process` for shell commands
@@ -34,10 +34,10 @@ Note: `~/.gsd/agent/extensions/` is reserved for bundled extensions synced from
34
34
 
35
35
  | Package | Purpose |
36
36
  |---------|---------|
37
- | `@mariozechner/pi-coding-agent` | `ExtensionAPI`, `ExtensionContext`, `Theme`, event types, tool utilities, `DynamicBorder`, `BorderedLoader`, `CustomEditor`, `highlightCode` |
37
+ | `@gsd/pi-coding-agent` | `ExtensionAPI`, `ExtensionContext`, `Theme`, event types, tool utilities, `DynamicBorder`, `BorderedLoader`, `CustomEditor`, `highlightCode` |
38
38
  | `@sinclair/typebox` | `Type.Object`, `Type.String`, `Type.Number`, `Type.Optional`, `Type.Boolean`, `Type.Array` |
39
- | `@mariozechner/pi-ai` | `StringEnum` (required for string enums), `Type` re-export |
40
- | `@mariozechner/pi-tui` | `Text`, `Box`, `Container`, `Spacer`, `Markdown`, `SelectList`, `Input`, `matchesKey`, `Key`, `truncateToWidth`, `visibleWidth` |
39
+ | `@gsd/pi-ai` | `StringEnum` (required for string enums), `Type` re-export |
40
+ | `@gsd/pi-tui` | `Text`, `Box`, `Container`, `Spacer`, `Markdown`, `SelectList`, `Input`, `matchesKey`, `Key`, `truncateToWidth`, `visibleWidth` |
41
41
  | Node.js built-ins | `node:fs`, `node:path`, `node:child_process`, etc. |
42
42
 
43
43
  </essential_principles>
@@ -65,6 +65,9 @@ All domain knowledge in `references/`:
65
65
  **Capabilities:** custom-tools.md, custom-commands.md, custom-ui.md, custom-rendering.md
66
66
  **Patterns:** state-management.md, system-prompt-modification.md, compaction-session-control.md
67
67
  **Infrastructure:** model-provider-management.md, remote-execution-overrides.md, packaging-distribution.md, mode-behavior.md
68
+ **Spec:** `docs/extension-sdk/manifest-spec.md` — manifest format, tiers, validation
69
+ **Testing:** `docs/extension-sdk/testing.md` — mock patterns, test conventions
70
+ **SDK:** `docs/extension-sdk/` — the authoritative GSD-2 extension guide
68
71
  **Gotchas:** key-rules-gotchas.md
69
72
  </reference_index>
70
73
 
@@ -78,6 +81,7 @@ All domain knowledge in `references/`:
78
81
 
79
82
  <success_criteria>
80
83
  Extension is complete when:
84
+ - `extension-manifest.json` exists with accurate `provides` listing all registered tools/commands/hooks/shortcuts
81
85
  - TypeScript compiles without errors (jiti handles this at runtime)
82
86
  - Extension loads on GSD startup or `/reload` without errors
83
87
  - Tools appear in the LLM's system prompt and are callable
@@ -19,7 +19,7 @@ pi.registerCommand("deploy", {
19
19
  Add tab-completion for command arguments:
20
20
 
21
21
  ```typescript
22
- import type { AutocompleteItem } from "@mariozechner/pi-tui";
22
+ import type { AutocompleteItem } from "@gsd/pi-tui";
23
23
 
24
24
  pi.registerCommand("deploy", {
25
25
  description: "Deploy to an environment",
@@ -6,8 +6,8 @@ Custom rendering for tools and messages — control how they appear in the TUI.
6
6
  Tools can provide `renderCall` (how the call looks) and `renderResult` (how the result looks):
7
7
 
8
8
  ```typescript
9
- import { Text } from "@mariozechner/pi-tui";
10
- import { keyHint } from "@mariozechner/pi-coding-agent";
9
+ import { Text } from "@gsd/pi-tui";
10
+ import { keyHint } from "@gsd/pi-coding-agent";
11
11
 
12
12
  pi.registerTool({
13
13
  name: "my_tool",
@@ -54,7 +54,7 @@ If you omit `renderCall`/`renderResult`, the built-in renderer is used. Useful f
54
54
  Key hint helpers for showing keybinding info in render output:
55
55
 
56
56
  ```typescript
57
- import { keyHint, appKeyHint, editorKey, rawKeyHint } from "@mariozechner/pi-coding-agent";
57
+ import { keyHint, appKeyHint, editorKey, rawKeyHint } from "@gsd/pi-coding-agent";
58
58
 
59
59
  // Editor action hint (respects user keybinding config)
60
60
  keyHint("expandTools", "to expand") // e.g., "Ctrl+O to expand"
@@ -69,7 +69,7 @@ rawKeyHint("Ctrl+O", "to expand")
69
69
  Register a renderer for custom message types:
70
70
 
71
71
  ```typescript
72
- import { Text } from "@mariozechner/pi-tui";
72
+ import { Text } from "@gsd/pi-tui";
73
73
 
74
74
  pi.registerMessageRenderer("my-extension", (message, options, theme) => {
75
75
  const { expanded } = options;
@@ -92,7 +92,7 @@ pi.sendMessage({
92
92
 
93
93
  <syntax_highlighting>
94
94
  ```typescript
95
- import { highlightCode, getLanguageFromPath } from "@mariozechner/pi-coding-agent";
95
+ import { highlightCode, getLanguageFromPath } from "@gsd/pi-coding-agent";
96
96
 
97
97
  const lang = getLanguageFromPath("/path/to/file.rs"); // "rust"
98
98
  const highlighted = highlightCode(code, lang, theme);
@@ -5,7 +5,7 @@ Complete custom tools reference — registration, parameters, execution, output
5
5
  <registration>
6
6
  ```typescript
7
7
  import { Type } from "@sinclair/typebox";
8
- import { StringEnum } from "@mariozechner/pi-ai";
8
+ import { StringEnum } from "@gsd/pi-ai";
9
9
 
10
10
  pi.registerTool({
11
11
  name: "my_tool", // Unique identifier (snake_case)
@@ -60,7 +60,7 @@ pi.registerTool({
60
60
  **⚠️ MUST use `StringEnum` for string enum parameters:**
61
61
 
62
62
  ```typescript
63
- import { StringEnum } from "@mariozechner/pi-ai";
63
+ import { StringEnum } from "@gsd/pi-ai";
64
64
 
65
65
  // ✅ Correct — works with all providers including Google
66
66
  action: StringEnum(["list", "add", "remove"] as const)
@@ -77,7 +77,7 @@ Tools MUST truncate output to avoid context overflow. Built-in limit: 50KB / 200
77
77
  import {
78
78
  truncateHead, truncateTail, formatSize,
79
79
  DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES,
80
- } from "@mariozechner/pi-coding-agent";
80
+ } from "@gsd/pi-coding-agent";
81
81
 
82
82
  async execute(toolCallId, params, signal, onUpdate, ctx) {
83
83
  const output = await runCommand();
@@ -129,7 +129,7 @@ Use `pi.setActiveTools(names)` to enable/disable tools at runtime.
129
129
  Register a tool with the same name as a built-in (`read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`) to override it. **Must match exact result shape including `details` type.**
130
130
 
131
131
  ```typescript
132
- import { createReadTool } from "@mariozechner/pi-coding-agent";
132
+ import { createReadTool } from "@gsd/pi-coding-agent";
133
133
 
134
134
  pi.registerTool({
135
135
  name: "read",
@@ -277,7 +277,7 @@ bottom-left bottom-center bottom-right
277
277
  Replace the main input editor permanently:
278
278
 
279
279
  ```typescript
280
- import { CustomEditor } from "@mariozechner/pi-coding-agent";
280
+ import { CustomEditor } from "@gsd/pi-coding-agent";
281
281
 
282
282
  class VimEditor extends CustomEditor {
283
283
  private mode: "normal" | "insert" = "insert";
@@ -307,7 +307,7 @@ ctx.ui.setEditorComponent(undefined); // Restore default
307
307
  </custom_editor>
308
308
 
309
309
  <built_in_components>
310
- **From `@mariozechner/pi-tui`:**
310
+ **From `@gsd/pi-tui`:**
311
311
 
312
312
  | Component | Constructor | Purpose |
313
313
  |-----------|-------------|---------|
@@ -352,7 +352,7 @@ const settings = new SettingsList(items, 15, getSettingsListTheme(),
352
352
  );
353
353
  ```
354
354
 
355
- **From `@mariozechner/pi-coding-agent`:**
355
+ **From `@gsd/pi-coding-agent`:**
356
356
 
357
357
  | Component | Constructor | Purpose |
358
358
  |-----------|-------------|---------|
@@ -363,7 +363,7 @@ const settings = new SettingsList(items, 15, getSettingsListTheme(),
363
363
 
364
364
  <keyboard_input>
365
365
  ```typescript
366
- import { matchesKey, Key } from "@mariozechner/pi-tui";
366
+ import { matchesKey, Key } from "@gsd/pi-tui";
367
367
 
368
368
  handleInput(data: string) {
369
369
  // Basic keys
@@ -403,7 +403,7 @@ handleInput(data: string) {
403
403
  **Cardinal rule: each line from render() must not exceed `width` visible characters.**
404
404
 
405
405
  ```typescript
406
- import { visibleWidth, truncateToWidth, wrapTextWithAnsi } from "@mariozechner/pi-tui";
406
+ import { visibleWidth, truncateToWidth, wrapTextWithAnsi } from "@gsd/pi-tui";
407
407
 
408
408
  visibleWidth("\x1b[32mHello\x1b[0m"); // Returns 5 (ignores ANSI codes)
409
409
  truncateToWidth("Very long text here", 10); // "Very lo..."
@@ -470,7 +470,7 @@ Always use theme from callback params, never import directly.
470
470
 
471
471
  **Syntax highlighting:**
472
472
  ```typescript
473
- import { highlightCode, getLanguageFromPath } from "@mariozechner/pi-coding-agent";
473
+ import { highlightCode, getLanguageFromPath } from "@gsd/pi-coding-agent";
474
474
  const lang = getLanguageFromPath("/file.rs"); // "rust"
475
475
  const highlighted = highlightCode(code, lang, theme);
476
476
  ```
@@ -47,7 +47,7 @@ pi.on("before_agent_start", async (event, ctx) => {
47
47
 
48
48
  **tool_call** — Fired before tool executes. Can block.
49
49
  ```typescript
50
- import { isToolCallEventType } from "@mariozechner/pi-coding-agent";
50
+ import { isToolCallEventType } from "@gsd/pi-coding-agent";
51
51
 
52
52
  pi.on("tool_call", async (event, ctx) => {
53
53
  if (isToolCallEventType("bash", event)) {
@@ -61,7 +61,7 @@ pi.on("tool_call", async (event, ctx) => {
61
61
 
62
62
  **tool_result** — Fired after tool executes. Can modify result. Handlers chain like middleware.
63
63
  ```typescript
64
- import { isToolResultEventType } from "@mariozechner/pi-coding-agent";
64
+ import { isToolResultEventType } from "@gsd/pi-coding-agent";
65
65
 
66
66
  pi.on("tool_result", async (event, ctx) => {
67
67
  if (isToolResultEventType("bash", event)) {
@@ -105,7 +105,7 @@ pi.on("model_select", async (event, ctx) => {
105
105
  Built-in type guards for tool events:
106
106
 
107
107
  ```typescript
108
- import { isToolCallEventType, isToolResultEventType } from "@mariozechner/pi-coding-agent";
108
+ import { isToolCallEventType, isToolResultEventType } from "@gsd/pi-coding-agent";
109
109
 
110
110
  // Tool calls — narrows event.input type
111
111
  if (isToolCallEventType("bash", event)) { /* event.input: { command, timeout? } */ }
@@ -39,7 +39,7 @@ If no `pi` manifest exists, auto-discovers:
39
39
  </convention_directories>
40
40
 
41
41
  <dependencies>
42
- - List `@mariozechner/pi-ai`, `@mariozechner/pi-coding-agent`, `@mariozechner/pi-tui`, `@sinclair/typebox` in `peerDependencies` with `"*"` — they're bundled by the runtime.
42
+ - List `@gsd/pi-ai`, `@gsd/pi-coding-agent`, `@gsd/pi-tui`, `@sinclair/typebox` in `peerDependencies` with `"*"` — they're bundled by the runtime.
43
43
  - Other npm deps go in `dependencies`. The runtime runs `npm install` on package installation.
44
44
  </dependencies>
45
45
 
@@ -6,7 +6,7 @@ Remote execution via pluggable operations, spawnHook for bash, and tool override
6
6
  Built-in tools support pluggable operations for SSH, containers, etc.:
7
7
 
8
8
  ```typescript
9
- import { createReadTool, createBashTool, createWriteTool } from "@mariozechner/pi-coding-agent";
9
+ import { createReadTool, createBashTool, createWriteTool } from "@gsd/pi-coding-agent";
10
10
 
11
11
  // Create tool with custom remote operations
12
12
  const remoteBash = createBashTool(cwd, {
@@ -37,7 +37,7 @@ const bashTool = createBashTool(cwd, {
37
37
  Full SSH pattern with flag-based switching:
38
38
 
39
39
  ```typescript
40
- import { createBashTool, type ExtensionAPI } from "@mariozechner/pi-coding-agent";
40
+ import { createBashTool, type ExtensionAPI } from "@gsd/pi-coding-agent";
41
41
 
42
42
  export default function (pi: ExtensionAPI) {
43
43
  pi.registerFlag("ssh", { description: "SSH target", type: "string" });
@@ -65,7 +65,7 @@ export default function (pi: ExtensionAPI) {
65
65
  Override built-in tools for logging/access control — omit renderCall/renderResult to keep built-in rendering:
66
66
 
67
67
  ```typescript
68
- import { createReadTool } from "@mariozechner/pi-coding-agent";
68
+ import { createReadTool } from "@gsd/pi-coding-agent";
69
69
  import { Type } from "@sinclair/typebox";
70
70
 
71
71
  pi.registerTool({
@@ -5,9 +5,9 @@
5
5
  * {{CAPABILITIES_LIST}}
6
6
  */
7
7
 
8
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
8
+ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
9
9
  import { Type } from "@sinclair/typebox";
10
- import { StringEnum } from "@mariozechner/pi-ai";
10
+ import { StringEnum } from "@gsd/pi-ai";
11
11
 
12
12
  export default function (pi: ExtensionAPI) {
13
13
  // === Events ===
@@ -4,10 +4,10 @@
4
4
  * State is stored in tool result details for proper branching support.
5
5
  */
6
6
 
7
- import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
7
+ import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
8
8
  import { Type } from "@sinclair/typebox";
9
- import { StringEnum } from "@mariozechner/pi-ai";
10
- import { Text, truncateToWidth, matchesKey, Key } from "@mariozechner/pi-tui";
9
+ import { StringEnum } from "@gsd/pi-ai";
10
+ import { Text, truncateToWidth, matchesKey, Key } from "@gsd/pi-tui";
11
11
 
12
12
  interface {{ItemType}} {
13
13
  id: number;
@@ -0,0 +1,58 @@
1
+ // GSD-2 — Extension template import path validation
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
3
+
4
+ import { describe, it } from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { readFileSync, readdirSync, statSync } from "node:fs";
7
+ import { join, dirname, relative } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+ const skillRoot = join(__dirname, "..");
12
+
13
+ function walk(dir: string): string[] {
14
+ const out: string[] = [];
15
+ for (const entry of readdirSync(dir)) {
16
+ const full = join(dir, entry);
17
+ if (statSync(full).isDirectory()) {
18
+ out.push(...walk(full));
19
+ } else {
20
+ out.push(full);
21
+ }
22
+ }
23
+ return out;
24
+ }
25
+
26
+ describe("extension templates use @gsd/* imports", () => {
27
+ const templates = ["extension-skeleton.ts", "stateful-tool-skeleton.ts"];
28
+
29
+ for (const template of templates) {
30
+ it(`${template} uses @gsd/pi-coding-agent (not @mariozechner)`, () => {
31
+ const content = readFileSync(join(__dirname, template), "utf-8");
32
+ assert.ok(content.includes("@gsd/pi-coding-agent"), `Expected @gsd/pi-coding-agent import in ${template}`);
33
+ assert.ok(!content.includes("@mariozechner/"), `Found stale @mariozechner/ import in ${template}`);
34
+ });
35
+ }
36
+
37
+ it("extension-skeleton.ts uses @gsd/pi-ai for StringEnum", () => {
38
+ const content = readFileSync(join(__dirname, "extension-skeleton.ts"), "utf-8");
39
+ assert.ok(content.includes("@gsd/pi-ai"), "Expected @gsd/pi-ai import");
40
+ });
41
+
42
+ it("stateful-tool-skeleton.ts uses @gsd/pi-tui", () => {
43
+ const content = readFileSync(join(__dirname, "stateful-tool-skeleton.ts"), "utf-8");
44
+ assert.ok(content.includes("@gsd/pi-tui"), "Expected @gsd/pi-tui import");
45
+ });
46
+
47
+ it("no @mariozechner/ references anywhere in create-gsd-extension/", () => {
48
+ const offenders: string[] = [];
49
+ for (const file of walk(skillRoot)) {
50
+ if (file.endsWith("templates.test.ts")) continue;
51
+ const content = readFileSync(file, "utf-8");
52
+ if (content.includes("@mariozechner/")) {
53
+ offenders.push(relative(skillRoot, file));
54
+ }
55
+ }
56
+ assert.deepEqual(offenders, [], `Stale @mariozechner/ references found in: ${offenders.join(", ")}`);
57
+ });
58
+ });
@@ -34,22 +34,19 @@ Identify what the extension needs from the user's description:
34
34
 
35
35
  ## Step 3: Choose Extension Structure
36
36
 
37
- **Single file** — for small extensions (1-2 tools/commands, simple hooks):
38
- ```
39
- ~/.pi/agent/extensions/my-extension.ts
40
- ```
41
-
42
- **Directory with index.ts** — for multi-file extensions:
37
+ **Directory with index.ts** — the standard pattern for all extensions:
43
38
  ```
44
39
  ~/.pi/agent/extensions/my-extension/
45
- ├── index.ts
46
- ├── tools.ts
47
- └── utils.ts
40
+ ├── extension-manifest.json # Required — declares capabilities
41
+ ├── index.ts # Entry point (must export default function)
42
+ ├── tools.ts # Optional — tool implementations
43
+ └── utils.ts # Optional — shared utilities
48
44
  ```
49
45
 
50
46
  **Package with dependencies** — when npm packages are needed:
51
47
  ```
52
48
  ~/.pi/agent/extensions/my-extension/
49
+ ├── extension-manifest.json
53
50
  ├── package.json
54
51
  ├── src/index.ts
55
52
  └── node_modules/
@@ -64,12 +61,34 @@ For packages, `package.json` needs:
64
61
  }
65
62
  ```
66
63
 
64
+ ## Step 3b: Create the Extension Manifest
65
+
66
+ Every extension must include an `extension-manifest.json`:
67
+
68
+ ```json
69
+ {
70
+ "id": "my-extension",
71
+ "name": "My Extension",
72
+ "version": "1.0.0",
73
+ "description": "What this extension does in one line",
74
+ "tier": "community",
75
+ "requires": { "platform": ">=2.29.0" },
76
+ "provides": {
77
+ "tools": ["my_tool"],
78
+ "commands": ["mycommand"],
79
+ "hooks": ["session_start"]
80
+ }
81
+ }
82
+ ```
83
+
84
+ Only include non-empty arrays in `provides`. See `docs/extension-sdk/manifest-spec.md` for the full spec.
85
+
67
86
  ## Step 4: Write the Extension
68
87
 
69
88
  Start with the skeleton:
70
89
 
71
90
  ```typescript
72
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
91
+ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
73
92
 
74
93
  export default function (pi: ExtensionAPI) {
75
94
  // Register events, tools, commands here
@@ -81,7 +100,7 @@ Then add capabilities based on Step 2. Reference the appropriate reference files
81
100
  **Tool registration pattern:**
82
101
  ```typescript
83
102
  import { Type } from "@sinclair/typebox";
84
- import { StringEnum } from "@mariozechner/pi-ai";
103
+ import { StringEnum } from "@gsd/pi-ai";
85
104
 
86
105
  pi.registerTool({
87
106
  name: "my_tool",
@@ -144,7 +163,8 @@ Fix issues, add features, refine. Use `/reload` for hot-reload during developmen
144
163
 
145
164
  <success_criteria>
146
165
  Extension creation is complete when:
147
- - [ ] Extension file(s) written to correct location
166
+ - [ ] Extension directory created with index.ts and extension-manifest.json
167
+ - [ ] Manifest `provides` accurately lists all registered tools, commands, hooks, shortcuts
148
168
  - [ ] All imports resolve (TypeBox, pi-ai, pi-coding-agent, pi-tui as needed)
149
169
  - [ ] Tools use `StringEnum` for string enums (not `Type.Union`/`Type.Literal`)
150
170
  - [ ] Tool output is truncated if variable-length