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
@@ -0,0 +1,82 @@
1
+ /**
2
+ * dev-workflow-engine.ts — DevWorkflowEngine implementation.
3
+ *
4
+ * Implements WorkflowEngine by delegating to existing GSD state derivation
5
+ * and dispatch logic. This is the "dev" engine — it wraps the current GSD
6
+ * auto-mode behavior behind the engine-polymorphic interface.
7
+ */
8
+ import { deriveState } from "./state.js";
9
+ import { resolveDispatch } from "./auto-dispatch.js";
10
+ import { loadEffectiveGSDPreferences } from "./preferences.js";
11
+ // ─── Bridge: DispatchAction → EngineDispatchAction ────────────────────────
12
+ /**
13
+ * Map a GSD-specific DispatchAction (which carries `matchedRule`, `unitType`,
14
+ * etc.) to the engine-generic EngineDispatchAction discriminated union.
15
+ *
16
+ * Exported for unit testing.
17
+ */
18
+ export function bridgeDispatchAction(da) {
19
+ switch (da.action) {
20
+ case "dispatch":
21
+ return {
22
+ action: "dispatch",
23
+ step: {
24
+ unitType: da.unitType,
25
+ unitId: da.unitId,
26
+ prompt: da.prompt,
27
+ },
28
+ };
29
+ case "stop":
30
+ return {
31
+ action: "stop",
32
+ reason: da.reason,
33
+ level: da.level,
34
+ };
35
+ case "skip":
36
+ return { action: "skip" };
37
+ }
38
+ }
39
+ // ─── DevWorkflowEngine ───────────────────────────────────────────────────
40
+ export class DevWorkflowEngine {
41
+ engineId = "dev";
42
+ async deriveState(basePath) {
43
+ const gsd = await deriveState(basePath);
44
+ return {
45
+ phase: gsd.phase,
46
+ currentMilestoneId: gsd.activeMilestone?.id ?? null,
47
+ activeSliceId: gsd.activeSlice?.id ?? null,
48
+ activeTaskId: gsd.activeTask?.id ?? null,
49
+ isComplete: gsd.phase === "complete",
50
+ raw: gsd,
51
+ };
52
+ }
53
+ async resolveDispatch(state, context) {
54
+ const gsd = state.raw;
55
+ const mid = gsd.activeMilestone?.id ?? "";
56
+ const midTitle = gsd.activeMilestone?.title ?? "";
57
+ const loaded = loadEffectiveGSDPreferences();
58
+ const prefs = loaded?.preferences ?? undefined;
59
+ const dispatchCtx = {
60
+ basePath: context.basePath,
61
+ mid,
62
+ midTitle,
63
+ state: gsd,
64
+ prefs,
65
+ };
66
+ const result = await resolveDispatch(dispatchCtx);
67
+ return bridgeDispatchAction(result);
68
+ }
69
+ async reconcile(state, _completedStep) {
70
+ return {
71
+ outcome: state.isComplete ? "milestone-complete" : "continue",
72
+ };
73
+ }
74
+ getDisplayMetadata(state) {
75
+ return {
76
+ engineLabel: "GSD Dev",
77
+ currentPhase: state.phase,
78
+ progressSummary: `${state.currentMilestoneId ?? "no milestone"} / ${state.activeSliceId ?? "—"} / ${state.activeTaskId ?? "—"}`,
79
+ stepCount: null,
80
+ };
81
+ }
82
+ }
@@ -1,6 +1,6 @@
1
1
  import { existsSync, lstatSync, readdirSync, readFileSync, realpathSync, rmSync, statSync } from "node:fs";
2
2
  import { basename, dirname, join, sep } from "node:path";
3
- import { readRepoMeta, externalProjectsRoot } from "./repo-identity.js";
3
+ import { readRepoMeta, externalProjectsRoot, cleanNumberedGsdVariants } from "./repo-identity.js";
4
4
  import { loadFile, parseRoadmap } from "./files.js";
5
5
  import { resolveMilestoneFile, milestonesDir, gsdRoot, resolveGsdRootFile } from "./paths.js";
6
6
  import { deriveState, isMilestoneComplete } from "./state.js";
@@ -733,6 +733,36 @@ export async function checkRuntimeHealth(basePath, issues, fixesApplied, shouldF
733
733
  catch {
734
734
  // Non-fatal — external state check failed
735
735
  }
736
+ // ── Numbered .gsd collision variants (#2205) ───────────────────────────
737
+ // macOS APFS can create ".gsd 2", ".gsd 3" etc. when a directory blocks
738
+ // symlink creation. These must be removed so the canonical .gsd is used.
739
+ try {
740
+ const variantPattern = /^\.gsd \d+$/;
741
+ const entries = readdirSync(basePath);
742
+ const variants = entries.filter(e => variantPattern.test(e));
743
+ if (variants.length > 0) {
744
+ for (const v of variants) {
745
+ issues.push({
746
+ severity: "warning",
747
+ code: "numbered_gsd_variant",
748
+ scope: "project",
749
+ unitId: "project",
750
+ message: `Found macOS collision variant "${v}" — this can cause GSD state to appear deleted.`,
751
+ file: v,
752
+ fixable: true,
753
+ });
754
+ }
755
+ if (shouldFix("numbered_gsd_variant")) {
756
+ const removed = cleanNumberedGsdVariants(basePath);
757
+ for (const name of removed) {
758
+ fixesApplied.push(`removed numbered .gsd variant: ${name}`);
759
+ }
760
+ }
761
+ }
762
+ }
763
+ catch {
764
+ // Non-fatal — variant check failed
765
+ }
736
766
  // ── Metrics ledger integrity ───────────────────────────────────────────
737
767
  try {
738
768
  const metricsPath = join(root, "metrics.json");
@@ -260,11 +260,21 @@ function checkRemoteQuestionsProvider() {
260
260
  function checkOptionalProviders() {
261
261
  const optional = ["brave", "tavily", "jina", "context7"];
262
262
  const results = [];
263
+ // Determine which search providers are configured so we can suppress
264
+ // "not configured" noise for alternative search providers when at least
265
+ // one is already active (e.g. don't warn about missing BRAVE_API_KEY
266
+ // when Tavily is configured).
267
+ const searchProviderIds = ["brave", "tavily"];
268
+ const hasAnySearchProvider = searchProviderIds.some(id => resolveKey(id).found);
263
269
  for (const providerId of optional) {
264
270
  const info = PROVIDER_REGISTRY.find(p => p.id === providerId);
265
271
  if (!info)
266
272
  continue;
267
273
  const lookup = resolveKey(providerId);
274
+ // Skip unconfigured search providers when another search provider is active
275
+ if (!lookup.found && hasAnySearchProvider && info.category === "search") {
276
+ continue;
277
+ }
268
278
  results.push({
269
279
  name: providerId,
270
280
  label: info.label,
@@ -745,6 +745,7 @@ export async function runGSDDoctor(basePath, options) {
745
745
  }
746
746
  catch { /* non-fatal */ }
747
747
  let allTasksDone = plan.tasks.length > 0;
748
+ let taskUncheckedByDoctor = false;
748
749
  for (const task of plan.tasks) {
749
750
  const taskUnitId = `${unitId}/${task.id}`;
750
751
  const summaryPath = resolveTaskFile(basePath, milestoneId, slice.id, task.id, "SUMMARY");
@@ -762,6 +763,7 @@ export async function runGSDDoctor(basePath, options) {
762
763
  dryRunCanFix("task_done_missing_summary", `uncheck ${task.id} in plan for ${taskUnitId}`);
763
764
  if (shouldFix("task_done_missing_summary")) {
764
765
  await markTaskUndoneInPlan(basePath, milestoneId, slice.id, task.id, fixesApplied);
766
+ taskUncheckedByDoctor = true;
765
767
  }
766
768
  }
767
769
  if (!task.done && hasSummary) {
@@ -822,6 +824,14 @@ export async function runGSDDoctor(basePath, options) {
822
824
  }
823
825
  allTasksDone = allTasksDone && task.done;
824
826
  }
827
+ // ── #1850: cascade slice uncheck when task_done_missing_summary fires ──
828
+ // When doctor unchecks tasks inside a done slice, the slice must also be
829
+ // unchecked so the state machine re-enters the executing phase. Without
830
+ // this, state.ts skips done slices and the unchecked tasks never run,
831
+ // causing doctor to fire again on every start (infinite loop).
832
+ if (taskUncheckedByDoctor && slice.done) {
833
+ await markSliceUndoneInRoadmap(basePath, milestoneId, slice.id, fixesApplied);
834
+ }
825
835
  // Blocker-without-replan detection
826
836
  const replanPath = resolveSliceFile(basePath, milestoneId, slice.id, "REPLAN");
827
837
  if (!replanPath) {
@@ -898,7 +908,7 @@ export async function runGSDDoctor(basePath, options) {
898
908
  fixable: true,
899
909
  });
900
910
  dryRunCanFix("all_tasks_done_roadmap_not_checked", `mark ${slice.id} done in roadmap`);
901
- if (shouldFix("all_tasks_done_roadmap_not_checked") && (hasSliceSummary || issues.some(issue => issue.code === "all_tasks_done_missing_slice_summary" && issue.unitId === unitId))) {
911
+ if (shouldFix("all_tasks_done_roadmap_not_checked") && (hasSliceSummary || existsSync(join(slicePath, `${slice.id}-SUMMARY.md`)))) {
902
912
  await markSliceDoneInRoadmap(basePath, milestoneId, slice.id, fixesApplied);
903
913
  }
904
914
  }
@@ -0,0 +1,40 @@
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
+ import { DevWorkflowEngine } from "./dev-workflow-engine.js";
10
+ import { DevExecutionPolicy } from "./dev-execution-policy.js";
11
+ import { CustomWorkflowEngine } from "./custom-workflow-engine.js";
12
+ import { CustomExecutionPolicy } from "./custom-execution-policy.js";
13
+ /**
14
+ * Resolve an engine/policy pair for the given session.
15
+ *
16
+ * - `null` or `"dev"` → DevWorkflowEngine + DevExecutionPolicy
17
+ * - any other non-null ID → CustomWorkflowEngine(activeRunDir) + CustomExecutionPolicy()
18
+ * (requires activeRunDir to be a non-empty string)
19
+ *
20
+ * Note: `GSD_ENGINE_BYPASS=1` is checked in autoLoop before calling this function.
21
+ */
22
+ export function resolveEngine(session) {
23
+ const { activeEngineId, activeRunDir } = session;
24
+ if (activeEngineId === null || activeEngineId === "dev") {
25
+ return {
26
+ engine: new DevWorkflowEngine(),
27
+ policy: new DevExecutionPolicy(),
28
+ };
29
+ }
30
+ // Any non-null, non-"dev" engine ID is a custom workflow engine.
31
+ // activeRunDir is required — the engine reads GRAPH.yaml from it.
32
+ if (!activeRunDir || typeof activeRunDir !== "string") {
33
+ throw new Error(`Custom engine "${activeEngineId}" requires activeRunDir to be a non-empty string, ` +
34
+ `got: ${JSON.stringify(activeRunDir)}`);
35
+ }
36
+ return {
37
+ engine: new CustomWorkflowEngine(activeRunDir),
38
+ policy: new CustomExecutionPolicy(activeRunDir),
39
+ };
40
+ }
@@ -0,0 +1,8 @@
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
+ export {};
@@ -0,0 +1,8 @@
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
+ export {};
@@ -4,8 +4,18 @@ export function registerExitCommand(pi, deps = {}) {
4
4
  description: "Exit GSD gracefully",
5
5
  handler: async (_args, ctx) => {
6
6
  // Stop auto-mode first so locks and activity state are cleaned up before shutdown.
7
- const stopAuto = deps.stopAuto ?? (await importExtensionModule(import.meta.url, "./auto.js")).stopAuto;
8
- await stopAuto(ctx, pi, "Graceful exit");
7
+ // Wrapped in try/catch: if gsd-pi was updated on disk mid-session, the dynamic
8
+ // import may resolve a new auto-worktree.js whose static imports reference
9
+ // exports absent from the process-cached native-git-bridge.js (ESM cache is
10
+ // immutable). The user's work is already saved — this is cleanup only.
11
+ try {
12
+ const stopAuto = deps.stopAuto ?? (await importExtensionModule(import.meta.url, "./auto.js")).stopAuto;
13
+ await stopAuto(ctx, pi, "Graceful exit");
14
+ }
15
+ catch (e) {
16
+ const msg = e instanceof Error ? e.message : String(e);
17
+ ctx.ui?.notify?.(`Auto-mode cleanup skipped (module version mismatch): ${msg}`, "warning");
18
+ }
9
19
  ctx.shutdown();
10
20
  },
11
21
  });
@@ -2,7 +2,7 @@
2
2
  // Generate shareable reports of milestone work in JSON or markdown format.
3
3
  import { writeFileSync, mkdirSync } from "node:fs";
4
4
  import { join, basename } from "node:path";
5
- import { exec } from "node:child_process";
5
+ import { execFile } from "node:child_process";
6
6
  import { getLedger, getProjectTotals, aggregateByPhase, aggregateBySlice, aggregateByModel, formatCost, formatTokenCount, loadLedgerFromDisk, } from "./metrics.js";
7
7
  import { gsdRoot } from "./paths.js";
8
8
  import { formatDuration, fileLink } from "../shared/format-utils.js";
@@ -13,18 +13,14 @@ import { getErrorMessage } from "./error-utils.js";
13
13
  * Non-blocking, non-fatal — failures are silently ignored.
14
14
  */
15
15
  export function openInBrowser(filePath) {
16
- const cmd = process.platform === "darwin" ? "open" :
17
- process.platform === "win32" ? "start" :
18
- "xdg-open";
19
- // On Windows, `start` needs an empty title argument when the path has spaces
20
- const args = process.platform === "win32"
21
- ? `"" "${filePath}"`
22
- : `"${filePath}"`;
23
- exec(`${cmd} ${args}`, (err) => {
24
- // Non-fatal — if the browser can't be opened, the file path is still shown
25
- if (err)
26
- void err;
27
- });
16
+ if (process.platform === "win32") {
17
+ // PowerShell's Start-Process handles paths with '&' and spaces safely.
18
+ execFile("powershell", ["-c", `Start-Process '${filePath.replace(/'/g, "''")}'`], () => { });
19
+ }
20
+ else {
21
+ const cmd = process.platform === "darwin" ? "open" : "xdg-open";
22
+ execFile(cmd, [filePath], () => { });
23
+ }
28
24
  }
29
25
  /**
30
26
  * Write an export file directly, without requiring an ExtensionCommandContext.
@@ -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"],
@@ -309,19 +309,36 @@ function _parsePlanImpl(content) {
309
309
  let currentTask = null;
310
310
  for (const line of taskLines) {
311
311
  const cbMatch = line.match(/^-\s+\[([ xX])\]\s+\*\*([\w.]+):\s+(.+?)\*\*\s*(.*)/);
312
- if (cbMatch) {
312
+ // Heading-style: ### T01 -- Title, ### T01: Title, ### T01 — Title
313
+ const hdMatch = !cbMatch ? line.match(/^#{2,4}\s+([\w.]+)\s*(?:--|—|:)\s*(.+)/) : null;
314
+ if (cbMatch || hdMatch) {
313
315
  if (currentTask)
314
316
  tasks.push(currentTask);
315
- const rest = cbMatch[4] || '';
316
- const estMatch = rest.match(/`est:([^`]+)`/);
317
- const estimate = estMatch ? estMatch[1] : '';
318
- currentTask = {
319
- id: cbMatch[2],
320
- title: cbMatch[3],
321
- description: '',
322
- done: cbMatch[1].toLowerCase() === 'x',
323
- estimate,
324
- };
317
+ if (cbMatch) {
318
+ const rest = cbMatch[4] || '';
319
+ const estMatch = rest.match(/`est:([^`]+)`/);
320
+ const estimate = estMatch ? estMatch[1] : '';
321
+ currentTask = {
322
+ id: cbMatch[2],
323
+ title: cbMatch[3],
324
+ description: '',
325
+ done: cbMatch[1].toLowerCase() === 'x',
326
+ estimate,
327
+ };
328
+ }
329
+ else {
330
+ const rest = hdMatch[2] || '';
331
+ const titleEstMatch = rest.match(/^(.+?)\s*`est:([^`]+)`\s*$/);
332
+ const title = titleEstMatch ? titleEstMatch[1].trim() : rest.trim();
333
+ const estimate = titleEstMatch ? titleEstMatch[2] : '';
334
+ currentTask = {
335
+ id: hdMatch[1],
336
+ title,
337
+ description: '',
338
+ done: false,
339
+ estimate,
340
+ };
341
+ }
325
342
  }
326
343
  else if (currentTask && line.match(/^\s*-\s+Files:\s*(.*)/)) {
327
344
  const filesMatch = line.match(/^\s*-\s+Files:\s*(.*)/);
@@ -10,6 +10,7 @@
10
10
  import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
11
11
  import { join, dirname, relative } from "node:path";
12
12
  import { fileURLToPath } from "node:url";
13
+ import { homedir } from "node:os";
13
14
  import { extractTrace } from "./session-forensics.js";
14
15
  import { nativeParseJsonlTail } from "./native-parser-bridge.js";
15
16
  import { MAX_JSONL_BYTES, parseJSONL } from "./jsonl-utils.js";
@@ -23,6 +24,70 @@ import { loadPrompt } from "./prompt-loader.js";
23
24
  import { gsdRoot } from "./paths.js";
24
25
  import { formatDuration } from "../shared/format-utils.js";
25
26
  import { getAutoWorktreePath } from "./auto-worktree.js";
27
+ import { loadEffectiveGSDPreferences, loadGlobalGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
28
+ import { showNextAction } from "../shared/tui.js";
29
+ import { ensurePreferencesFile, serializePreferencesToFrontmatter } from "./commands-prefs-wizard.js";
30
+ // ─── Duplicate Detection ──────────────────────────────────────────────────────
31
+ const DEDUP_PROMPT_SECTION = `
32
+ ## Duplicate Detection (REQUIRED before issue creation)
33
+
34
+ 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.
35
+
36
+ ### Search Steps
37
+
38
+ 1. **Search closed issues** for similar keywords from your diagnosis:
39
+ \`\`\`
40
+ gh issue list --repo gsd-build/gsd-2 --state closed --search "<keywords from root cause>" --limit 20
41
+ \`\`\`
42
+
43
+ 2. **Search open PRs** that might contain the fix:
44
+ \`\`\`
45
+ gh pr list --repo gsd-build/gsd-2 --state open --search "<keywords>" --limit 10
46
+ \`\`\`
47
+
48
+ 3. **Search merged PRs** that may have already fixed this:
49
+ \`\`\`
50
+ gh pr list --repo gsd-build/gsd-2 --state merged --search "<keywords>" --limit 10
51
+ \`\`\`
52
+
53
+ ### Analysis
54
+
55
+ For each result, compare it against your root-cause diagnosis:
56
+ - Does the issue describe the same code path or file?
57
+ - Does the PR modify the same file:line you identified?
58
+ - Is the symptom description semantically similar even if keywords differ?
59
+
60
+ ### Present Findings
61
+
62
+ If you find potential matches, present them to the user:
63
+
64
+ 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.
65
+ 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.
66
+ 3. **"Create new issue anyway"** — when existing results do not cover this specific failure.
67
+
68
+ Only proceed to issue creation if no matches were found OR the user explicitly chooses "Create new issue anyway".
69
+ `;
70
+ async function writeForensicsDedupPref(ctx, enabled) {
71
+ const prefsPath = getGlobalGSDPreferencesPath();
72
+ await ensurePreferencesFile(prefsPath, ctx, "global");
73
+ const existing = loadGlobalGSDPreferences();
74
+ const prefs = existing?.preferences ? { ...existing.preferences } : {};
75
+ prefs.version = prefs.version || 1;
76
+ prefs.forensics_dedup = enabled;
77
+ const frontmatter = serializePreferencesToFrontmatter(prefs);
78
+ const raw = existsSync(prefsPath) ? readFileSync(prefsPath, "utf-8") : "";
79
+ let body = "\n# GSD Skill Preferences\n\nSee `~/.gsd/agent/extensions/gsd/docs/preferences-reference.md` for full field documentation and examples.\n";
80
+ const start = raw.startsWith("---\n") ? 4 : raw.startsWith("---\r\n") ? 5 : -1;
81
+ if (start !== -1) {
82
+ const closingIdx = raw.indexOf("\n---", start);
83
+ if (closingIdx !== -1) {
84
+ const after = raw.slice(closingIdx + 4);
85
+ if (after.trim())
86
+ body = after;
87
+ }
88
+ }
89
+ writeFileSync(prefsPath, `---\n${frontmatter}---${body}`, "utf-8");
90
+ }
26
91
  // ─── Entry Point ──────────────────────────────────────────────────────────────
27
92
  export async function handleForensics(args, ctx, pi) {
28
93
  if (isAutoActive()) {
@@ -43,17 +108,43 @@ export async function handleForensics(args, ctx, pi) {
43
108
  ctx.ui.notify("Problem description required for forensic analysis.", "warning");
44
109
  return;
45
110
  }
111
+ // ─── Duplicate detection opt-in ─────────────────────────────────────────────
112
+ const effectivePrefs = loadEffectiveGSDPreferences()?.preferences;
113
+ let dedupEnabled = effectivePrefs?.forensics_dedup === true;
114
+ if (effectivePrefs?.forensics_dedup === undefined) {
115
+ const choice = await showNextAction(ctx, {
116
+ title: "Duplicate detection available",
117
+ summary: ["Before filing a GitHub issue, forensics can search existing issues and PRs to avoid duplicates.", "This uses additional AI tokens for analysis."],
118
+ actions: [
119
+ { id: "enable", label: "Enable duplicate detection", description: "Search issues/PRs before filing (recommended)", recommended: true },
120
+ { id: "skip", label: "Skip for now", description: "File without checking for duplicates" },
121
+ ],
122
+ notYetMessage: "You can enable this later via preferences (forensics_dedup: true).",
123
+ });
124
+ if (choice === "enable") {
125
+ await writeForensicsDedupPref(ctx, true);
126
+ dedupEnabled = true;
127
+ }
128
+ }
129
+ const dedupSection = dedupEnabled ? DEDUP_PROMPT_SECTION : "";
46
130
  ctx.ui.notify("Building forensic report...", "info");
47
131
  const report = await buildForensicReport(basePath);
48
132
  const savedPath = saveForensicReport(basePath, report, problemDescription);
49
- // Derive GSD source dir for prompt
50
- const __extensionDir = dirname(fileURLToPath(import.meta.url));
51
- const gsdSourceDir = __extensionDir;
133
+ // Derive GSD source dir for prompt — fall back to ~/.gsd/agent/extensions/gsd/
134
+ // when import.meta.url resolves to the npm-global install path (Windows).
135
+ let gsdSourceDir = dirname(fileURLToPath(import.meta.url));
136
+ if (!existsSync(join(gsdSourceDir, "prompts"))) {
137
+ const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
138
+ const fallback = join(gsdHome, "agent", "extensions", "gsd");
139
+ if (existsSync(join(fallback, "prompts")))
140
+ gsdSourceDir = fallback;
141
+ }
52
142
  const forensicData = formatReportForPrompt(report);
53
143
  const content = loadPrompt("forensics", {
54
144
  problemDescription,
55
145
  forensicData,
56
146
  gsdSourceDir,
147
+ dedupSection,
57
148
  });
58
149
  ctx.ui.notify(`Forensic report saved: ${relative(basePath, savedPath)}`, "info");
59
150
  pi.sendMessage({ customType: "gsd-forensics", content, display: false }, { triggerTurn: true });
@@ -7,4 +7,5 @@ export const GIT_NO_PROMPT_ENV = {
7
7
  GIT_TERMINAL_PROMPT: "0",
8
8
  GIT_ASKPASS: "",
9
9
  GIT_SVN_ID: "",
10
+ LC_ALL: "C", // force English git output so stderr string checks work on all locales (#1997)
10
11
  };
@@ -130,7 +130,7 @@ export function readIntegrationBranch(basePath, milestoneId) {
130
130
  */
131
131
  /** Regex matching GSD quick-task branches: gsd/quick/<num>-<slug> */
132
132
  export const QUICK_BRANCH_RE = /^gsd\/quick\//;
133
- export function writeIntegrationBranch(basePath, milestoneId, branch, _options) {
133
+ export function writeIntegrationBranch(basePath, milestoneId, branch) {
134
134
  // Don't record slice branches as the integration target
135
135
  if (SLICE_BRANCH_RE.test(branch))
136
136
  return;
@@ -508,7 +508,11 @@ export class GitServiceImpl {
508
508
  */
509
509
  export function createDraftPR(basePath, milestoneId, title, body) {
510
510
  try {
511
- const result = execSync(`gh pr create --draft --title ${JSON.stringify(title)} --body ${JSON.stringify(body)}`, { cwd: basePath, encoding: "utf8", timeout: 30000, env: GIT_NO_PROMPT_ENV });
511
+ const result = execFileSync("gh", [
512
+ "pr", "create", "--draft",
513
+ "--title", title,
514
+ "--body", body,
515
+ ], { cwd: basePath, encoding: "utf8", timeout: 30000, env: GIT_NO_PROMPT_ENV });
512
516
  return result.trim();
513
517
  }
514
518
  catch {