gsd-pi 2.41.0 → 2.42.0-dev.1df898f

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 (494) hide show
  1. package/README.md +92 -29
  2. package/dist/cli-web-branch.d.ts +6 -0
  3. package/dist/cli-web-branch.js +17 -0
  4. package/dist/cli.js +18 -3
  5. package/dist/loader.js +3 -1
  6. package/dist/onboarding.js +2 -1
  7. package/dist/resource-loader.js +39 -6
  8. package/dist/resources/extensions/async-jobs/async-bash-tool.js +52 -4
  9. package/dist/resources/extensions/async-jobs/await-tool.js +5 -0
  10. package/dist/resources/extensions/async-jobs/index.js +2 -0
  11. package/dist/resources/extensions/gsd/auto/loop.js +89 -1
  12. package/dist/resources/extensions/gsd/auto/phases.js +29 -13
  13. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  14. package/dist/resources/extensions/gsd/auto-dashboard.js +8 -2
  15. package/dist/resources/extensions/gsd/auto-dispatch.js +19 -2
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -0
  17. package/dist/resources/extensions/gsd/auto-prompts.js +3 -16
  18. package/dist/resources/extensions/gsd/auto-recovery.js +12 -4
  19. package/dist/resources/extensions/gsd/auto-start.js +16 -14
  20. package/dist/resources/extensions/gsd/auto-worktree.js +147 -13
  21. package/dist/resources/extensions/gsd/auto.js +64 -2
  22. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +199 -164
  23. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +62 -0
  24. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +25 -3
  26. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +7 -2
  27. package/dist/resources/extensions/gsd/commands/catalog.js +40 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
  29. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  30. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +146 -0
  31. package/dist/resources/extensions/gsd/context-injector.js +74 -0
  32. package/dist/resources/extensions/gsd/context-store.js +4 -3
  33. package/dist/resources/extensions/gsd/custom-execution-policy.js +47 -0
  34. package/dist/resources/extensions/gsd/custom-verification.js +145 -0
  35. package/dist/resources/extensions/gsd/custom-workflow-engine.js +164 -0
  36. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -0
  37. package/dist/resources/extensions/gsd/db-writer.js +5 -2
  38. package/dist/resources/extensions/gsd/definition-loader.js +352 -0
  39. package/dist/resources/extensions/gsd/detection.js +20 -1
  40. package/dist/resources/extensions/gsd/dev-execution-policy.js +24 -0
  41. package/dist/resources/extensions/gsd/dev-workflow-engine.js +82 -0
  42. package/dist/resources/extensions/gsd/doctor-checks.js +31 -1
  43. package/dist/resources/extensions/gsd/doctor-providers.js +10 -0
  44. package/dist/resources/extensions/gsd/doctor.js +11 -1
  45. package/dist/resources/extensions/gsd/engine-resolver.js +40 -0
  46. package/dist/resources/extensions/gsd/engine-types.js +8 -0
  47. package/dist/resources/extensions/gsd/execution-policy.js +8 -0
  48. package/dist/resources/extensions/gsd/exit-command.js +12 -2
  49. package/dist/resources/extensions/gsd/export.js +9 -13
  50. package/dist/resources/extensions/gsd/extension-manifest.json +2 -2
  51. package/dist/resources/extensions/gsd/files.js +28 -11
  52. package/dist/resources/extensions/gsd/forensics.js +94 -3
  53. package/dist/resources/extensions/gsd/git-constants.js +1 -0
  54. package/dist/resources/extensions/gsd/git-service.js +6 -2
  55. package/dist/resources/extensions/gsd/graph.js +225 -0
  56. package/dist/resources/extensions/gsd/gsd-db.js +25 -8
  57. package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
  58. package/dist/resources/extensions/gsd/guided-flow.js +7 -3
  59. package/dist/resources/extensions/gsd/journal.js +85 -0
  60. package/dist/resources/extensions/gsd/md-importer.js +5 -0
  61. package/dist/resources/extensions/gsd/milestone-ids.js +1 -1
  62. package/dist/resources/extensions/gsd/native-git-bridge.js +3 -2
  63. package/dist/resources/extensions/gsd/post-unit-hooks.js +24 -412
  64. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  65. package/dist/resources/extensions/gsd/preferences.js +60 -8
  66. package/dist/resources/extensions/gsd/prompt-loader.js +34 -4
  67. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  68. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  69. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
  71. package/dist/resources/extensions/gsd/prompts/queue.md +1 -1
  72. package/dist/resources/extensions/gsd/repo-identity.js +92 -7
  73. package/dist/resources/extensions/gsd/rule-registry.js +489 -0
  74. package/dist/resources/extensions/gsd/rule-types.js +6 -0
  75. package/dist/resources/extensions/gsd/run-manager.js +134 -0
  76. package/dist/resources/extensions/gsd/service-tier.js +147 -0
  77. package/dist/resources/extensions/gsd/session-lock.js +2 -2
  78. package/dist/resources/extensions/gsd/structured-data-formatter.js +2 -1
  79. package/dist/resources/extensions/gsd/templates/decisions.md +2 -2
  80. package/dist/resources/extensions/gsd/workflow-engine.js +7 -0
  81. package/dist/resources/extensions/gsd/workflow-templates.js +13 -1
  82. package/dist/resources/extensions/gsd/worktree-manager.js +20 -6
  83. package/dist/resources/extensions/gsd/worktree-resolver.js +21 -4
  84. package/dist/resources/extensions/gsd/worktree.js +2 -2
  85. package/dist/resources/extensions/mcp-client/index.js +2 -1
  86. package/dist/resources/extensions/search-the-web/tool-search.js +3 -3
  87. package/dist/resources/extensions/subagent/index.js +7 -3
  88. package/dist/resources/extensions/voice/index.js +4 -4
  89. package/dist/resources/skills/create-workflow/SKILL.md +103 -0
  90. package/dist/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  91. package/dist/resources/skills/create-workflow/references/verification-policies.md +76 -0
  92. package/dist/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  93. package/dist/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  94. package/dist/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  95. package/dist/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  96. package/dist/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  97. package/dist/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  98. package/dist/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  99. package/dist/web/standalone/.next/BUILD_ID +1 -1
  100. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  101. package/dist/web/standalone/.next/build-manifest.json +4 -4
  102. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  103. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  104. package/dist/web/standalone/.next/required-server-files.json +3 -3
  105. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  106. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  108. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  116. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  170. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  176. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  190. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  192. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  194. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/index.html +1 -1
  204. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  205. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  206. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  207. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  208. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  209. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  210. package/dist/web/standalone/.next/server/app/page.js +2 -2
  211. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  213. package/dist/web/standalone/.next/server/chunks/229.js +3 -3
  214. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  215. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/middleware.js +2 -2
  218. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  219. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  220. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  221. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  222. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  223. package/dist/web/standalone/.next/static/chunks/4024.c195dc1fdd2adbea.js +9 -0
  224. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  226. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  227. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  228. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  229. package/dist/web/standalone/.next/static/chunks/{webpack-9afaaebf6042a1d7.js → webpack-fa307370fcf9fb2c.js} +1 -1
  230. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  231. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  232. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  233. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  234. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  235. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  236. package/dist/web/standalone/server.js +1 -1
  237. package/dist/web-mode.d.ts +4 -0
  238. package/dist/web-mode.js +69 -11
  239. package/package.json +1 -1
  240. package/packages/native/src/__tests__/text.test.mjs +33 -0
  241. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  242. package/packages/pi-agent-core/dist/agent.js +2 -0
  243. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  244. package/packages/pi-agent-core/dist/types.d.ts +6 -0
  245. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  246. package/packages/pi-agent-core/dist/types.js.map +1 -1
  247. package/packages/pi-agent-core/src/agent.test.ts +53 -0
  248. package/packages/pi-agent-core/src/agent.ts +3 -0
  249. package/packages/pi-agent-core/src/types.ts +6 -0
  250. package/packages/pi-agent-core/tsconfig.json +1 -1
  251. package/packages/pi-ai/dist/models.d.ts +5 -3
  252. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  253. package/packages/pi-ai/dist/models.generated.d.ts +801 -1468
  254. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  255. package/packages/pi-ai/dist/models.generated.js +1135 -1588
  256. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  257. package/packages/pi-ai/dist/models.js.map +1 -1
  258. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  259. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +60 -2
  260. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  261. package/packages/pi-ai/scripts/generate-models.ts +1543 -0
  262. package/packages/pi-ai/src/models.generated.ts +1140 -1593
  263. package/packages/pi-ai/src/models.ts +7 -4
  264. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +74 -2
  265. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -1
  267. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +7 -0
  269. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/auth-storage.js +29 -2
  271. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +60 -0
  273. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  274. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +3 -1
  275. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  278. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  280. package/packages/pi-coding-agent/dist/core/lsp/client.js +23 -0
  281. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  282. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -0
  284. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/package-manager.d.ts +6 -0
  286. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/package-manager.js +63 -11
  288. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +9 -0
  290. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/resource-loader.js +20 -6
  292. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  294. package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -5
  295. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js +3 -0
  298. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +9 -6
  301. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  303. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +10 -7
  304. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  305. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +34 -10
  307. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  308. package/packages/pi-coding-agent/package.json +1 -1
  309. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -1
  310. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +68 -0
  311. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -2
  312. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +4 -2
  313. package/packages/pi-coding-agent/src/core/extensions/loader.ts +18 -0
  314. package/packages/pi-coding-agent/src/core/lsp/client.ts +29 -0
  315. package/packages/pi-coding-agent/src/core/model-registry.ts +3 -0
  316. package/packages/pi-coding-agent/src/core/package-manager.ts +99 -58
  317. package/packages/pi-coding-agent/src/core/resource-loader.ts +24 -6
  318. package/packages/pi-coding-agent/src/core/system-prompt.ts +6 -5
  319. package/packages/pi-coding-agent/src/modes/interactive/components/extension-editor.ts +3 -0
  320. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -6
  321. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +11 -7
  322. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +36 -11
  323. package/pkg/package.json +1 -1
  324. package/src/resources/extensions/async-jobs/async-bash-timeout.test.ts +122 -0
  325. package/src/resources/extensions/async-jobs/async-bash-tool.ts +40 -4
  326. package/src/resources/extensions/async-jobs/await-tool.test.ts +47 -0
  327. package/src/resources/extensions/async-jobs/await-tool.ts +5 -0
  328. package/src/resources/extensions/async-jobs/index.ts +1 -0
  329. package/src/resources/extensions/async-jobs/job-manager.ts +2 -0
  330. package/src/resources/extensions/gsd/auto/loop-deps.ts +5 -2
  331. package/src/resources/extensions/gsd/auto/loop.ts +101 -1
  332. package/src/resources/extensions/gsd/auto/phases.ts +31 -13
  333. package/src/resources/extensions/gsd/auto/session.ts +6 -0
  334. package/src/resources/extensions/gsd/auto/types.ts +4 -0
  335. package/src/resources/extensions/gsd/auto-dashboard.ts +9 -2
  336. package/src/resources/extensions/gsd/auto-dispatch.ts +25 -5
  337. package/src/resources/extensions/gsd/auto-post-unit.ts +8 -0
  338. package/src/resources/extensions/gsd/auto-prompts.ts +2 -18
  339. package/src/resources/extensions/gsd/auto-recovery.ts +12 -4
  340. package/src/resources/extensions/gsd/auto-start.ts +15 -13
  341. package/src/resources/extensions/gsd/auto-worktree.ts +162 -18
  342. package/src/resources/extensions/gsd/auto.ts +71 -2
  343. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +209 -162
  344. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +62 -0
  345. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  346. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +25 -4
  347. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +9 -2
  348. package/src/resources/extensions/gsd/commands/catalog.ts +40 -1
  349. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
  350. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  351. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +164 -0
  352. package/src/resources/extensions/gsd/context-injector.ts +100 -0
  353. package/src/resources/extensions/gsd/context-store.ts +4 -3
  354. package/src/resources/extensions/gsd/custom-execution-policy.ts +73 -0
  355. package/src/resources/extensions/gsd/custom-verification.ts +180 -0
  356. package/src/resources/extensions/gsd/custom-workflow-engine.ts +216 -0
  357. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -0
  358. package/src/resources/extensions/gsd/db-writer.ts +6 -2
  359. package/src/resources/extensions/gsd/definition-loader.ts +462 -0
  360. package/src/resources/extensions/gsd/detection.ts +20 -1
  361. package/src/resources/extensions/gsd/dev-execution-policy.ts +51 -0
  362. package/src/resources/extensions/gsd/dev-workflow-engine.ts +110 -0
  363. package/src/resources/extensions/gsd/doctor-checks.ts +32 -1
  364. package/src/resources/extensions/gsd/doctor-providers.ts +13 -0
  365. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  366. package/src/resources/extensions/gsd/doctor.ts +12 -1
  367. package/src/resources/extensions/gsd/engine-resolver.ts +57 -0
  368. package/src/resources/extensions/gsd/engine-types.ts +71 -0
  369. package/src/resources/extensions/gsd/execution-policy.ts +43 -0
  370. package/src/resources/extensions/gsd/exit-command.ts +14 -2
  371. package/src/resources/extensions/gsd/export.ts +8 -15
  372. package/src/resources/extensions/gsd/extension-manifest.json +2 -2
  373. package/src/resources/extensions/gsd/files.ts +29 -12
  374. package/src/resources/extensions/gsd/forensics.ts +101 -3
  375. package/src/resources/extensions/gsd/git-constants.ts +1 -0
  376. package/src/resources/extensions/gsd/git-service.ts +5 -5
  377. package/src/resources/extensions/gsd/gitignore.ts +1 -1
  378. package/src/resources/extensions/gsd/graph.ts +312 -0
  379. package/src/resources/extensions/gsd/gsd-db.ts +37 -8
  380. package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
  381. package/src/resources/extensions/gsd/guided-flow.ts +7 -3
  382. package/src/resources/extensions/gsd/journal.ts +134 -0
  383. package/src/resources/extensions/gsd/md-importer.ts +6 -0
  384. package/src/resources/extensions/gsd/milestone-ids.ts +1 -1
  385. package/src/resources/extensions/gsd/native-git-bridge.ts +3 -2
  386. package/src/resources/extensions/gsd/post-unit-hooks.ts +24 -462
  387. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  388. package/src/resources/extensions/gsd/preferences.ts +63 -6
  389. package/src/resources/extensions/gsd/prompt-loader.ts +35 -4
  390. package/src/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  391. package/src/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  392. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  393. package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
  394. package/src/resources/extensions/gsd/prompts/queue.md +1 -1
  395. package/src/resources/extensions/gsd/repo-identity.ts +95 -7
  396. package/src/resources/extensions/gsd/rule-registry.ts +599 -0
  397. package/src/resources/extensions/gsd/rule-types.ts +68 -0
  398. package/src/resources/extensions/gsd/run-manager.ts +180 -0
  399. package/src/resources/extensions/gsd/service-tier.ts +184 -0
  400. package/src/resources/extensions/gsd/session-lock.ts +2 -2
  401. package/src/resources/extensions/gsd/structured-data-formatter.ts +3 -1
  402. package/src/resources/extensions/gsd/templates/decisions.md +2 -2
  403. package/src/resources/extensions/gsd/tests/activity-log.test.ts +31 -69
  404. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +103 -120
  405. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +85 -0
  406. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -2
  407. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +202 -0
  408. package/src/resources/extensions/gsd/tests/bundled-workflow-defs.test.ts +180 -0
  409. package/src/resources/extensions/gsd/tests/captures.test.ts +12 -1
  410. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +283 -0
  411. package/src/resources/extensions/gsd/tests/context-injector.test.ts +313 -0
  412. package/src/resources/extensions/gsd/tests/context-store.test.ts +10 -5
  413. package/src/resources/extensions/gsd/tests/continue-here.test.ts +20 -20
  414. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +540 -0
  415. package/src/resources/extensions/gsd/tests/custom-verification.test.ts +382 -0
  416. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +339 -0
  417. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +87 -0
  418. package/src/resources/extensions/gsd/tests/db-writer.test.ts +10 -0
  419. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +778 -0
  420. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +318 -0
  421. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +15 -10
  422. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +5 -4
  423. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +167 -0
  424. package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +174 -0
  425. package/src/resources/extensions/gsd/tests/e2e-workflow-pipeline-integration.test.ts +476 -0
  426. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +271 -0
  427. package/src/resources/extensions/gsd/tests/exit-command.test.ts +55 -0
  428. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +48 -0
  429. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
  430. package/src/resources/extensions/gsd/tests/git-locale.test.ts +133 -0
  431. package/src/resources/extensions/gsd/tests/git-service.test.ts +44 -0
  432. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +599 -0
  433. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +8 -1
  434. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +7 -7
  435. package/src/resources/extensions/gsd/tests/iterate-engine-integration.test.ts +429 -0
  436. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +513 -0
  437. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +147 -0
  438. package/src/resources/extensions/gsd/tests/journal.test.ts +341 -0
  439. package/src/resources/extensions/gsd/tests/manifest-status.test.ts +73 -82
  440. package/src/resources/extensions/gsd/tests/md-importer.test.ts +31 -1
  441. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  442. package/src/resources/extensions/gsd/tests/milestone-id-reservation.test.ts +1 -1
  443. package/src/resources/extensions/gsd/tests/parsers.test.ts +110 -0
  444. package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -25
  445. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +3 -1
  446. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +61 -1
  447. package/src/resources/extensions/gsd/tests/routing-history.test.ts +11 -22
  448. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +413 -0
  449. package/src/resources/extensions/gsd/tests/run-manager.test.ts +229 -0
  450. package/src/resources/extensions/gsd/tests/service-tier.test.ts +127 -0
  451. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +56 -3
  452. package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +2 -2
  453. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +102 -0
  454. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +4 -3
  455. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +151 -0
  456. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +45 -0
  457. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +117 -0
  458. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -1
  459. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +156 -263
  460. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +99 -0
  461. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -0
  462. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +4 -0
  463. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +135 -0
  464. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +203 -106
  465. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +79 -5
  466. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +140 -0
  467. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +74 -0
  468. package/src/resources/extensions/gsd/types.ts +3 -0
  469. package/src/resources/extensions/gsd/workflow-engine.ts +38 -0
  470. package/src/resources/extensions/gsd/workflow-templates.ts +12 -1
  471. package/src/resources/extensions/gsd/worktree-manager.ts +21 -6
  472. package/src/resources/extensions/gsd/worktree-resolver.ts +32 -12
  473. package/src/resources/extensions/gsd/worktree.ts +2 -2
  474. package/src/resources/extensions/mcp-client/index.ts +5 -1
  475. package/src/resources/extensions/search-the-web/tool-search.ts +3 -3
  476. package/src/resources/extensions/subagent/index.ts +7 -3
  477. package/src/resources/extensions/voice/index.ts +4 -4
  478. package/src/resources/skills/create-workflow/SKILL.md +103 -0
  479. package/src/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  480. package/src/resources/skills/create-workflow/references/verification-policies.md +76 -0
  481. package/src/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  482. package/src/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  483. package/src/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  484. package/src/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  485. package/src/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  486. package/src/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  487. package/src/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  488. package/dist/web/standalone/.next/static/chunks/4024.279c423e4661ece1.js +0 -9
  489. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  490. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  491. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  492. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  493. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → qw8qDHXOTLUXBq1vEknSz}/_buildManifest.js +0 -0
  494. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → qw8qDHXOTLUXBq1vEknSz}/_ssgManifest.js +0 -0
@@ -2,7 +2,7 @@ import { existsSync, lstatSync, readdirSync, readFileSync, realpathSync, rmSync,
2
2
  import { basename, dirname, join, sep } from "node:path";
3
3
 
4
4
  import type { DoctorIssue, DoctorIssueCode } from "./doctor-types.js";
5
- import { readRepoMeta, externalProjectsRoot } from "./repo-identity.js";
5
+ import { readRepoMeta, externalProjectsRoot, cleanNumberedGsdVariants } from "./repo-identity.js";
6
6
  import { loadFile, parseRoadmap } from "./files.js";
7
7
  import { resolveMilestoneFile, milestonesDir, gsdRoot, resolveGsdRootFile, relGsdRootFile } from "./paths.js";
8
8
  import { deriveState, isMilestoneComplete } from "./state.js";
@@ -776,6 +776,37 @@ export async function checkRuntimeHealth(
776
776
  // Non-fatal — external state check failed
777
777
  }
778
778
 
779
+ // ── Numbered .gsd collision variants (#2205) ───────────────────────────
780
+ // macOS APFS can create ".gsd 2", ".gsd 3" etc. when a directory blocks
781
+ // symlink creation. These must be removed so the canonical .gsd is used.
782
+ try {
783
+ const variantPattern = /^\.gsd \d+$/;
784
+ const entries = readdirSync(basePath);
785
+ const variants = entries.filter(e => variantPattern.test(e));
786
+ if (variants.length > 0) {
787
+ for (const v of variants) {
788
+ issues.push({
789
+ severity: "warning",
790
+ code: "numbered_gsd_variant",
791
+ scope: "project",
792
+ unitId: "project",
793
+ message: `Found macOS collision variant "${v}" — this can cause GSD state to appear deleted.`,
794
+ file: v,
795
+ fixable: true,
796
+ });
797
+ }
798
+
799
+ if (shouldFix("numbered_gsd_variant")) {
800
+ const removed = cleanNumberedGsdVariants(basePath);
801
+ for (const name of removed) {
802
+ fixesApplied.push(`removed numbered .gsd variant: ${name}`);
803
+ }
804
+ }
805
+ }
806
+ } catch {
807
+ // Non-fatal — variant check failed
808
+ }
809
+
779
810
  // ── Metrics ledger integrity ───────────────────────────────────────────
780
811
  try {
781
812
  const metricsPath = join(root, "metrics.json");
@@ -305,11 +305,24 @@ function checkOptionalProviders(): ProviderCheckResult[] {
305
305
  const optional = ["brave", "tavily", "jina", "context7"] as const;
306
306
  const results: ProviderCheckResult[] = [];
307
307
 
308
+ // Determine which search providers are configured so we can suppress
309
+ // "not configured" noise for alternative search providers when at least
310
+ // one is already active (e.g. don't warn about missing BRAVE_API_KEY
311
+ // when Tavily is configured).
312
+ const searchProviderIds = ["brave", "tavily"] as const;
313
+ const hasAnySearchProvider = searchProviderIds.some(id => resolveKey(id).found);
314
+
308
315
  for (const providerId of optional) {
309
316
  const info = PROVIDER_REGISTRY.find(p => p.id === providerId);
310
317
  if (!info) continue;
311
318
 
312
319
  const lookup = resolveKey(providerId);
320
+
321
+ // Skip unconfigured search providers when another search provider is active
322
+ if (!lookup.found && hasAnySearchProvider && info.category === "search") {
323
+ continue;
324
+ }
325
+
313
326
  results.push({
314
327
  name: providerId,
315
328
  label: info.label,
@@ -33,6 +33,7 @@ export type DoctorIssueCode =
33
33
  | "unresolvable_dependency"
34
34
  | "failed_migration"
35
35
  | "broken_symlink"
36
+ | "numbered_gsd_variant"
36
37
  // Environment health checks (#1221)
37
38
  | "env_node_version"
38
39
  | "env_dependencies"
@@ -792,6 +792,7 @@ export async function runGSDDoctor(basePath: string, options?: { fix?: boolean;
792
792
  } catch { /* non-fatal */ }
793
793
 
794
794
  let allTasksDone = plan.tasks.length > 0;
795
+ let taskUncheckedByDoctor = false;
795
796
  for (const task of plan.tasks) {
796
797
  const taskUnitId = `${unitId}/${task.id}`;
797
798
  const summaryPath = resolveTaskFile(basePath, milestoneId, slice.id, task.id, "SUMMARY");
@@ -810,6 +811,7 @@ export async function runGSDDoctor(basePath: string, options?: { fix?: boolean;
810
811
  dryRunCanFix("task_done_missing_summary", `uncheck ${task.id} in plan for ${taskUnitId}`);
811
812
  if (shouldFix("task_done_missing_summary")) {
812
813
  await markTaskUndoneInPlan(basePath, milestoneId, slice.id, task.id, fixesApplied);
814
+ taskUncheckedByDoctor = true;
813
815
  }
814
816
  }
815
817
 
@@ -873,6 +875,15 @@ export async function runGSDDoctor(basePath: string, options?: { fix?: boolean;
873
875
  allTasksDone = allTasksDone && task.done;
874
876
  }
875
877
 
878
+ // ── #1850: cascade slice uncheck when task_done_missing_summary fires ──
879
+ // When doctor unchecks tasks inside a done slice, the slice must also be
880
+ // unchecked so the state machine re-enters the executing phase. Without
881
+ // this, state.ts skips done slices and the unchecked tasks never run,
882
+ // causing doctor to fire again on every start (infinite loop).
883
+ if (taskUncheckedByDoctor && slice.done) {
884
+ await markSliceUndoneInRoadmap(basePath, milestoneId, slice.id, fixesApplied);
885
+ }
886
+
876
887
  // Blocker-without-replan detection
877
888
  const replanPath = resolveSliceFile(basePath, milestoneId, slice.id, "REPLAN");
878
889
  if (!replanPath) {
@@ -949,7 +960,7 @@ export async function runGSDDoctor(basePath: string, options?: { fix?: boolean;
949
960
  fixable: true,
950
961
  });
951
962
  dryRunCanFix("all_tasks_done_roadmap_not_checked", `mark ${slice.id} done in roadmap`);
952
- if (shouldFix("all_tasks_done_roadmap_not_checked") && (hasSliceSummary || issues.some(issue => issue.code === "all_tasks_done_missing_slice_summary" && issue.unitId === unitId))) {
963
+ if (shouldFix("all_tasks_done_roadmap_not_checked") && (hasSliceSummary || existsSync(join(slicePath, `${slice.id}-SUMMARY.md`)))) {
953
964
  await markSliceDoneInRoadmap(basePath, milestoneId, slice.id, fixesApplied);
954
965
  }
955
966
  }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * engine-resolver.ts — Route sessions to engine/policy pairs.
3
+ *
4
+ * Routes `null` and `"dev"` engine IDs to the DevWorkflowEngine/DevExecutionPolicy
5
+ * pair. Any other non-null engine ID is treated as a custom workflow engine that
6
+ * reads its state from an `activeRunDir`. Respects `GSD_ENGINE_BYPASS=1` kill
7
+ * switch to skip the engine layer entirely.
8
+ */
9
+
10
+ import type { WorkflowEngine } from "./workflow-engine.js";
11
+ import type { ExecutionPolicy } from "./execution-policy.js";
12
+ import { DevWorkflowEngine } from "./dev-workflow-engine.js";
13
+ import { DevExecutionPolicy } from "./dev-execution-policy.js";
14
+ import { CustomWorkflowEngine } from "./custom-workflow-engine.js";
15
+ import { CustomExecutionPolicy } from "./custom-execution-policy.js";
16
+
17
+ /** A resolved engine + policy pair ready for the auto-loop. */
18
+ export interface ResolvedEngine {
19
+ engine: WorkflowEngine;
20
+ policy: ExecutionPolicy;
21
+ }
22
+
23
+ /**
24
+ * Resolve an engine/policy pair for the given session.
25
+ *
26
+ * - `null` or `"dev"` → DevWorkflowEngine + DevExecutionPolicy
27
+ * - any other non-null ID → CustomWorkflowEngine(activeRunDir) + CustomExecutionPolicy()
28
+ * (requires activeRunDir to be a non-empty string)
29
+ *
30
+ * Note: `GSD_ENGINE_BYPASS=1` is checked in autoLoop before calling this function.
31
+ */
32
+ export function resolveEngine(
33
+ session: { activeEngineId: string | null; activeRunDir?: string | null },
34
+ ): ResolvedEngine {
35
+ const { activeEngineId, activeRunDir } = session;
36
+
37
+ if (activeEngineId === null || activeEngineId === "dev") {
38
+ return {
39
+ engine: new DevWorkflowEngine(),
40
+ policy: new DevExecutionPolicy(),
41
+ };
42
+ }
43
+
44
+ // Any non-null, non-"dev" engine ID is a custom workflow engine.
45
+ // activeRunDir is required — the engine reads GRAPH.yaml from it.
46
+ if (!activeRunDir || typeof activeRunDir !== "string") {
47
+ throw new Error(
48
+ `Custom engine "${activeEngineId}" requires activeRunDir to be a non-empty string, ` +
49
+ `got: ${JSON.stringify(activeRunDir)}`,
50
+ );
51
+ }
52
+
53
+ return {
54
+ engine: new CustomWorkflowEngine(activeRunDir),
55
+ policy: new CustomExecutionPolicy(activeRunDir),
56
+ };
57
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * engine-types.ts — Engine-polymorphic type contracts.
3
+ *
4
+ * LEAF NODE: This file must have ZERO imports from any GSD module.
5
+ * Only `node:` imports are permitted. All engine/policy interfaces
6
+ * depend on these types; nothing here depends on GSD internals.
7
+ */
8
+
9
+ /** Snapshot of engine state at a point in time. */
10
+ export interface EngineState {
11
+ phase: string;
12
+ currentMilestoneId: string | null;
13
+ activeSliceId: string | null;
14
+ activeTaskId: string | null;
15
+ isComplete: boolean;
16
+ /** Opaque engine-specific state — never narrowed to a GSD-specific type. */
17
+ raw: unknown;
18
+ }
19
+
20
+ /** A unit of work the engine wants the agent to execute. */
21
+ export interface StepContract {
22
+ unitType: string;
23
+ unitId: string;
24
+ prompt: string;
25
+ }
26
+
27
+ /** UI-facing metadata for progress display. */
28
+ export interface DisplayMetadata {
29
+ engineLabel: string;
30
+ currentPhase: string;
31
+ progressSummary: string;
32
+ stepCount: { completed: number; total: number } | null;
33
+ }
34
+
35
+ /**
36
+ * Discriminated union: what the engine tells the loop to do next.
37
+ *
38
+ * - `dispatch` — execute a step
39
+ * - `stop` — halt the loop with a reason and severity
40
+ * - `skip` — nothing to do right now, advance without executing
41
+ */
42
+ export type EngineDispatchAction =
43
+ | { action: "dispatch"; step: StepContract }
44
+ | { action: "stop"; reason: string; level: "info" | "warning" | "error" }
45
+ | { action: "skip" };
46
+
47
+ /** Outcome of reconciling state after a step completes. */
48
+ export interface ReconcileResult {
49
+ outcome: "continue" | "milestone-complete" | "pause" | "stop";
50
+ reason?: string;
51
+ }
52
+
53
+ /** Recovery strategy when a step fails. */
54
+ export interface RecoveryAction {
55
+ outcome: "retry" | "skip" | "stop" | "pause";
56
+ reason?: string;
57
+ }
58
+
59
+ /** Result of closing out a completed unit. */
60
+ export interface CloseoutResult {
61
+ committed: boolean;
62
+ artifacts: string[];
63
+ }
64
+
65
+ /** Record of a completed execution step. */
66
+ export interface CompletedStep {
67
+ unitType: string;
68
+ unitId: string;
69
+ startedAt: number;
70
+ finishedAt: number;
71
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * execution-policy.ts — ExecutionPolicy interface.
3
+ *
4
+ * Defines the policy layer that governs model selection, verification,
5
+ * recovery, and closeout for each execution step. Imports only from
6
+ * the leaf-node engine-types.
7
+ */
8
+
9
+ import type { RecoveryAction, CloseoutResult } from "./engine-types.js";
10
+
11
+ /** Policy governing how each step is executed, verified, and closed out. */
12
+ export interface ExecutionPolicy {
13
+ /** Prepare the workspace before a milestone begins (e.g. worktree setup). */
14
+ prepareWorkspace(basePath: string, milestoneId: string): Promise<void>;
15
+
16
+ /** Select the model tier for a given unit. Returns null to use defaults. */
17
+ selectModel(
18
+ unitType: string,
19
+ unitId: string,
20
+ context: { basePath: string },
21
+ ): Promise<{ tier: string; modelDowngraded: boolean } | null>;
22
+
23
+ /** Verify unit output. Returns disposition for the loop. */
24
+ verify(
25
+ unitType: string,
26
+ unitId: string,
27
+ context: { basePath: string },
28
+ ): Promise<"continue" | "retry" | "pause">;
29
+
30
+ /** Determine recovery action when a unit fails. */
31
+ recover(
32
+ unitType: string,
33
+ unitId: string,
34
+ context: { basePath: string },
35
+ ): Promise<RecoveryAction>;
36
+
37
+ /** Close out a completed unit (commit, snapshot, artifact capture). */
38
+ closeout(
39
+ unitType: string,
40
+ unitId: string,
41
+ context: { basePath: string; startedAt: number },
42
+ ): Promise<CloseoutResult>;
43
+ }
@@ -10,8 +10,20 @@ export function registerExitCommand(
10
10
  description: "Exit GSD gracefully",
11
11
  handler: async (_args: string, ctx: ExtensionCommandContext) => {
12
12
  // Stop auto-mode first so locks and activity state are cleaned up before shutdown.
13
- const stopAuto = deps.stopAuto ?? (await importExtensionModule<typeof import("./auto.js")>(import.meta.url, "./auto.js")).stopAuto;
14
- await stopAuto(ctx, pi, "Graceful exit");
13
+ // Wrapped in try/catch: if gsd-pi was updated on disk mid-session, the dynamic
14
+ // import may resolve a new auto-worktree.js whose static imports reference
15
+ // exports absent from the process-cached native-git-bridge.js (ESM cache is
16
+ // immutable). The user's work is already saved — this is cleanup only.
17
+ try {
18
+ const stopAuto = deps.stopAuto ?? (await importExtensionModule<typeof import("./auto.js")>(import.meta.url, "./auto.js")).stopAuto;
19
+ await stopAuto(ctx, pi, "Graceful exit");
20
+ } catch (e) {
21
+ const msg = e instanceof Error ? e.message : String(e);
22
+ ctx.ui?.notify?.(
23
+ `Auto-mode cleanup skipped (module version mismatch): ${msg}`,
24
+ "warning",
25
+ );
26
+ }
15
27
  ctx.shutdown();
16
28
  },
17
29
  });
@@ -4,7 +4,7 @@
4
4
  import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
5
5
  import { writeFileSync, mkdirSync } from "node:fs";
6
6
  import { join, basename } from "node:path";
7
- import { exec } from "node:child_process";
7
+ import { exec, execFile } from "node:child_process";
8
8
  import {
9
9
  getLedger, getProjectTotals, aggregateByPhase, aggregateBySlice,
10
10
  aggregateByModel, formatCost, formatTokenCount, loadLedgerFromDisk,
@@ -20,20 +20,13 @@ import { getErrorMessage } from "./error-utils.js";
20
20
  * Non-blocking, non-fatal — failures are silently ignored.
21
21
  */
22
22
  export function openInBrowser(filePath: string): void {
23
- const cmd =
24
- process.platform === "darwin" ? "open" :
25
- process.platform === "win32" ? "start" :
26
- "xdg-open";
27
-
28
- // On Windows, `start` needs an empty title argument when the path has spaces
29
- const args = process.platform === "win32"
30
- ? `"" "${filePath}"`
31
- : `"${filePath}"`;
32
-
33
- exec(`${cmd} ${args}`, (err) => {
34
- // Non-fatal — if the browser can't be opened, the file path is still shown
35
- if (err) void err;
36
- });
23
+ if (process.platform === "win32") {
24
+ // PowerShell's Start-Process handles paths with '&' and spaces safely.
25
+ execFile("powershell", ["-c", `Start-Process '${filePath.replace(/'/g, "''")}'`], () => {});
26
+ } else {
27
+ const cmd = process.platform === "darwin" ? "open" : "xdg-open";
28
+ execFile(cmd, [filePath], () => {});
29
+ }
37
30
  }
38
31
 
39
32
  /**
@@ -8,8 +8,8 @@
8
8
  "provides": {
9
9
  "tools": [
10
10
  "bash", "write", "read", "edit",
11
- "gsd_save_decision", "gsd_save_summary",
12
- "gsd_update_requirement", "gsd_generate_milestone_id"
11
+ "gsd_decision_save", "gsd_summary_save",
12
+ "gsd_requirement_update", "gsd_milestone_generate_id"
13
13
  ],
14
14
  "commands": ["gsd", "kill", "worktree", "exit"],
15
15
  "hooks": ["session_start"],
@@ -374,20 +374,37 @@ function _parsePlanImpl(content: string): SlicePlan {
374
374
 
375
375
  for (const line of taskLines) {
376
376
  const cbMatch = line.match(/^-\s+\[([ xX])\]\s+\*\*([\w.]+):\s+(.+?)\*\*\s*(.*)/);
377
- if (cbMatch) {
377
+ // Heading-style: ### T01 -- Title, ### T01: Title, ### T01 — Title
378
+ const hdMatch = !cbMatch ? line.match(/^#{2,4}\s+([\w.]+)\s*(?:--|—|:)\s*(.+)/) : null;
379
+ if (cbMatch || hdMatch) {
378
380
  if (currentTask) tasks.push(currentTask);
379
381
 
380
- const rest = cbMatch[4] || '';
381
- const estMatch = rest.match(/`est:([^`]+)`/);
382
- const estimate = estMatch ? estMatch[1] : '';
383
-
384
- currentTask = {
385
- id: cbMatch[2],
386
- title: cbMatch[3],
387
- description: '',
388
- done: cbMatch[1].toLowerCase() === 'x',
389
- estimate,
390
- };
382
+ if (cbMatch) {
383
+ const rest = cbMatch[4] || '';
384
+ const estMatch = rest.match(/`est:([^`]+)`/);
385
+ const estimate = estMatch ? estMatch[1] : '';
386
+
387
+ currentTask = {
388
+ id: cbMatch[2],
389
+ title: cbMatch[3],
390
+ description: '',
391
+ done: cbMatch[1].toLowerCase() === 'x',
392
+ estimate,
393
+ };
394
+ } else {
395
+ const rest = hdMatch![2] || '';
396
+ const titleEstMatch = rest.match(/^(.+?)\s*`est:([^`]+)`\s*$/);
397
+ const title = titleEstMatch ? titleEstMatch[1].trim() : rest.trim();
398
+ const estimate = titleEstMatch ? titleEstMatch[2] : '';
399
+
400
+ currentTask = {
401
+ id: hdMatch![1],
402
+ title,
403
+ description: '',
404
+ done: false,
405
+ estimate,
406
+ };
407
+ }
391
408
  } else if (currentTask && line.match(/^\s*-\s+Files:\s*(.*)/)) {
392
409
  const filesMatch = line.match(/^\s*-\s+Files:\s*(.*)/);
393
410
  if (filesMatch) {
@@ -12,6 +12,7 @@ import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent
12
12
  import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
13
13
  import { join, dirname, relative } from "node:path";
14
14
  import { fileURLToPath } from "node:url";
15
+ import { homedir } from "node:os";
15
16
 
16
17
  import { extractTrace, type ExecutionTrace } from "./session-forensics.js";
17
18
  import { nativeParseJsonlTail } from "./native-parser-bridge.js";
@@ -29,6 +30,9 @@ import { loadPrompt } from "./prompt-loader.js";
29
30
  import { gsdRoot } from "./paths.js";
30
31
  import { formatDuration } from "../shared/format-utils.js";
31
32
  import { getAutoWorktreePath } from "./auto-worktree.js";
33
+ import { loadEffectiveGSDPreferences, loadGlobalGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
34
+ import { showNextAction } from "../shared/tui.js";
35
+ import { ensurePreferencesFile, serializePreferencesToFrontmatter } from "./commands-prefs-wizard.js";
32
36
 
33
37
  // ─── Types ────────────────────────────────────────────────────────────────────
34
38
 
@@ -66,6 +70,71 @@ interface ForensicReport {
66
70
  recentUnits: { type: string; id: string; cost: number; duration: number; model: string; finishedAt: number }[];
67
71
  }
68
72
 
73
+ // ─── Duplicate Detection ──────────────────────────────────────────────────────
74
+
75
+ const DEDUP_PROMPT_SECTION = `
76
+ ## Duplicate Detection (REQUIRED before issue creation)
77
+
78
+ Before offering to create a GitHub issue, you MUST search for existing issues and PRs that may already address this bug. This step uses the user's AI tokens for analysis.
79
+
80
+ ### Search Steps
81
+
82
+ 1. **Search closed issues** for similar keywords from your diagnosis:
83
+ \`\`\`
84
+ gh issue list --repo gsd-build/gsd-2 --state closed --search "<keywords from root cause>" --limit 20
85
+ \`\`\`
86
+
87
+ 2. **Search open PRs** that might contain the fix:
88
+ \`\`\`
89
+ gh pr list --repo gsd-build/gsd-2 --state open --search "<keywords>" --limit 10
90
+ \`\`\`
91
+
92
+ 3. **Search merged PRs** that may have already fixed this:
93
+ \`\`\`
94
+ gh pr list --repo gsd-build/gsd-2 --state merged --search "<keywords>" --limit 10
95
+ \`\`\`
96
+
97
+ ### Analysis
98
+
99
+ For each result, compare it against your root-cause diagnosis:
100
+ - Does the issue describe the same code path or file?
101
+ - Does the PR modify the same file:line you identified?
102
+ - Is the symptom description semantically similar even if keywords differ?
103
+
104
+ ### Present Findings
105
+
106
+ If you find potential matches, present them to the user:
107
+
108
+ 1. **"Already fixed by PR #X — skip issue creation"** — when a merged PR or closed issue clearly addresses the same root cause. Explain why you believe it matches.
109
+ 2. **"Add my findings to existing issue #Y"** — when an open issue exists for the same bug. Use \`gh issue comment #Y --repo gsd-build/gsd-2\` to add forensic evidence.
110
+ 3. **"Create new issue anyway"** — when existing results do not cover this specific failure.
111
+
112
+ Only proceed to issue creation if no matches were found OR the user explicitly chooses "Create new issue anyway".
113
+ `;
114
+
115
+ async function writeForensicsDedupPref(ctx: ExtensionCommandContext, enabled: boolean): Promise<void> {
116
+ const prefsPath = getGlobalGSDPreferencesPath();
117
+ await ensurePreferencesFile(prefsPath, ctx, "global");
118
+ const existing = loadGlobalGSDPreferences();
119
+ const prefs: Record<string, unknown> = existing?.preferences ? { ...existing.preferences } : {};
120
+ prefs.version = prefs.version || 1;
121
+ prefs.forensics_dedup = enabled;
122
+
123
+ const frontmatter = serializePreferencesToFrontmatter(prefs);
124
+ const raw = existsSync(prefsPath) ? readFileSync(prefsPath, "utf-8") : "";
125
+ let body = "\n# GSD Skill Preferences\n\nSee `~/.gsd/agent/extensions/gsd/docs/preferences-reference.md` for full field documentation and examples.\n";
126
+ const start = raw.startsWith("---\n") ? 4 : raw.startsWith("---\r\n") ? 5 : -1;
127
+ if (start !== -1) {
128
+ const closingIdx = raw.indexOf("\n---", start);
129
+ if (closingIdx !== -1) {
130
+ const after = raw.slice(closingIdx + 4);
131
+ if (after.trim()) body = after;
132
+ }
133
+ }
134
+
135
+ writeFileSync(prefsPath, `---\n${frontmatter}---${body}`, "utf-8");
136
+ }
137
+
69
138
  // ─── Entry Point ──────────────────────────────────────────────────────────────
70
139
 
71
140
  export async function handleForensics(
@@ -97,20 +166,49 @@ export async function handleForensics(
97
166
  return;
98
167
  }
99
168
 
169
+ // ─── Duplicate detection opt-in ─────────────────────────────────────────────
170
+ const effectivePrefs = loadEffectiveGSDPreferences()?.preferences;
171
+ let dedupEnabled = effectivePrefs?.forensics_dedup === true;
172
+
173
+ if (effectivePrefs?.forensics_dedup === undefined) {
174
+ const choice = await showNextAction(ctx, {
175
+ title: "Duplicate detection available",
176
+ summary: ["Before filing a GitHub issue, forensics can search existing issues and PRs to avoid duplicates.", "This uses additional AI tokens for analysis."],
177
+ actions: [
178
+ { id: "enable", label: "Enable duplicate detection", description: "Search issues/PRs before filing (recommended)", recommended: true },
179
+ { id: "skip", label: "Skip for now", description: "File without checking for duplicates" },
180
+ ],
181
+ notYetMessage: "You can enable this later via preferences (forensics_dedup: true).",
182
+ });
183
+
184
+ if (choice === "enable") {
185
+ await writeForensicsDedupPref(ctx, true);
186
+ dedupEnabled = true;
187
+ }
188
+ }
189
+
190
+ const dedupSection = dedupEnabled ? DEDUP_PROMPT_SECTION : "";
191
+
100
192
  ctx.ui.notify("Building forensic report...", "info");
101
193
 
102
194
  const report = await buildForensicReport(basePath);
103
195
  const savedPath = saveForensicReport(basePath, report, problemDescription);
104
196
 
105
- // Derive GSD source dir for prompt
106
- const __extensionDir = dirname(fileURLToPath(import.meta.url));
107
- const gsdSourceDir = __extensionDir;
197
+ // Derive GSD source dir for prompt — fall back to ~/.gsd/agent/extensions/gsd/
198
+ // when import.meta.url resolves to the npm-global install path (Windows).
199
+ let gsdSourceDir = dirname(fileURLToPath(import.meta.url));
200
+ if (!existsSync(join(gsdSourceDir, "prompts"))) {
201
+ const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
202
+ const fallback = join(gsdHome, "agent", "extensions", "gsd");
203
+ if (existsSync(join(fallback, "prompts"))) gsdSourceDir = fallback;
204
+ }
108
205
 
109
206
  const forensicData = formatReportForPrompt(report);
110
207
  const content = loadPrompt("forensics", {
111
208
  problemDescription,
112
209
  forensicData,
113
210
  gsdSourceDir,
211
+ dedupSection,
114
212
  });
115
213
 
116
214
  ctx.ui.notify(`Forensic report saved: ${relative(basePath, savedPath)}`, "info");
@@ -8,4 +8,5 @@ export const GIT_NO_PROMPT_ENV = {
8
8
  GIT_TERMINAL_PROMPT: "0",
9
9
  GIT_ASKPASS: "",
10
10
  GIT_SVN_ID: "",
11
+ LC_ALL: "C", // force English git output so stderr string checks work on all locales (#1997)
11
12
  };
@@ -245,7 +245,6 @@ export function writeIntegrationBranch(
245
245
  basePath: string,
246
246
  milestoneId: string,
247
247
  branch: string,
248
- _options?: { commitDocs?: boolean },
249
248
  ): void {
250
249
  // Don't record slice branches as the integration target
251
250
  if (SLICE_BRANCH_RE.test(branch)) return;
@@ -683,10 +682,11 @@ export function createDraftPR(
683
682
  body: string,
684
683
  ): string | null {
685
684
  try {
686
- const result = execSync(
687
- `gh pr create --draft --title ${JSON.stringify(title)} --body ${JSON.stringify(body)}`,
688
- { cwd: basePath, encoding: "utf8", timeout: 30000, env: GIT_NO_PROMPT_ENV },
689
- );
685
+ const result = execFileSync("gh", [
686
+ "pr", "create", "--draft",
687
+ "--title", title,
688
+ "--body", body,
689
+ ], { cwd: basePath, encoding: "utf8", timeout: 30000, env: GIT_NO_PROMPT_ENV });
690
690
  return result.trim();
691
691
  } catch {
692
692
  return null;
@@ -137,7 +137,7 @@ export function hasGitTrackedGsdFiles(basePath: string): boolean {
137
137
  */
138
138
  export function ensureGitignore(
139
139
  basePath: string,
140
- options?: { manageGitignore?: boolean; commitDocs?: boolean },
140
+ options?: { manageGitignore?: boolean },
141
141
  ): boolean {
142
142
  // If manage_gitignore is explicitly false, do not touch .gitignore at all
143
143
  if (options?.manageGitignore === false) return false;