gsd-pi 2.76.0 → 2.77.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (536) hide show
  1. package/README.md +45 -25
  2. package/dist/claude-cli-check.js +32 -3
  3. package/dist/mcp-server.d.ts +7 -0
  4. package/dist/mcp-server.js +35 -1
  5. package/dist/onboarding.js +45 -0
  6. package/dist/resource-loader.d.ts +1 -1
  7. package/dist/resource-loader.js +2 -8
  8. package/dist/resources/agents/researcher.md +1 -1
  9. package/dist/resources/extensions/claude-code-cli/readiness.js +31 -8
  10. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +77 -17
  11. package/dist/resources/extensions/gsd/auto/loop.js +9 -0
  12. package/dist/resources/extensions/gsd/auto/phases.js +104 -11
  13. package/dist/resources/extensions/gsd/auto/run-unit.js +38 -2
  14. package/dist/resources/extensions/gsd/auto/session.js +22 -1
  15. package/dist/resources/extensions/gsd/auto-dispatch.js +16 -3
  16. package/dist/resources/extensions/gsd/auto-model-selection.js +53 -16
  17. package/dist/resources/extensions/gsd/auto-post-unit.js +25 -2
  18. package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
  19. package/dist/resources/extensions/gsd/auto-recovery.js +32 -1
  20. package/dist/resources/extensions/gsd/auto-start.js +58 -57
  21. package/dist/resources/extensions/gsd/auto-verification.js +33 -0
  22. package/dist/resources/extensions/gsd/auto-worktree.js +51 -53
  23. package/dist/resources/extensions/gsd/auto.js +70 -28
  24. package/dist/resources/extensions/gsd/blocked-models.js +68 -0
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +93 -1
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +39 -9
  27. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +93 -0
  28. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +3 -0
  29. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +12 -0
  30. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +52 -6
  31. package/dist/resources/extensions/gsd/bootstrap/system-context.js +84 -23
  32. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
  33. package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
  34. package/dist/resources/extensions/gsd/commands-extract-learnings.js +54 -89
  35. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
  36. package/dist/resources/extensions/gsd/compaction-snapshot.js +121 -0
  37. package/dist/resources/extensions/gsd/complexity-classifier.js +5 -3
  38. package/dist/resources/extensions/gsd/db-writer.js +88 -16
  39. package/dist/resources/extensions/gsd/doctor-git-checks.js +23 -29
  40. package/dist/resources/extensions/gsd/doctor-providers.js +51 -5
  41. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +1 -0
  42. package/dist/resources/extensions/gsd/error-classifier.js +31 -3
  43. package/dist/resources/extensions/gsd/exec-history.js +120 -0
  44. package/dist/resources/extensions/gsd/exec-sandbox.js +258 -0
  45. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  46. package/dist/resources/extensions/gsd/gsd-db.js +168 -23
  47. package/dist/resources/extensions/gsd/guided-flow.js +190 -1
  48. package/dist/resources/extensions/gsd/health-widget.js +4 -1
  49. package/dist/resources/extensions/gsd/hook-emitter.js +108 -0
  50. package/dist/resources/extensions/gsd/init-wizard.js +15 -1
  51. package/dist/resources/extensions/gsd/key-manager.js +28 -0
  52. package/dist/resources/extensions/gsd/memory-backfill.js +126 -0
  53. package/dist/resources/extensions/gsd/memory-store.js +19 -0
  54. package/dist/resources/extensions/gsd/model-router.js +36 -3
  55. package/dist/resources/extensions/gsd/pre-execution-checks.js +44 -9
  56. package/dist/resources/extensions/gsd/preferences-types.js +9 -0
  57. package/dist/resources/extensions/gsd/preferences-validation.js +83 -0
  58. package/dist/resources/extensions/gsd/preferences.js +17 -17
  59. package/dist/resources/extensions/gsd/prompt-loader.js +22 -7
  60. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  61. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  62. package/dist/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
  63. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
  64. package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
  65. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
  66. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  67. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  68. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -0
  69. package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
  70. package/dist/resources/extensions/gsd/safety/file-change-validator.js +13 -5
  71. package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
  72. package/dist/resources/extensions/gsd/state.js +43 -4
  73. package/dist/resources/extensions/gsd/token-counter.js +22 -5
  74. package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
  75. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +59 -0
  76. package/dist/resources/extensions/gsd/tools/exec-tool.js +126 -0
  77. package/dist/resources/extensions/gsd/tools/memory-tools.js +26 -1
  78. package/dist/resources/extensions/gsd/tools/resume-tool.js +23 -0
  79. package/dist/resources/extensions/gsd/uok/plan-v2.js +20 -3
  80. package/dist/resources/extensions/gsd/workflow-mcp.js +3 -0
  81. package/dist/resources/extensions/gsd/workflow-templates/spike.md +6 -0
  82. package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
  83. package/dist/resources/extensions/search-the-web/command-search-provider.js +5 -4
  84. package/dist/resources/extensions/search-the-web/native-search.js +45 -13
  85. package/dist/resources/skills/api-design/SKILL.md +190 -0
  86. package/dist/resources/skills/create-mcp-server/SKILL.md +121 -0
  87. package/dist/resources/skills/decompose-into-slices/SKILL.md +139 -0
  88. package/dist/resources/skills/dependency-upgrade/SKILL.md +158 -0
  89. package/dist/resources/skills/design-an-interface/SKILL.md +102 -0
  90. package/dist/resources/skills/forensics/SKILL.md +153 -0
  91. package/dist/resources/skills/grill-me/SKILL.md +93 -0
  92. package/dist/resources/skills/handoff/SKILL.md +121 -0
  93. package/dist/resources/skills/observability/SKILL.md +174 -0
  94. package/dist/resources/skills/security-review/SKILL.md +181 -0
  95. package/dist/resources/skills/spike-wrap-up/SKILL.md +138 -0
  96. package/dist/resources/skills/tdd/SKILL.md +112 -0
  97. package/dist/resources/skills/verify-before-complete/SKILL.md +98 -0
  98. package/dist/resources/skills/write-docs/SKILL.md +82 -0
  99. package/dist/resources/skills/write-milestone-brief/SKILL.md +135 -0
  100. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  101. package/dist/web/standalone/.next/BUILD_ID +1 -1
  102. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  103. package/dist/web/standalone/.next/build-manifest.json +2 -2
  104. package/dist/web/standalone/.next/required-server-files.json +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/index.html +1 -1
  122. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  129. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  130. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/middleware-manifest.json +1 -1
  132. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  133. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  134. package/dist/web/standalone/server.js +1 -1
  135. package/dist/welcome-screen.js +6 -1
  136. package/dist/wizard.js +2 -0
  137. package/package.json +1 -1
  138. package/packages/daemon/package.json +2 -2
  139. package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
  140. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
  141. package/packages/mcp-server/dist/remote-questions.js +732 -0
  142. package/packages/mcp-server/dist/remote-questions.js.map +1 -0
  143. package/packages/mcp-server/dist/server.d.ts +7 -0
  144. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  145. package/packages/mcp-server/dist/server.js +70 -8
  146. package/packages/mcp-server/dist/server.js.map +1 -1
  147. package/packages/mcp-server/dist/session-manager.d.ts +14 -0
  148. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
  149. package/packages/mcp-server/dist/session-manager.js +49 -1
  150. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  151. package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
  152. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  153. package/packages/mcp-server/dist/workflow-tools.js +163 -25
  154. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  155. package/packages/mcp-server/package.json +4 -3
  156. package/packages/mcp-server/src/mcp-server.test.ts +67 -0
  157. package/packages/mcp-server/src/remote-questions.test.ts +294 -0
  158. package/packages/mcp-server/src/remote-questions.ts +916 -0
  159. package/packages/mcp-server/src/server.ts +89 -14
  160. package/packages/mcp-server/src/session-manager.ts +43 -1
  161. package/packages/mcp-server/src/workflow-tools.test.ts +146 -1
  162. package/packages/mcp-server/src/workflow-tools.ts +215 -43
  163. package/packages/mcp-server/tsconfig.test.json +19 -0
  164. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  165. package/packages/native/package.json +1 -1
  166. package/packages/pi-agent-core/dist/agent-loop.js +12 -0
  167. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  168. package/packages/pi-agent-core/dist/types.d.ts +30 -0
  169. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  170. package/packages/pi-agent-core/dist/types.js.map +1 -1
  171. package/packages/pi-agent-core/package.json +1 -1
  172. package/packages/pi-agent-core/src/agent-loop.ts +14 -0
  173. package/packages/pi-agent-core/src/types.ts +34 -0
  174. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  175. package/packages/pi-ai/dist/models/custom.d.ts +38 -0
  176. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
  177. package/packages/pi-ai/dist/models/custom.js +41 -0
  178. package/packages/pi-ai/dist/models/custom.js.map +1 -1
  179. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
  180. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  181. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts +2 -0
  182. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts.map +1 -0
  183. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +13 -0
  184. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -0
  185. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  186. package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
  187. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  188. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  189. package/packages/pi-ai/dist/providers/anthropic.js +13 -4
  190. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  191. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
  192. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
  193. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
  194. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
  195. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  196. package/packages/pi-ai/dist/providers/openai-completions.js +60 -15
  197. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  198. package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
  199. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  200. package/packages/pi-ai/dist/providers/simple-options.js +16 -1
  201. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  202. package/packages/pi-ai/dist/providers/think-tag-parser.d.ts +17 -0
  203. package/packages/pi-ai/dist/providers/think-tag-parser.d.ts.map +1 -0
  204. package/packages/pi-ai/dist/providers/think-tag-parser.js +75 -0
  205. package/packages/pi-ai/dist/providers/think-tag-parser.js.map +1 -0
  206. package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts +2 -0
  207. package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts.map +1 -0
  208. package/packages/pi-ai/dist/providers/think-tag-parser.test.js +41 -0
  209. package/packages/pi-ai/dist/providers/think-tag-parser.test.js.map +1 -0
  210. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  211. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +12 -2
  212. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  213. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +164 -14
  214. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
  215. package/packages/pi-ai/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
  216. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js +15 -3
  217. package/packages/pi-ai/dist/utils/oauth/google-antigravity.js.map +1 -1
  218. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts +2 -0
  219. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts.map +1 -0
  220. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +67 -0
  221. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -0
  222. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
  223. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js +16 -3
  224. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js.map +1 -1
  225. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts +2 -0
  226. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts.map +1 -0
  227. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +67 -0
  228. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -0
  229. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +2 -0
  230. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +1 -0
  231. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +289 -0
  232. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +1 -0
  233. package/packages/pi-ai/package.json +1 -1
  234. package/packages/pi-ai/src/models/custom.ts +42 -0
  235. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
  236. package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -0
  237. package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
  238. package/packages/pi-ai/src/providers/anthropic.ts +15 -4
  239. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
  240. package/packages/pi-ai/src/providers/openai-completions.ts +57 -16
  241. package/packages/pi-ai/src/providers/simple-options.ts +17 -1
  242. package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
  243. package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
  244. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +200 -23
  245. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +12 -2
  246. package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +84 -0
  247. package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +15 -5
  248. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +84 -0
  249. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +16 -5
  250. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +363 -0
  251. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  252. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
  253. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  254. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
  255. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  256. package/packages/pi-coding-agent/dist/core/agent-session.js +32 -2
  257. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  259. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  260. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  261. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  262. package/packages/pi-coding-agent/dist/core/extensions/loader.js +4 -0
  263. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  264. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +35 -2
  265. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/extensions/runner.js +233 -0
  267. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +205 -2
  269. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts +53 -0
  272. package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts.map +1 -0
  273. package/packages/pi-coding-agent/dist/core/hooks-runner.js +337 -0
  274. package/packages/pi-coding-agent/dist/core/hooks-runner.js.map +1 -0
  275. package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts +2 -0
  276. package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts.map +1 -0
  277. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +234 -0
  278. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -0
  279. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
  280. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/index.js +1 -0
  282. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/model-discovery.d.ts +3 -1
  284. package/packages/pi-coding-agent/dist/core/model-discovery.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/model-discovery.js +92 -12
  286. package/packages/pi-coding-agent/dist/core/model-discovery.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/model-discovery.test.js +16 -1
  288. package/packages/pi-coding-agent/dist/core/model-discovery.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts +2 -0
  290. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts.map +1 -0
  291. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js +40 -0
  292. package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js.map +1 -0
  293. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
  294. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
  295. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
  296. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
  297. package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js +61 -1
  298. package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js.map +1 -1
  299. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +5 -0
  300. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  301. package/packages/pi-coding-agent/dist/core/model-registry.js +90 -10
  302. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts +2 -0
  304. package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts.map +1 -0
  305. package/packages/pi-coding-agent/dist/core/redact-secrets.js +49 -0
  306. package/packages/pi-coding-agent/dist/core/redact-secrets.js.map +1 -0
  307. package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts +2 -0
  308. package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts.map +1 -0
  309. package/packages/pi-coding-agent/dist/core/redact-secrets.test.js +67 -0
  310. package/packages/pi-coding-agent/dist/core/redact-secrets.test.js.map +1 -0
  311. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/session-manager.js +10 -6
  313. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/session-manager.test.js +45 -1
  315. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +55 -0
  317. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  318. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  320. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  321. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
  323. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
  325. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  326. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +13 -7
  328. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
  330. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
  332. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  333. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  334. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
  335. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  336. package/packages/pi-coding-agent/package.json +1 -1
  337. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
  338. package/packages/pi-coding-agent/src/core/agent-session.ts +38 -2
  339. package/packages/pi-coding-agent/src/core/extensions/index.ts +16 -0
  340. package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
  341. package/packages/pi-coding-agent/src/core/extensions/runner.ts +351 -0
  342. package/packages/pi-coding-agent/src/core/extensions/types.ts +258 -0
  343. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +269 -0
  344. package/packages/pi-coding-agent/src/core/hooks-runner.ts +460 -0
  345. package/packages/pi-coding-agent/src/core/index.ts +10 -0
  346. package/packages/pi-coding-agent/src/core/model-discovery.test.ts +19 -0
  347. package/packages/pi-coding-agent/src/core/model-discovery.ts +99 -12
  348. package/packages/pi-coding-agent/src/core/model-registry-auth-header.test.ts +44 -0
  349. package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
  350. package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +75 -0
  351. package/packages/pi-coding-agent/src/core/model-registry.ts +102 -10
  352. package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
  353. package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
  354. package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -1
  355. package/packages/pi-coding-agent/src/core/session-manager.ts +10 -6
  356. package/packages/pi-coding-agent/src/core/settings-manager.ts +57 -0
  357. package/packages/pi-coding-agent/src/index.ts +16 -0
  358. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
  359. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -7
  360. package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
  361. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
  362. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  363. package/packages/pi-tui/package.json +1 -1
  364. package/packages/rpc-client/package.json +1 -1
  365. package/pkg/package.json +1 -1
  366. package/scripts/link-workspace-packages.cjs +1 -0
  367. package/src/resources/agents/researcher.md +1 -1
  368. package/src/resources/extensions/claude-code-cli/readiness.ts +32 -8
  369. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +78 -17
  370. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +149 -5
  371. package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -0
  372. package/src/resources/extensions/gsd/auto/loop.ts +9 -0
  373. package/src/resources/extensions/gsd/auto/phases.ts +131 -10
  374. package/src/resources/extensions/gsd/auto/run-unit.ts +40 -2
  375. package/src/resources/extensions/gsd/auto/session.ts +35 -2
  376. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -3
  377. package/src/resources/extensions/gsd/auto-model-selection.ts +71 -15
  378. package/src/resources/extensions/gsd/auto-post-unit.ts +29 -3
  379. package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
  380. package/src/resources/extensions/gsd/auto-recovery.ts +26 -1
  381. package/src/resources/extensions/gsd/auto-start.ts +60 -68
  382. package/src/resources/extensions/gsd/auto-verification.ts +33 -0
  383. package/src/resources/extensions/gsd/auto-worktree.ts +62 -63
  384. package/src/resources/extensions/gsd/auto.ts +73 -28
  385. package/src/resources/extensions/gsd/blocked-models.ts +98 -0
  386. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +120 -1
  387. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +40 -9
  388. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +109 -0
  389. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +5 -0
  390. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -0
  391. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +54 -6
  392. package/src/resources/extensions/gsd/bootstrap/system-context.ts +89 -26
  393. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
  394. package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
  395. package/src/resources/extensions/gsd/commands-extract-learnings.ts +55 -90
  396. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
  397. package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
  398. package/src/resources/extensions/gsd/complexity-classifier.ts +5 -3
  399. package/src/resources/extensions/gsd/db-writer.ts +88 -17
  400. package/src/resources/extensions/gsd/doctor-git-checks.ts +23 -27
  401. package/src/resources/extensions/gsd/doctor-providers.ts +59 -6
  402. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +2 -0
  403. package/src/resources/extensions/gsd/error-classifier.ts +36 -3
  404. package/src/resources/extensions/gsd/exec-history.ts +153 -0
  405. package/src/resources/extensions/gsd/exec-sandbox.ts +326 -0
  406. package/src/resources/extensions/gsd/gitignore.ts +1 -1
  407. package/src/resources/extensions/gsd/gsd-db.ts +186 -23
  408. package/src/resources/extensions/gsd/guided-flow.ts +222 -1
  409. package/src/resources/extensions/gsd/health-widget.ts +3 -1
  410. package/src/resources/extensions/gsd/hook-emitter.ts +188 -0
  411. package/src/resources/extensions/gsd/init-wizard.ts +15 -1
  412. package/src/resources/extensions/gsd/journal.ts +2 -1
  413. package/src/resources/extensions/gsd/key-manager.ts +28 -0
  414. package/src/resources/extensions/gsd/memory-backfill.ts +140 -0
  415. package/src/resources/extensions/gsd/memory-store.ts +26 -0
  416. package/src/resources/extensions/gsd/model-router.ts +42 -1
  417. package/src/resources/extensions/gsd/pre-execution-checks.ts +46 -10
  418. package/src/resources/extensions/gsd/preferences-types.ts +46 -0
  419. package/src/resources/extensions/gsd/preferences-validation.ts +79 -0
  420. package/src/resources/extensions/gsd/preferences.ts +17 -17
  421. package/src/resources/extensions/gsd/prompt-loader.ts +30 -7
  422. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  423. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
  424. package/src/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
  425. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
  426. package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
  427. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
  428. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  429. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  430. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -0
  431. package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
  432. package/src/resources/extensions/gsd/safety/file-change-validator.ts +17 -4
  433. package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
  434. package/src/resources/extensions/gsd/state.ts +45 -4
  435. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +188 -2
  436. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +95 -1
  437. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
  438. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +49 -0
  439. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
  440. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +33 -3
  441. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +38 -0
  442. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
  443. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +98 -0
  444. package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +54 -0
  445. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
  446. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +68 -66
  447. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +123 -0
  448. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
  449. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  450. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  451. package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +3 -3
  452. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
  453. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +42 -0
  454. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +8 -4
  455. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +148 -3
  456. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
  457. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +306 -1
  458. package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
  459. package/src/resources/extensions/gsd/tests/exec-history.test.ts +237 -0
  460. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +210 -0
  461. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +58 -0
  462. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +40 -9
  463. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +62 -0
  464. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +447 -1
  465. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
  466. package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +11 -0
  467. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +78 -0
  468. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +1 -0
  469. package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
  470. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
  471. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +1 -1
  472. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +1 -1
  473. package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
  474. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +37 -0
  475. package/src/resources/extensions/gsd/tests/key-manager.test.ts +9 -0
  476. package/src/resources/extensions/gsd/tests/load-memory-block.test.ts +36 -0
  477. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  478. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
  479. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  480. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
  481. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
  482. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +14 -0
  483. package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
  484. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +356 -0
  485. package/src/resources/extensions/gsd/tests/preferences.test.ts +110 -0
  486. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
  487. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
  488. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +103 -4
  489. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
  490. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
  491. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
  492. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
  493. package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
  494. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
  495. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
  496. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
  497. package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
  498. package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
  499. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +23 -0
  500. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -3
  501. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
  502. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
  503. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
  504. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
  505. package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
  506. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +3 -1
  507. package/src/resources/extensions/gsd/token-counter.ts +22 -5
  508. package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
  509. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
  510. package/src/resources/extensions/gsd/tools/exec-tool.ts +183 -0
  511. package/src/resources/extensions/gsd/tools/memory-tools.ts +31 -1
  512. package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
  513. package/src/resources/extensions/gsd/uok/plan-v2.ts +26 -3
  514. package/src/resources/extensions/gsd/workflow-logger.ts +4 -1
  515. package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
  516. package/src/resources/extensions/gsd/workflow-templates/spike.md +6 -0
  517. package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
  518. package/src/resources/extensions/search-the-web/command-search-provider.ts +5 -4
  519. package/src/resources/extensions/search-the-web/native-search.ts +48 -12
  520. package/src/resources/skills/api-design/SKILL.md +190 -0
  521. package/src/resources/skills/create-mcp-server/SKILL.md +121 -0
  522. package/src/resources/skills/decompose-into-slices/SKILL.md +139 -0
  523. package/src/resources/skills/dependency-upgrade/SKILL.md +158 -0
  524. package/src/resources/skills/design-an-interface/SKILL.md +102 -0
  525. package/src/resources/skills/forensics/SKILL.md +153 -0
  526. package/src/resources/skills/grill-me/SKILL.md +93 -0
  527. package/src/resources/skills/handoff/SKILL.md +121 -0
  528. package/src/resources/skills/observability/SKILL.md +174 -0
  529. package/src/resources/skills/security-review/SKILL.md +181 -0
  530. package/src/resources/skills/spike-wrap-up/SKILL.md +138 -0
  531. package/src/resources/skills/tdd/SKILL.md +112 -0
  532. package/src/resources/skills/verify-before-complete/SKILL.md +98 -0
  533. package/src/resources/skills/write-docs/SKILL.md +82 -0
  534. package/src/resources/skills/write-milestone-brief/SKILL.md +135 -0
  535. /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_buildManifest.js +0 -0
  536. /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_ssgManifest.js +0 -0
@@ -0,0 +1,188 @@
1
+ // GSD Extension — Layer 2 Event Emitter Bridge
2
+ //
3
+ // Holds a module-scoped reference to the ExtensionAPI so deeply-nested code
4
+ // (auto-loop, git-service callers, verification, budget) can emit Layer 2
5
+ // events without having to thread `pi` through every function signature.
6
+ //
7
+ // Set once from `registerGsdExtension`. All emitters are best-effort — a
8
+ // missing `pi` (e.g. in standalone unit tests) silently becomes a no-op.
9
+
10
+ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
11
+ import type {
12
+ BeforeCommitEventResult,
13
+ BeforePrEventResult,
14
+ BeforePushEventResult,
15
+ BeforeVerifyEventResult,
16
+ BudgetThresholdEventResult,
17
+ VerifyFailure,
18
+ } from "@gsd/pi-coding-agent";
19
+
20
+ let _pi: ExtensionAPI | undefined;
21
+
22
+ export function setHookEmitter(pi: ExtensionAPI): void {
23
+ _pi = pi;
24
+ }
25
+
26
+ export function clearHookEmitter(): void {
27
+ _pi = undefined;
28
+ }
29
+
30
+ // ─── Notification ──────────────────────────────────────────────────────────
31
+
32
+ export async function emitNotification(
33
+ kind: "blocked" | "input_needed" | "milestone_ready" | "idle" | "error",
34
+ message: string,
35
+ details?: Record<string, unknown>,
36
+ ): Promise<void> {
37
+ if (!_pi) return;
38
+ await _pi.emitExtensionEvent({ type: "notification", kind, message, details });
39
+ }
40
+
41
+ // ─── Git Lifecycle ─────────────────────────────────────────────────────────
42
+
43
+ export async function emitBeforeCommit(args: {
44
+ message: string;
45
+ files: string[];
46
+ cwd: string;
47
+ author?: string;
48
+ }): Promise<BeforeCommitEventResult | undefined> {
49
+ if (!_pi) return undefined;
50
+ return (await _pi.emitExtensionEvent({
51
+ type: "before_commit",
52
+ ...args,
53
+ })) as BeforeCommitEventResult | undefined;
54
+ }
55
+
56
+ export async function emitCommit(args: {
57
+ sha: string;
58
+ message: string;
59
+ files: string[];
60
+ cwd: string;
61
+ }): Promise<void> {
62
+ if (!_pi) return;
63
+ await _pi.emitExtensionEvent({ type: "commit", ...args });
64
+ }
65
+
66
+ export async function emitBeforePush(args: {
67
+ remote: string;
68
+ branch: string;
69
+ cwd: string;
70
+ }): Promise<BeforePushEventResult | undefined> {
71
+ if (!_pi) return undefined;
72
+ return (await _pi.emitExtensionEvent({
73
+ type: "before_push",
74
+ ...args,
75
+ })) as BeforePushEventResult | undefined;
76
+ }
77
+
78
+ export async function emitPush(args: { remote: string; branch: string; cwd: string }): Promise<void> {
79
+ if (!_pi) return;
80
+ await _pi.emitExtensionEvent({ type: "push", ...args });
81
+ }
82
+
83
+ export async function emitBeforePr(args: {
84
+ branch: string;
85
+ targetBranch: string;
86
+ title: string;
87
+ body: string;
88
+ cwd: string;
89
+ }): Promise<BeforePrEventResult | undefined> {
90
+ if (!_pi) return undefined;
91
+ return (await _pi.emitExtensionEvent({
92
+ type: "before_pr",
93
+ ...args,
94
+ })) as BeforePrEventResult | undefined;
95
+ }
96
+
97
+ export async function emitPrOpened(args: {
98
+ url: string;
99
+ branch: string;
100
+ targetBranch: string;
101
+ cwd: string;
102
+ }): Promise<void> {
103
+ if (!_pi) return;
104
+ await _pi.emitExtensionEvent({ type: "pr_opened", ...args });
105
+ }
106
+
107
+ // ─── Verification ──────────────────────────────────────────────────────────
108
+
109
+ export async function emitBeforeVerify(args: {
110
+ unitType?: string;
111
+ unitId?: string;
112
+ cwd: string;
113
+ }): Promise<BeforeVerifyEventResult | undefined> {
114
+ if (!_pi) return undefined;
115
+ return (await _pi.emitExtensionEvent({
116
+ type: "before_verify",
117
+ ...args,
118
+ })) as BeforeVerifyEventResult | undefined;
119
+ }
120
+
121
+ export async function emitVerifyResult(args: {
122
+ passed: boolean;
123
+ failures: VerifyFailure[];
124
+ unitType?: string;
125
+ unitId?: string;
126
+ cwd: string;
127
+ }): Promise<void> {
128
+ if (!_pi) return;
129
+ await _pi.emitExtensionEvent({ type: "verify_result", ...args });
130
+ }
131
+
132
+ // ─── Budget ────────────────────────────────────────────────────────────────
133
+
134
+ export async function emitBudgetThreshold(args: {
135
+ fraction: number;
136
+ spent: number;
137
+ limit: number;
138
+ }): Promise<BudgetThresholdEventResult | undefined> {
139
+ if (!_pi) return undefined;
140
+ return (await _pi.emitExtensionEvent({
141
+ type: "budget_threshold",
142
+ fraction: args.fraction,
143
+ spent: args.spent,
144
+ limit: args.limit,
145
+ currency: "USD",
146
+ })) as BudgetThresholdEventResult | undefined;
147
+ }
148
+
149
+ // ─── Orchestrator Boundaries ───────────────────────────────────────────────
150
+
151
+ export async function emitMilestoneStart(args: {
152
+ milestoneId: string;
153
+ title?: string;
154
+ cwd: string;
155
+ }): Promise<void> {
156
+ if (!_pi) return;
157
+ await _pi.emitExtensionEvent({ type: "milestone_start", ...args });
158
+ }
159
+
160
+ export async function emitMilestoneEnd(args: {
161
+ milestoneId: string;
162
+ status: "completed" | "failed" | "cancelled";
163
+ cwd: string;
164
+ }): Promise<void> {
165
+ if (!_pi) return;
166
+ await _pi.emitExtensionEvent({ type: "milestone_end", ...args });
167
+ }
168
+
169
+ export async function emitUnitStart(args: {
170
+ unitType: string;
171
+ unitId: string;
172
+ milestoneId?: string;
173
+ cwd: string;
174
+ }): Promise<void> {
175
+ if (!_pi) return;
176
+ await _pi.emitExtensionEvent({ type: "unit_start", ...args });
177
+ }
178
+
179
+ export async function emitUnitEnd(args: {
180
+ unitType: string;
181
+ unitId: string;
182
+ milestoneId?: string;
183
+ status: "completed" | "failed" | "cancelled" | "blocked";
184
+ cwd: string;
185
+ }): Promise<void> {
186
+ if (!_pi) return;
187
+ await _pi.emitExtensionEvent({ type: "unit_end", ...args });
188
+ }
@@ -10,7 +10,7 @@ import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent
10
10
  import { existsSync, mkdirSync, writeFileSync, readFileSync } from "node:fs";
11
11
  import { join } from "node:path";
12
12
  import { showNextAction } from "../shared/tui.js";
13
- import { nativeIsRepo, nativeInit } from "./native-git-bridge.js";
13
+ import { nativeIsRepo, nativeInit, nativeAddAll, nativeCommit } from "./native-git-bridge.js";
14
14
  import { ensureGitignore, untrackRuntimeFiles } from "./gitignore.js";
15
15
  import { gsdRoot } from "./paths.js";
16
16
  import { assertSafeDirectory } from "./validate-directory.js";
@@ -74,6 +74,7 @@ export async function showProjectInit(
74
74
  }
75
75
 
76
76
  // ── Step 2: Git setup ──────────────────────────────────────────────────────
77
+ let didInitGit = false;
77
78
  if (!signals.isGitRepo) {
78
79
  const gitChoice = await showNextAction(ctx, {
79
80
  title: "GSD — Project Setup",
@@ -89,6 +90,7 @@ export async function showProjectInit(
89
90
 
90
91
  if (gitChoice === "init_git") {
91
92
  nativeInit(basePath, prefs.mainBranch);
93
+ didInitGit = true;
92
94
  }
93
95
  } else {
94
96
  // Auto-detect main branch from existing repo
@@ -295,6 +297,18 @@ export async function showProjectInit(
295
297
  ensureGitignore(basePath);
296
298
  untrackRuntimeFiles(basePath);
297
299
 
300
+ // Create initial commit so git log and git worktree work immediately (#4530).
301
+ // Without this, the branch is "unborn" (zero commits) and downstream operations
302
+ // like `git log` and `git worktree add` fail.
303
+ if (didInitGit) {
304
+ try {
305
+ nativeAddAll(basePath);
306
+ nativeCommit(basePath, "chore: init project");
307
+ } catch {
308
+ // Non-fatal — user can commit manually; don't block project init
309
+ }
310
+ }
311
+
298
312
  // Auto-generate codebase map for instant agent orientation
299
313
  try {
300
314
  const result = generateCodebaseMap(basePath);
@@ -39,7 +39,8 @@ export type JournalEventType =
39
39
  | "worktree-create-failed"
40
40
  | "worktree-skip"
41
41
  | "worktree-merge-start"
42
- | "worktree-merge-failed";
42
+ | "worktree-merge-failed"
43
+ | "artifact-verification-retry";
43
44
 
44
45
  /** A single structured event in the journal. */
45
46
  export interface JournalEntry {
@@ -35,6 +35,12 @@ export interface ProviderInfo {
35
35
  export const PROVIDER_REGISTRY: ProviderInfo[] = [
36
36
  // LLM Providers
37
37
  { id: "anthropic", label: "Anthropic (Claude)", category: "llm", envVar: "ANTHROPIC_API_KEY", prefixes: ["sk-ant-"], hasOAuth: true, dashboardUrl: "console.anthropic.com" },
38
+ // Claude Code CLI: routes through the local `claude` binary — no API key,
39
+ // authentication is handled by the CLI's own OAuth flow.
40
+ // Referenced by doctor-providers.ts, auto-model-selection.ts, and others;
41
+ // must be in the canonical registry so all consumers see the same catalog.
42
+ // See: https://github.com/gsd-build/gsd-2/issues/4541
43
+ { id: "claude-code", label: "Claude Code CLI", category: "llm", hasOAuth: true },
38
44
  { id: "openai", label: "OpenAI", category: "llm", envVar: "OPENAI_API_KEY", prefixes: ["sk-"], dashboardUrl: "platform.openai.com/api-keys" },
39
45
  { id: "github-copilot", label: "GitHub Copilot", category: "llm", envVar: "GITHUB_TOKEN", hasOAuth: true },
40
46
  { id: "openai-codex", label: "ChatGPT Plus/Pro (Codex)",category: "llm", hasOAuth: true },
@@ -45,6 +51,8 @@ export const PROVIDER_REGISTRY: ProviderInfo[] = [
45
51
  { id: "xai", label: "xAI (Grok)", category: "llm", envVar: "XAI_API_KEY", dashboardUrl: "console.x.ai" },
46
52
  { id: "openrouter", label: "OpenRouter", category: "llm", envVar: "OPENROUTER_API_KEY", dashboardUrl: "openrouter.ai/keys" },
47
53
  { id: "mistral", label: "Mistral", category: "llm", envVar: "MISTRAL_API_KEY", dashboardUrl: "console.mistral.ai" },
54
+ { id: "minimax", label: "MiniMax", category: "llm", envVar: "MINIMAX_API_KEY", dashboardUrl: "platform.minimax.io" },
55
+ { id: "minimax-cn", label: "MiniMax CN", category: "llm", envVar: "MINIMAX_CN_API_KEY", dashboardUrl: "platform.minimax.io" },
48
56
  { id: "ollama-cloud", label: "Ollama Cloud", category: "llm", envVar: "OLLAMA_API_KEY" },
49
57
  { id: "custom-openai", label: "Custom (OpenAI-compat)", category: "llm", envVar: "CUSTOM_OPENAI_API_KEY" },
50
58
  { id: "cerebras", label: "Cerebras", category: "llm", envVar: "CEREBRAS_API_KEY" },
@@ -480,6 +488,26 @@ const TEST_ENDPOINTS: Record<string, { url: string; method?: string; headers?: (
480
488
  url: "https://api.mistral.ai/v1/models",
481
489
  headers: (key) => ({ Authorization: `Bearer ${key}` }),
482
490
  },
491
+ minimax: {
492
+ url: "https://api.minimax.io/anthropic/v1/messages",
493
+ method: "POST",
494
+ headers: (key) => ({
495
+ "x-api-key": key,
496
+ "anthropic-version": "2023-06-01",
497
+ "content-type": "application/json",
498
+ }),
499
+ body: JSON.stringify({ model: "MiniMax-M2.7", max_tokens: 1, messages: [{ role: "user", content: "hi" }] }),
500
+ },
501
+ "minimax-cn": {
502
+ url: "https://api.minimaxi.com/anthropic/v1/messages",
503
+ method: "POST",
504
+ headers: (key) => ({
505
+ "x-api-key": key,
506
+ "anthropic-version": "2023-06-01",
507
+ "content-type": "application/json",
508
+ }),
509
+ body: JSON.stringify({ model: "MiniMax-M2.7", max_tokens: 1, messages: [{ role: "user", content: "hi" }] }),
510
+ },
483
511
  openrouter: {
484
512
  url: "https://openrouter.ai/api/v1/models",
485
513
  headers: (key) => ({ Authorization: `Bearer ${key}` }),
@@ -0,0 +1,140 @@
1
+ // GSD2 — Decisions -> memories backfill (ADR-013 step 5)
2
+ //
3
+ // Idempotent one-shot migration that copies every active decisions row into
4
+ // the memories table with category="architecture" and a structured_fields
5
+ // payload preserving the original gsd_save_decision schema (when_context,
6
+ // scope, decision, choice, rationale, made_by, revisable, sourceDecisionId).
7
+ //
8
+ // The backfill exists so the cutover in ADR-013 step 6 can drop the
9
+ // decisions table without losing schema fidelity. Idempotency is enforced
10
+ // by tagging each backfilled memory with structured_fields.sourceDecisionId
11
+ // and skipping any decision whose ID already appears in the memories table.
12
+ //
13
+ // Triggered opportunistically by buildBeforeAgentStartResult so the cost
14
+ // only ever fires once per project. Costs O(N) inserts on first run where
15
+ // N is the active-decisions count; subsequent runs are an O(N) lookup that
16
+ // finds existing markers and exits.
17
+
18
+ import { isDbAvailable, _getAdapter } from "./gsd-db.js";
19
+ import { createMemory } from "./memory-store.js";
20
+ import { logWarning } from "./workflow-logger.js";
21
+
22
+ interface DecisionRow {
23
+ id: string;
24
+ when_context: string;
25
+ scope: string;
26
+ decision: string;
27
+ choice: string;
28
+ rationale: string;
29
+ made_by: string;
30
+ revisable: string;
31
+ superseded_by: string | null;
32
+ }
33
+
34
+ /**
35
+ * Backfill active decisions rows into the memories table.
36
+ *
37
+ * - Idempotent (per-row): every row written carries
38
+ * `structured_fields.sourceDecisionId = "<decisionId>"`. Each candidate
39
+ * decision is checked individually; only decisions whose id is already
40
+ * present in the memory store are skipped. A user-authored memory with
41
+ * their own `sourceDecisionId` does NOT abort the backfill.
42
+ * - Best-effort: never throws. Logs and returns 0 on failure so a broken
43
+ * backfill cannot block agent startup.
44
+ * - Active-only: skips rows where `superseded_by IS NOT NULL`. Superseded
45
+ * decisions are historical record; the memory store is for active
46
+ * knowledge.
47
+ *
48
+ * Returns the number of memories written (0 when already backfilled or
49
+ * when the DB has no decisions). Callers can log the result or surface it
50
+ * to the user.
51
+ */
52
+ export function backfillDecisionsToMemories(): number {
53
+ if (!isDbAvailable()) return 0;
54
+ const adapter = _getAdapter();
55
+ if (!adapter) return 0;
56
+
57
+ try {
58
+ const decisions = adapter
59
+ .prepare("SELECT id, when_context, scope, decision, choice, rationale, made_by, revisable, superseded_by FROM decisions WHERE superseded_by IS NULL")
60
+ .all() as Array<Record<string, unknown>>;
61
+
62
+ if (decisions.length === 0) return 0;
63
+
64
+ // Per-row idempotency: each memory backfilled from a decision carries
65
+ // structured_fields.sourceDecisionId="<decisionId>". Skipping is decided
66
+ // per row by matching that exact id, NOT by a global sentinel — a global
67
+ // sentinel would silently abort the backfill if a user manually called
68
+ // capture_thought with their own structuredFields.sourceDecisionId.
69
+ const checkExisting = adapter.prepare(
70
+ "SELECT 1 FROM memories WHERE structured_fields LIKE :pattern LIMIT 1",
71
+ );
72
+
73
+ let written = 0;
74
+ for (const raw of decisions) {
75
+ const row: DecisionRow = {
76
+ id: String(raw["id"] ?? ""),
77
+ when_context: String(raw["when_context"] ?? ""),
78
+ scope: String(raw["scope"] ?? ""),
79
+ decision: String(raw["decision"] ?? ""),
80
+ choice: String(raw["choice"] ?? ""),
81
+ rationale: String(raw["rationale"] ?? ""),
82
+ made_by: String(raw["made_by"] ?? "agent"),
83
+ revisable: String(raw["revisable"] ?? ""),
84
+ superseded_by: raw["superseded_by"] == null ? null : String(raw["superseded_by"]),
85
+ };
86
+ if (!row.id) continue;
87
+
88
+ // Pattern is anchored to the JSON-stringified shape and the exact
89
+ // decision id to avoid prefix collisions (e.g. "D1" vs "D10").
90
+ if (checkExisting.get({ ":pattern": `%"sourceDecisionId":"${row.id}"%` })) continue;
91
+
92
+ const content = synthesizeContent(row);
93
+ const id = createMemory({
94
+ category: "architecture",
95
+ content,
96
+ scope: row.scope || "project",
97
+ confidence: 0.85,
98
+ structuredFields: {
99
+ sourceDecisionId: row.id,
100
+ when_context: row.when_context,
101
+ scope: row.scope,
102
+ decision: row.decision,
103
+ choice: row.choice,
104
+ rationale: row.rationale,
105
+ made_by: row.made_by,
106
+ revisable: row.revisable,
107
+ },
108
+ });
109
+ if (id) written += 1;
110
+ }
111
+
112
+ return written;
113
+ } catch (e) {
114
+ logWarning("memory-backfill", `decisions->memories backfill failed: ${(e as Error).message}`);
115
+ return 0;
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Combine the decision's structured fields into a 1-3 sentence content
121
+ * string suitable for keyword retrieval and human review.
122
+ *
123
+ * Format: "<decision> Chose: <choice>. Rationale: <rationale>."
124
+ * Truncates each field to keep the synthesized line under ~600 chars so
125
+ * memory_query rendering stays readable.
126
+ */
127
+ function synthesizeContent(row: DecisionRow): string {
128
+ const trim = (value: string, max: number): string => {
129
+ const cleaned = value.replace(/\s+/g, " ").trim();
130
+ return cleaned.length > max ? cleaned.slice(0, max - 1) + "\u2026" : cleaned;
131
+ };
132
+ const parts: string[] = [];
133
+ const decision = trim(row.decision, 240);
134
+ const choice = trim(row.choice, 200);
135
+ const rationale = trim(row.rationale, 200);
136
+ if (decision) parts.push(decision);
137
+ if (choice) parts.push(`Chose: ${choice}.`);
138
+ if (rationale) parts.push(`Rationale: ${rationale}.`);
139
+ return parts.join(" ");
140
+ }
@@ -36,6 +36,12 @@ export interface Memory {
36
36
  hit_count: number;
37
37
  scope: string;
38
38
  tags: string[];
39
+ /**
40
+ * ADR-013 Step 2: optional structured payload. NULL for memories captured
41
+ * via plain capture_thought. Populated on memories backfilled from the
42
+ * decisions table (Step 5) with the original scope/decision/choice/etc.
43
+ */
44
+ structured_fields: Record<string, unknown> | null;
39
45
  }
40
46
 
41
47
  export type MemoryActionCreate = {
@@ -45,6 +51,7 @@ export type MemoryActionCreate = {
45
51
  confidence?: number;
46
52
  scope?: string;
47
53
  tags?: string[];
54
+ structuredFields?: Record<string, unknown> | null;
48
55
  };
49
56
 
50
57
  export type MemoryActionUpdate = {
@@ -108,9 +115,22 @@ function rowToMemory(row: Record<string, unknown>): Memory {
108
115
  hit_count: row['hit_count'] as number,
109
116
  scope: (row['scope'] as string) ?? 'project',
110
117
  tags: parseTags(row['tags']),
118
+ structured_fields: parseStructuredFields(row['structured_fields']),
111
119
  };
112
120
  }
113
121
 
122
+ function parseStructuredFields(raw: unknown): Record<string, unknown> | null {
123
+ if (typeof raw !== 'string' || raw.length === 0) return null;
124
+ try {
125
+ const parsed = JSON.parse(raw);
126
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
127
+ ? (parsed as Record<string, unknown>)
128
+ : null;
129
+ } catch {
130
+ return null;
131
+ }
132
+ }
133
+
114
134
  function parseTags(raw: unknown): string[] {
115
135
  if (typeof raw !== 'string' || raw.length === 0) return [];
116
136
  try {
@@ -477,6 +497,7 @@ export function createMemory(fields: {
477
497
  source_unit_id?: string;
478
498
  scope?: string;
479
499
  tags?: string[];
500
+ structuredFields?: Record<string, unknown> | null;
480
501
  }): string | null {
481
502
  if (!isDbAvailable()) return null;
482
503
  const adapter = _getAdapter();
@@ -497,6 +518,7 @@ export function createMemory(fields: {
497
518
  updatedAt: now,
498
519
  scope: fields.scope ?? 'project',
499
520
  tags: fields.tags ?? [],
521
+ structuredFields: fields.structuredFields ?? null,
500
522
  });
501
523
  // Derive the real ID from the assigned seq (SELECT is still fine via adapter)
502
524
  const row = adapter.prepare('SELECT seq FROM memories WHERE id = :id').get({ ':id': placeholder });
@@ -684,6 +706,10 @@ export function applyMemoryActions(
684
706
  source_unit_id: unitId,
685
707
  scope: action.scope,
686
708
  tags: action.tags,
709
+ // ADR-013: forward structured payload through the action layer so
710
+ // bulk applyMemoryActions callers (extraction, ingestion) don't
711
+ // silently drop it.
712
+ structuredFields: action.structuredFields ?? null,
687
713
  });
688
714
  break;
689
715
  case 'UPDATE':
@@ -561,6 +561,23 @@ function bareModelId(modelId: string): string {
561
561
  return modelId.includes("/") ? modelId.split("/").pop()! : modelId;
562
562
  }
563
563
 
564
+ // ─── Provider-specific Tool Limits ─────────────────────────────────────────
565
+
566
+ /**
567
+ * Groq enforces a hard limit of 128 tools per request.
568
+ * Requests exceeding this limit receive a 400 error:
569
+ * "maximum number of items is 128"
570
+ * @see https://console.groq.com/docs/tool-use
571
+ */
572
+ export const GROQ_MAX_TOOLS = 128;
573
+
574
+ /**
575
+ * Provider IDs that map to the Groq API backend.
576
+ * Used to detect Groq at the GSD routing layer where only the provider string
577
+ * is available (the pi-ai openai-completions adapter is shared across providers).
578
+ */
579
+ const GROQ_PROVIDER_IDS = new Set(["groq"]);
580
+
564
581
  // ─── Tool Compatibility Filter (ADR-005 Phase 3) ───────────────────────────
565
582
 
566
583
  /**
@@ -588,10 +605,17 @@ export function isToolCompatibleWithProvider(
588
605
  /**
589
606
  * Filter a list of tool names to only those compatible with a provider.
590
607
  * Used by the routing pipeline to adjust tool sets when switching providers.
608
+ *
609
+ * @param toolNames - The full list of active tool names to filter.
610
+ * @param providerApi - The pi-ai API string (e.g. "openai-completions").
611
+ * @param provider - Optional provider ID (e.g. "groq"). Used to apply
612
+ * provider-specific limits that can't be expressed as API-level capabilities
613
+ * (e.g. Groq's 128-tool hard limit on the shared openai-completions adapter).
591
614
  */
592
615
  export function filterToolsForProvider(
593
616
  toolNames: string[],
594
617
  providerApi: string,
618
+ provider?: string,
595
619
  ): { compatible: string[]; filtered: string[] } {
596
620
  const providerCaps = getProviderCapabilities(providerApi);
597
621
 
@@ -611,6 +635,17 @@ export function filterToolsForProvider(
611
635
  }
612
636
  }
613
637
 
638
+ // Groq enforces a hard limit of 128 tools per request (#4376).
639
+ // Trim the compatible list to GROQ_MAX_TOOLS and move the excess to filtered.
640
+ if (provider && GROQ_PROVIDER_IDS.has(provider) && compatible.length > GROQ_MAX_TOOLS) {
641
+ const trimmed = compatible.splice(GROQ_MAX_TOOLS);
642
+ filtered.push(...trimmed);
643
+ console.warn(
644
+ `[gsd] Groq tool limit: ${compatible.length + trimmed.length} tools active but Groq allows at most ${GROQ_MAX_TOOLS}. ` +
645
+ `Trimming to the first ${GROQ_MAX_TOOLS} tools. Removed: ${trimmed.join(", ")}`,
646
+ );
647
+ }
648
+
614
649
  return { compatible, filtered };
615
650
  }
616
651
 
@@ -620,11 +655,17 @@ export function filterToolsForProvider(
620
655
  *
621
656
  * This is a hard filter only — it removes tools that would fail at the
622
657
  * provider level. It does NOT remove tools based on soft heuristics.
658
+ *
659
+ * @param activeToolNames - The full list of currently active tool names.
660
+ * @param selectedModelApi - The pi-ai API string for the selected model.
661
+ * @param provider - Optional provider ID (e.g. "groq") for provider-specific
662
+ * limits beyond what the API-level capability profile expresses.
623
663
  */
624
664
  export function adjustToolSet(
625
665
  activeToolNames: string[],
626
666
  selectedModelApi: string,
667
+ provider?: string,
627
668
  ): { toolNames: string[]; removedTools: string[] } {
628
- const { compatible, filtered } = filterToolsForProvider(activeToolNames, selectedModelApi);
669
+ const { compatible, filtered } = filterToolsForProvider(activeToolNames, selectedModelApi, provider);
629
670
  return { toolNames: compatible, removedTools: filtered };
630
671
  }
@@ -91,8 +91,13 @@ export function extractPackageReferences(description: string): string[] {
91
91
  }
92
92
  }
93
93
 
94
- // require('pkg') or import from 'pkg' in code blocks
95
- const importPattern = /(?:require\s*\(\s*['"]|from\s+['"])([a-zA-Z0-9@/_-]+)['"\)]/g;
94
+ // require('pkg') or `import ... from 'pkg'` in code blocks.
95
+ // The `from\s+['"]` branch MUST be preceded by an `import` keyword so that
96
+ // natural-language prose like `from "What's Next"` or `from 'master'` does
97
+ // not produce false package-existence failures. Requiring the leading import
98
+ // keyword anchors the match to JavaScript/TypeScript syntax.
99
+ // See: https://github.com/gsd-build/gsd-2/issues/4388
100
+ const importPattern = /(?:require\s*\(\s*['"]|import\b[\s\S]*?\bfrom\s+['"])([a-zA-Z0-9@/_-]+)['"\)]/g;
96
101
  let importMatch: RegExpExecArray | null;
97
102
  while ((importMatch = importPattern.exec(description)) !== null) {
98
103
  // Skip relative imports and node builtins
@@ -323,9 +328,24 @@ function extractPathFromAnnotation(raw: string): string {
323
328
  return backtickMatch[2].trim();
324
329
  }
325
330
 
331
+ // Strip leading/trailing double or single quotes wrapping the whole value.
332
+ // Plan documents sometimes emit `"src/foo.ts"` or `'src/bar.ts'` as input
333
+ // annotations. Stripping the wrapper allows the inner path to be checked
334
+ // correctly instead of producing a false-positive "file not found" error
335
+ // for a literal string with quote characters in it (#3747).
336
+ const quoteMatch = trimmed.match(/^(["'])([^"']+)\1$/);
337
+ if (quoteMatch) {
338
+ return quoteMatch[2].trim();
339
+ }
340
+
326
341
  const annotatedMatch = trimmed.match(/^(.+?)\s+[—–-]\s+.+$/);
327
342
  if (annotatedMatch) {
328
- return annotatedMatch[1].trim();
343
+ const prefix = annotatedMatch[1].trim();
344
+ const prefixBacktickMatch = prefix.match(/`([^`]+)`/);
345
+ if (prefixBacktickMatch && looksLikePathOrUrl(prefixBacktickMatch[1].trim())) {
346
+ return prefixBacktickMatch[1].trim();
347
+ }
348
+ return prefix.replace(/`/g, "").trim();
329
349
  }
330
350
 
331
351
  // Fallback: scan all backticked tokens and return the first one that looks
@@ -388,13 +408,19 @@ function containsGlobPattern(candidate: string): boolean {
388
408
 
389
409
  /**
390
410
  * Build a set of files that will be created by tasks up to (but not including) taskIndex.
411
+ * Also includes outputs of completed tasks at any position — a completed task has already
412
+ * run and its outputs are available regardless of sequence position or disk state (#4071).
391
413
  * All paths are normalized for consistent comparison.
392
414
  */
393
415
  function getExpectedOutputsUpTo(tasks: TaskRow[], taskIndex: number): Set<string> {
394
416
  const outputs = new Set<string>();
395
- for (let i = 0; i < taskIndex; i++) {
396
- for (const file of tasks[i].expected_output) {
397
- outputs.add(normalizeFilePath(file));
417
+ for (let i = 0; i < tasks.length; i++) {
418
+ const task = tasks[i];
419
+ // Include prior tasks (i < taskIndex) OR completed tasks at any position
420
+ if (i < taskIndex || task.status === "completed") {
421
+ for (const file of task.expected_output) {
422
+ outputs.add(normalizeFilePath(file));
423
+ }
398
424
  }
399
425
  }
400
426
  return outputs;
@@ -481,13 +507,19 @@ export function checkTaskOrdering(
481
507
  const results: PreExecutionCheckJSON[] = [];
482
508
 
483
509
  // Build map: normalized file → task index that creates it
484
- const fileCreators = new Map<string, { taskId: string; index: number; originalPath: string }>();
510
+ const fileCreators = new Map<string, { taskId: string; index: number; originalPath: string; completed: boolean }>();
485
511
  for (let i = 0; i < tasks.length; i++) {
486
512
  const task = tasks[i];
487
513
  for (const file of task.expected_output) {
488
514
  const normalizedFile = normalizeFilePath(file);
489
- if (!fileCreators.has(normalizedFile)) {
490
- fileCreators.set(normalizedFile, { taskId: task.id, index: i, originalPath: file });
515
+ const existing = fileCreators.get(normalizedFile);
516
+ if (!existing || (!existing.completed && task.status === "completed")) {
517
+ fileCreators.set(normalizedFile, {
518
+ taskId: task.id,
519
+ index: i,
520
+ originalPath: file,
521
+ completed: task.status === "completed",
522
+ });
491
523
  }
492
524
  }
493
525
  }
@@ -511,7 +543,11 @@ export function checkTaskOrdering(
511
543
  const creator = fileCreators.get(normalizedFile);
512
544
  const absolutePath = resolve(basePath, normalizedFile);
513
545
  const existsOnDisk = existsSync(absolutePath);
514
- if (creator && creator.index > i && !existsOnDisk) {
546
+ // Skip if the creating task has already completed its output is available
547
+ // regardless of disk state (e.g. file was a temp artifact cleaned up after
548
+ // the task ran, or a replan introduced a new earlier-sequence task that
549
+ // reads this pre-execution output). (#4071)
550
+ if (creator && creator.index > i && !existsOnDisk && !creator.completed) {
515
551
  // Task reads file that is created later — impossible ordering
516
552
  results.push({
517
553
  category: "file",