gsd-pi 2.57.0-dev.f22a903 → 2.58.0-dev.778d6ac

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 (643) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +49 -35
  3. package/dist/headless-ui.d.ts +17 -0
  4. package/dist/headless-ui.js +97 -3
  5. package/dist/headless.js +67 -6
  6. package/dist/help-text.js +1 -0
  7. package/dist/onboarding.js +44 -0
  8. package/dist/resource-loader.js +16 -1
  9. package/dist/resources/agents/researcher.md +1 -1
  10. package/dist/resources/extensions/ask-user-questions.js +16 -3
  11. package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
  12. package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
  13. package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
  14. package/dist/resources/extensions/claude-code-cli/partial-builder.js +14 -6
  15. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
  16. package/dist/resources/extensions/context7/extension-manifest.json +1 -1
  17. package/dist/resources/extensions/get-secrets-from-user.js +8 -5
  18. package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
  19. package/dist/resources/extensions/google-search/index.js +2 -1
  20. package/dist/resources/extensions/gsd/auto/phases.js +25 -21
  21. package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
  22. package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
  23. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -2
  24. package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
  25. package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
  26. package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
  27. package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
  28. package/dist/resources/extensions/gsd/auto-start.js +35 -22
  29. package/dist/resources/extensions/gsd/auto-worktree.js +196 -12
  30. package/dist/resources/extensions/gsd/auto.js +4 -0
  31. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
  32. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -8
  33. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
  35. package/dist/resources/extensions/gsd/bootstrap/system-context.js +44 -11
  36. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
  37. package/dist/resources/extensions/gsd/captures.js +56 -4
  38. package/dist/resources/extensions/gsd/db-writer.js +116 -8
  39. package/dist/resources/extensions/gsd/doctor-git-checks.js +28 -0
  40. package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
  41. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
  42. package/dist/resources/extensions/gsd/doctor.js +3 -1
  43. package/dist/resources/extensions/gsd/error-classifier.js +13 -10
  44. package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
  45. package/dist/resources/extensions/gsd/forensics.js +123 -20
  46. package/dist/resources/extensions/gsd/git-service.js +23 -1
  47. package/dist/resources/extensions/gsd/gitignore.js +33 -0
  48. package/dist/resources/extensions/gsd/gsd-db.js +36 -9
  49. package/dist/resources/extensions/gsd/guided-flow.js +106 -44
  50. package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
  51. package/dist/resources/extensions/gsd/health-widget.js +17 -0
  52. package/dist/resources/extensions/gsd/index.js +1 -1
  53. package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
  54. package/dist/resources/extensions/gsd/migrate-external.js +8 -1
  55. package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
  56. package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
  57. package/dist/resources/extensions/gsd/model-router.js +35 -1
  58. package/dist/resources/extensions/gsd/native-git-bridge.js +17 -0
  59. package/dist/resources/extensions/gsd/notifications.js +16 -1
  60. package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
  61. package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
  62. package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
  63. package/dist/resources/extensions/gsd/paths.js +43 -0
  64. package/dist/resources/extensions/gsd/preferences-models.js +14 -1
  65. package/dist/resources/extensions/gsd/preferences-types.js +2 -1
  66. package/dist/resources/extensions/gsd/preferences.js +13 -16
  67. package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
  68. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  70. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  72. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
  73. package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
  74. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  75. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  77. package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  79. package/dist/resources/extensions/gsd/repo-identity.js +205 -11
  80. package/dist/resources/extensions/gsd/rethink.js +5 -0
  81. package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
  82. package/dist/resources/extensions/gsd/state.js +85 -27
  83. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  84. package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
  85. package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
  86. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
  87. package/dist/resources/extensions/gsd/tools/validate-milestone.js +14 -3
  88. package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
  89. package/dist/resources/extensions/gsd/undo.js +2 -2
  90. package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
  91. package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
  92. package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
  93. package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
  94. package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
  95. package/dist/resources/extensions/gsd/workspace-index.js +24 -0
  96. package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
  97. package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
  98. package/dist/resources/extensions/mcp-client/index.js +11 -7
  99. package/dist/resources/extensions/ollama/index.js +112 -0
  100. package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
  101. package/dist/resources/extensions/ollama/ollama-client.js +168 -0
  102. package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
  103. package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
  104. package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
  105. package/dist/resources/extensions/ollama/types.js +2 -0
  106. package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
  107. package/dist/resources/extensions/shared/interview-ui.js +11 -1
  108. package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
  109. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  110. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  111. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  112. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  113. package/dist/startup-model-validation.d.ts +39 -0
  114. package/dist/startup-model-validation.js +50 -0
  115. package/dist/web/standalone/.next/BUILD_ID +1 -1
  116. package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
  117. package/dist/web/standalone/.next/build-manifest.json +3 -3
  118. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  119. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  122. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  138. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.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_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/index.html +1 -1
  193. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  194. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  195. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  196. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  197. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  198. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  199. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
  201. package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
  202. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  205. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  206. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  207. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
  208. package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
  209. package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
  210. package/dist/web-mode.js +2 -1
  211. package/package.json +2 -2
  212. package/packages/daemon/src/cli.ts +49 -0
  213. package/packages/daemon/src/daemon.test.ts +104 -1
  214. package/packages/daemon/src/daemon.ts +24 -1
  215. package/packages/daemon/src/discord-bot.ts +73 -3
  216. package/packages/daemon/src/event-bridge.ts +15 -9
  217. package/packages/daemon/src/event-formatter.ts +30 -2
  218. package/packages/daemon/src/index.ts +9 -0
  219. package/packages/daemon/src/launchd.test.ts +356 -0
  220. package/packages/daemon/src/launchd.ts +242 -0
  221. package/packages/daemon/src/message-batcher.test.ts +2 -2
  222. package/packages/daemon/src/message-batcher.ts +9 -3
  223. package/packages/daemon/src/orchestrator.test.ts +1 -0
  224. package/packages/daemon/src/orchestrator.ts +106 -2
  225. package/packages/native/dist/ast/index.js +9 -5
  226. package/packages/native/dist/ast/types.js +2 -1
  227. package/packages/native/dist/clipboard/index.js +12 -7
  228. package/packages/native/dist/clipboard/types.js +2 -1
  229. package/packages/native/dist/diff/index.js +12 -7
  230. package/packages/native/dist/diff/types.js +2 -1
  231. package/packages/native/dist/fd/index.js +6 -3
  232. package/packages/native/dist/fd/types.js +2 -1
  233. package/packages/native/dist/glob/index.js +9 -5
  234. package/packages/native/dist/glob/types.js +2 -1
  235. package/packages/native/dist/grep/index.js +9 -5
  236. package/packages/native/dist/grep/types.js +2 -1
  237. package/packages/native/dist/gsd-parser/index.js +18 -11
  238. package/packages/native/dist/gsd-parser/types.js +2 -1
  239. package/packages/native/dist/highlight/index.js +12 -7
  240. package/packages/native/dist/highlight/types.js +2 -1
  241. package/packages/native/dist/html/index.js +6 -3
  242. package/packages/native/dist/html/types.js +2 -1
  243. package/packages/native/dist/image/index.js +10 -5
  244. package/packages/native/dist/image/types.js +7 -4
  245. package/packages/native/dist/index.js +70 -17
  246. package/packages/native/dist/json-parse/index.js +13 -8
  247. package/packages/native/dist/native.js +47 -10
  248. package/packages/native/dist/ps/index.js +15 -9
  249. package/packages/native/dist/ps/types.js +2 -1
  250. package/packages/native/dist/stream-process/index.js +12 -7
  251. package/packages/native/dist/text/index.js +24 -14
  252. package/packages/native/dist/text/types.js +5 -2
  253. package/packages/native/dist/truncate/index.js +12 -7
  254. package/packages/native/dist/ttsr/index.js +12 -7
  255. package/packages/native/dist/ttsr/types.js +2 -1
  256. package/packages/native/dist/xxhash/index.js +9 -5
  257. package/packages/native/package.json +19 -19
  258. package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
  259. package/packages/native/src/native.ts +9 -8
  260. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  261. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  262. package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
  263. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  264. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  265. package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
  266. package/packages/pi-agent-core/src/agent-loop.ts +3 -2
  267. package/packages/pi-agent-core/src/proxy.ts +1 -1
  268. package/packages/pi-ai/dist/env-api-keys.js +1 -0
  269. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  270. package/packages/pi-ai/dist/index.d.ts +1 -0
  271. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  272. package/packages/pi-ai/dist/index.js +1 -0
  273. package/packages/pi-ai/dist/index.js.map +1 -1
  274. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  275. package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -2
  276. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  277. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
  278. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
  279. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
  280. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
  281. package/packages/pi-ai/dist/types.d.ts +3 -3
  282. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  283. package/packages/pi-ai/dist/types.js.map +1 -1
  284. package/packages/pi-ai/dist/utils/json-parse.d.ts +3 -0
  285. package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
  286. package/packages/pi-ai/dist/utils/json-parse.js +24 -1
  287. package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
  288. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
  289. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
  290. package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
  291. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
  292. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
  293. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
  294. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
  295. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
  296. package/packages/pi-ai/src/env-api-keys.ts +1 -0
  297. package/packages/pi-ai/src/index.ts +1 -0
  298. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
  299. package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
  300. package/packages/pi-ai/src/types.ts +3 -2
  301. package/packages/pi-ai/src/utils/json-parse.ts +28 -1
  302. package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
  303. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
  304. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
  305. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
  307. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
  309. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
  311. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
  313. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
  314. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
  315. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
  316. package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/exec.js +3 -1
  318. package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
  320. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
  321. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
  322. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
  323. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
  324. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
  325. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
  326. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
  327. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
  328. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
  329. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
  330. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
  331. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
  332. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
  333. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
  334. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
  335. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
  336. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  337. package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
  338. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  339. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  340. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  341. package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
  342. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
  344. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
  345. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
  346. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
  347. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
  348. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
  349. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
  350. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
  351. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
  352. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/index.js +1 -1
  354. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  356. package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
  357. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  358. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  359. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
  360. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  361. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/core/messages.js +31 -2
  363. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
  365. package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
  366. package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
  367. package/packages/pi-coding-agent/dist/core/messages.test.js.map +1 -0
  368. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  370. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
  372. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  373. package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -1
  374. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  375. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +6 -0
  376. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  377. package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
  378. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  379. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
  380. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
  381. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
  382. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
  383. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
  385. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  387. package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
  388. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  389. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
  390. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
  391. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
  392. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
  393. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  394. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  395. package/packages/pi-coding-agent/dist/index.js +1 -1
  396. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  397. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  398. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +4 -0
  399. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  400. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
  401. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
  402. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
  403. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
  404. package/packages/pi-coding-agent/package.json +1 -1
  405. package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
  406. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
  407. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
  408. package/packages/pi-coding-agent/src/core/exec.ts +3 -1
  409. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
  410. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
  411. package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
  412. package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
  413. package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
  414. package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
  415. package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
  416. package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
  417. package/packages/pi-coding-agent/src/core/index.ts +6 -0
  418. package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
  419. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
  420. package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
  421. package/packages/pi-coding-agent/src/core/messages.ts +29 -2
  422. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  423. package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
  424. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
  425. package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
  426. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
  427. package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
  428. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
  429. package/packages/pi-coding-agent/src/index.ts +6 -0
  430. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -0
  431. package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
  432. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  433. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  434. package/packages/pi-tui/dist/terminal.js +9 -0
  435. package/packages/pi-tui/dist/terminal.js.map +1 -1
  436. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  437. package/packages/pi-tui/dist/tui.js +9 -0
  438. package/packages/pi-tui/dist/tui.js.map +1 -1
  439. package/packages/pi-tui/src/terminal.ts +14 -0
  440. package/packages/pi-tui/src/tui.ts +8 -0
  441. package/pkg/package.json +1 -1
  442. package/scripts/ensure-workspace-builds.cjs +45 -14
  443. package/src/resources/agents/researcher.md +1 -1
  444. package/src/resources/extensions/ask-user-questions.ts +21 -3
  445. package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
  446. package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
  447. package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
  448. package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
  449. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
  450. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
  451. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
  452. package/src/resources/extensions/context7/extension-manifest.json +1 -1
  453. package/src/resources/extensions/get-secrets-from-user.ts +8 -5
  454. package/src/resources/extensions/google-search/extension-manifest.json +1 -1
  455. package/src/resources/extensions/google-search/index.ts +2 -1
  456. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  457. package/src/resources/extensions/gsd/auto/phases.ts +43 -34
  458. package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
  459. package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
  460. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
  461. package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
  462. package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
  463. package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
  464. package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
  465. package/src/resources/extensions/gsd/auto-start.ts +35 -26
  466. package/src/resources/extensions/gsd/auto-worktree.ts +190 -9
  467. package/src/resources/extensions/gsd/auto.ts +5 -0
  468. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
  469. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +85 -8
  470. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
  471. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -19
  472. package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -11
  473. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
  474. package/src/resources/extensions/gsd/captures.ts +63 -3
  475. package/src/resources/extensions/gsd/db-writer.ts +140 -7
  476. package/src/resources/extensions/gsd/doctor-git-checks.ts +26 -0
  477. package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
  478. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
  479. package/src/resources/extensions/gsd/doctor.ts +3 -1
  480. package/src/resources/extensions/gsd/error-classifier.ts +14 -11
  481. package/src/resources/extensions/gsd/extension-manifest.json +16 -1
  482. package/src/resources/extensions/gsd/forensics.ts +144 -20
  483. package/src/resources/extensions/gsd/git-service.ts +26 -3
  484. package/src/resources/extensions/gsd/gitignore.ts +33 -0
  485. package/src/resources/extensions/gsd/gsd-db.ts +43 -7
  486. package/src/resources/extensions/gsd/guided-flow.ts +114 -45
  487. package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
  488. package/src/resources/extensions/gsd/health-widget.ts +17 -0
  489. package/src/resources/extensions/gsd/index.ts +1 -0
  490. package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
  491. package/src/resources/extensions/gsd/migrate-external.ts +9 -1
  492. package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
  493. package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
  494. package/src/resources/extensions/gsd/model-router.ts +35 -1
  495. package/src/resources/extensions/gsd/native-git-bridge.ts +17 -0
  496. package/src/resources/extensions/gsd/notifications.ts +16 -0
  497. package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
  498. package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
  499. package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
  500. package/src/resources/extensions/gsd/paths.ts +42 -0
  501. package/src/resources/extensions/gsd/preferences-models.ts +14 -1
  502. package/src/resources/extensions/gsd/preferences-types.ts +2 -1
  503. package/src/resources/extensions/gsd/preferences.ts +13 -15
  504. package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
  505. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  506. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  507. package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  508. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  509. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
  510. package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
  511. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  512. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  513. package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  514. package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
  515. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  516. package/src/resources/extensions/gsd/repo-identity.ts +186 -11
  517. package/src/resources/extensions/gsd/rethink.ts +6 -0
  518. package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
  519. package/src/resources/extensions/gsd/state.ts +84 -32
  520. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +47 -0
  521. package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
  522. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
  523. package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
  524. package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
  525. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
  526. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
  527. package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
  528. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
  529. package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
  530. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
  531. package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
  532. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
  533. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
  534. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
  535. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  536. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
  537. package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
  538. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
  539. package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
  540. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
  541. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
  542. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
  543. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
  544. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
  545. package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
  546. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
  547. package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
  548. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
  549. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
  550. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +101 -0
  551. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
  552. package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
  553. package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
  554. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
  555. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
  556. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
  557. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
  558. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
  559. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
  560. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
  561. package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
  562. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
  563. package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
  564. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
  565. package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
  566. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
  567. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
  568. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
  569. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -0
  570. package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
  571. package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
  572. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
  573. package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
  574. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
  575. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
  576. package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
  577. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
  578. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
  579. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
  580. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
  581. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
  582. package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
  583. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
  584. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
  585. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
  586. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
  587. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
  588. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
  589. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
  590. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
  591. package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
  592. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +4 -1
  593. package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
  594. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
  595. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
  596. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
  597. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
  598. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
  599. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
  600. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
  601. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
  602. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
  603. package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
  604. package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
  605. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
  606. package/src/resources/extensions/gsd/tools/validate-milestone.ts +20 -2
  607. package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
  608. package/src/resources/extensions/gsd/types.ts +4 -2
  609. package/src/resources/extensions/gsd/undo.ts +2 -2
  610. package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
  611. package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
  612. package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
  613. package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
  614. package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
  615. package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
  616. package/src/resources/extensions/gsd/workspace-index.ts +30 -0
  617. package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
  618. package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
  619. package/src/resources/extensions/mcp-client/index.ts +13 -7
  620. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
  621. package/src/resources/extensions/ollama/index.ts +130 -0
  622. package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
  623. package/src/resources/extensions/ollama/ollama-client.ts +196 -0
  624. package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
  625. package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
  626. package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
  627. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
  628. package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
  629. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
  630. package/src/resources/extensions/ollama/types.ts +130 -0
  631. package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
  632. package/src/resources/extensions/shared/interview-ui.ts +12 -1
  633. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
  634. package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
  635. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  636. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  637. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  638. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  639. package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +0 -9
  640. package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +0 -1
  641. package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
  642. /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
  643. /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Test: auto-mode prompts must prohibit ask_user_questions / secure_env_collect
3
+ *
4
+ * Bug #2936: When the LLM calls ask_user_questions during auto-mode units
5
+ * (plan-slice, execute-task, complete-slice), the interactive tool queues a
6
+ * user response which causes the subsequent gsd_plan_slice / gsd_complete_task
7
+ * call to fail with "Skipped due to queued user message." The canonical GSD
8
+ * tool call is never recorded, verifyExpectedArtifact finds no artifact, and
9
+ * the dispatch loop re-dispatches the same unit 2-4x.
10
+ *
11
+ * Fix: Each auto-mode prompt must contain an "Autonomous execution" guard
12
+ * that explicitly prohibits ask_user_questions and secure_env_collect.
13
+ */
14
+
15
+ import test from "node:test";
16
+ import assert from "node:assert/strict";
17
+ import { readFileSync } from "node:fs";
18
+ import { join, dirname } from "node:path";
19
+ import { fileURLToPath } from "node:url";
20
+
21
+ const __dirname = dirname(fileURLToPath(import.meta.url));
22
+ const promptsDir = join(__dirname, "..", "prompts");
23
+
24
+ function loadPromptRaw(name: string): string {
25
+ return readFileSync(join(promptsDir, `${name}.md`), "utf-8");
26
+ }
27
+
28
+ const AUTO_MODE_PROMPTS = ["plan-slice", "execute-task", "complete-slice"];
29
+
30
+ for (const promptName of AUTO_MODE_PROMPTS) {
31
+ test(`${promptName} prompt prohibits ask_user_questions in auto-mode`, () => {
32
+ const content = loadPromptRaw(promptName);
33
+
34
+ assert.ok(
35
+ content.includes("ask_user_questions"),
36
+ `${promptName}.md must mention ask_user_questions (to prohibit it)`,
37
+ );
38
+
39
+ assert.ok(
40
+ content.includes("secure_env_collect"),
41
+ `${promptName}.md must mention secure_env_collect (to prohibit it)`,
42
+ );
43
+
44
+ // The guard must clearly state this is autonomous / auto-mode
45
+ assert.ok(
46
+ content.toLowerCase().includes("auto-mode") || content.toLowerCase().includes("autonomous"),
47
+ `${promptName}.md must reference auto-mode or autonomous execution`,
48
+ );
49
+
50
+ // The guard must indicate no human is available
51
+ assert.ok(
52
+ content.includes("no human") || content.includes("no user"),
53
+ `${promptName}.md must state that no human/user is available to answer`,
54
+ );
55
+ });
56
+ }
57
+
58
+ test("auto-mode prompts contain autonomous guard before final tool call reminder", () => {
59
+ for (const promptName of AUTO_MODE_PROMPTS) {
60
+ const content = loadPromptRaw(promptName);
61
+
62
+ // The guard should appear before the final "MUST call" line
63
+ const guardIndex = content.indexOf("ask_user_questions");
64
+ const mustCallIndex = content.lastIndexOf("MUST call");
65
+
66
+ assert.ok(
67
+ guardIndex !== -1 && mustCallIndex !== -1 && guardIndex < mustCallIndex,
68
+ `${promptName}.md: autonomous guard (ask_user_questions prohibition) must appear before the final MUST call reminder`,
69
+ );
70
+ }
71
+ });
@@ -4,7 +4,7 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
 
7
- import { resolvePreferredModelConfig } from "../auto-model-selection.js";
7
+ import { resolvePreferredModelConfig, resolveModelId } from "../auto-model-selection.js";
8
8
 
9
9
  function makeTempDir(prefix: string): string {
10
10
  return mkdtempSync(join(tmpdir(), prefix));
@@ -137,3 +137,73 @@ test("resolvePreferredModelConfig keeps explicit phase models as the ceiling", (
137
137
  rmSync(tempGsdHome, { recursive: true, force: true });
138
138
  }
139
139
  });
140
+
141
+ // ─── resolveModelId tests ─────────────────────────────────────────────────
142
+
143
+ test("resolveModelId: bare ID resolves to anthropic over claude-code when session is claude-code (#2905)", () => {
144
+ const availableModels = [
145
+ { id: "claude-sonnet-4-6", provider: "anthropic" },
146
+ { id: "claude-sonnet-4-6", provider: "claude-code" },
147
+ ];
148
+
149
+ // Bug: when currentProvider is "claude-code", bare ID "claude-sonnet-4-6"
150
+ // resolves to claude-code/claude-sonnet-4-6 instead of anthropic/claude-sonnet-4-6
151
+ const result = resolveModelId("claude-sonnet-4-6", availableModels, "claude-code");
152
+ assert.ok(result, "should resolve a model");
153
+ assert.equal(result.provider, "anthropic", "bare ID must resolve to anthropic, not claude-code");
154
+ });
155
+
156
+ test("resolveModelId: bare ID still prefers current provider when it is a first-class API provider", () => {
157
+ const availableModels = [
158
+ { id: "claude-sonnet-4-6", provider: "anthropic" },
159
+ { id: "claude-sonnet-4-6", provider: "bedrock" },
160
+ ];
161
+
162
+ const result = resolveModelId("claude-sonnet-4-6", availableModels, "bedrock");
163
+ assert.ok(result, "should resolve a model");
164
+ assert.equal(result.provider, "bedrock", "bare ID should prefer current provider when it is a real API provider");
165
+ });
166
+
167
+ test("resolveModelId: explicit provider/model format still resolves to claude-code when specified", () => {
168
+ const availableModels = [
169
+ { id: "claude-sonnet-4-6", provider: "anthropic" },
170
+ { id: "claude-sonnet-4-6", provider: "claude-code" },
171
+ ];
172
+
173
+ const result = resolveModelId("claude-code/claude-sonnet-4-6", availableModels, "anthropic");
174
+ assert.ok(result, "should resolve a model");
175
+ assert.equal(result.provider, "claude-code", "explicit provider prefix must be respected");
176
+ });
177
+
178
+ test("resolveModelId: bare ID with only one provider works normally", () => {
179
+ const availableModels = [
180
+ { id: "claude-sonnet-4-6", provider: "anthropic" },
181
+ ];
182
+
183
+ const result = resolveModelId("claude-sonnet-4-6", availableModels, "anthropic");
184
+ assert.ok(result, "should resolve a model");
185
+ assert.equal(result.provider, "anthropic");
186
+ });
187
+
188
+ test("resolveModelId: bare ID with claude-code as only provider still resolves", () => {
189
+ const availableModels = [
190
+ { id: "claude-sonnet-4-6", provider: "claude-code" },
191
+ ];
192
+
193
+ // If claude-code is the ONLY provider for this model, it should still resolve
194
+ const result = resolveModelId("claude-sonnet-4-6", availableModels, "claude-code");
195
+ assert.ok(result, "should resolve even when only available via claude-code");
196
+ assert.equal(result.provider, "claude-code");
197
+ });
198
+
199
+ test("resolveModelId: anthropic wins over claude-code regardless of list order", () => {
200
+ const availableModels = [
201
+ { id: "claude-sonnet-4-6", provider: "claude-code" },
202
+ { id: "claude-sonnet-4-6", provider: "anthropic" },
203
+ ];
204
+
205
+ // Even when claude-code appears first in the list, anthropic should win
206
+ const result = resolveModelId("claude-sonnet-4-6", availableModels, "claude-code");
207
+ assert.ok(result, "should resolve a model");
208
+ assert.equal(result.provider, "anthropic", "anthropic must win over claude-code regardless of list order");
209
+ });
@@ -19,8 +19,11 @@ import {
19
19
  appendCapture,
20
20
  loadAllCaptures,
21
21
  loadPendingCaptures,
22
+ loadActionableCaptures,
22
23
  hasPendingCaptures,
23
24
  markCaptureResolved,
25
+ markCaptureExecuted,
26
+ stampCaptureMilestone,
24
27
  resolveCapturesPath,
25
28
  parseTriageOutput,
26
29
  } from "../captures.ts";
@@ -419,3 +422,103 @@ test("triage: parseTriageOutput preserves affectedFiles and targetSlice", () =>
419
422
  assert.strictEqual(results[1].targetSlice, "S04");
420
423
  assert.strictEqual(results[1].affectedFiles, undefined);
421
424
  });
425
+
426
+ // ─── Stale Quick-Task Captures (#2872) ────────────────────────────────────────
427
+
428
+ test("captures: markCaptureResolved stores milestone ID when provided", (t) => {
429
+ const tmp = makeTempDir("cap-milestone");
430
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
431
+
432
+ const id = appendCapture(tmp, "fix dialog width");
433
+ markCaptureResolved(tmp, id, "quick-task", "widen the dialog", "small fix", "M003");
434
+
435
+ const all = loadAllCaptures(tmp);
436
+ assert.strictEqual(all.length, 1);
437
+ assert.strictEqual(all[0].resolvedInMilestone, "M003", "should store milestone ID");
438
+ });
439
+
440
+ test("captures: loadActionableCaptures excludes captures resolved in prior milestones", (t) => {
441
+ const tmp = makeTempDir("cap-stale-filter");
442
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
443
+
444
+ // Capture resolved in M003 (prior milestone)
445
+ const id1 = appendCapture(tmp, "dialog too narrow");
446
+ markCaptureResolved(tmp, id1, "quick-task", "widen it", "small fix", "M003");
447
+
448
+ // Capture resolved in M004 (current milestone)
449
+ const id2 = appendCapture(tmp, "button misaligned");
450
+ markCaptureResolved(tmp, id2, "quick-task", "fix alignment", "css fix", "M004");
451
+
452
+ // Capture resolved without milestone context (legacy)
453
+ const id3 = appendCapture(tmp, "typo in label");
454
+ markCaptureResolved(tmp, id3, "quick-task", "fix typo", "trivial");
455
+
456
+ // When loading for M004, only M004 and no-milestone captures should be returned
457
+ const actionable = loadActionableCaptures(tmp, "M004");
458
+ const ids = actionable.map(c => c.id);
459
+
460
+ assert.ok(!ids.includes(id1), "should exclude capture resolved in M003");
461
+ assert.ok(ids.includes(id2), "should include capture resolved in M004");
462
+ assert.ok(ids.includes(id3), "should include capture with no milestone (legacy)");
463
+ });
464
+
465
+ test("captures: loadActionableCaptures without milestone returns all actionable", (t) => {
466
+ const tmp = makeTempDir("cap-no-milestone-filter");
467
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
468
+
469
+ const id1 = appendCapture(tmp, "issue one");
470
+ markCaptureResolved(tmp, id1, "quick-task", "fix it", "small", "M003");
471
+
472
+ const id2 = appendCapture(tmp, "issue two");
473
+ markCaptureResolved(tmp, id2, "inject", "inject it", "needed", "M004");
474
+
475
+ // Without milestone filter, all actionable captures are returned (backward compat)
476
+ const actionable = loadActionableCaptures(tmp);
477
+ assert.strictEqual(actionable.length, 2, "should return all actionable without filter");
478
+ });
479
+
480
+ test("captures: loadActionableCaptures excludes already-executed captures", (t) => {
481
+ const tmp = makeTempDir("cap-executed-filter");
482
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
483
+
484
+ const id1 = appendCapture(tmp, "already done");
485
+ markCaptureResolved(tmp, id1, "quick-task", "fix it", "small", "M004");
486
+ markCaptureExecuted(tmp, id1);
487
+
488
+ const id2 = appendCapture(tmp, "still pending");
489
+ markCaptureResolved(tmp, id2, "quick-task", "fix it too", "small", "M004");
490
+
491
+ const actionable = loadActionableCaptures(tmp, "M004");
492
+ assert.strictEqual(actionable.length, 1, "should exclude executed capture");
493
+ assert.strictEqual(actionable[0].id, id2);
494
+ });
495
+
496
+ test("captures: stampCaptureMilestone adds milestone to capture missing it", (t) => {
497
+ const tmp = makeTempDir("cap-stamp-milestone");
498
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
499
+
500
+ const id = appendCapture(tmp, "fix alignment");
501
+ markCaptureResolved(tmp, id, "quick-task", "fix it", "small");
502
+
503
+ // Before stamping, no milestone
504
+ let all = loadAllCaptures(tmp);
505
+ assert.strictEqual(all[0].resolvedInMilestone, undefined, "should have no milestone initially");
506
+
507
+ stampCaptureMilestone(tmp, id, "M004");
508
+
509
+ all = loadAllCaptures(tmp);
510
+ assert.strictEqual(all[0].resolvedInMilestone, "M004", "should have milestone after stamping");
511
+ });
512
+
513
+ test("captures: stampCaptureMilestone is no-op if milestone already present", (t) => {
514
+ const tmp = makeTempDir("cap-stamp-noop");
515
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
516
+
517
+ const id = appendCapture(tmp, "fix alignment");
518
+ markCaptureResolved(tmp, id, "quick-task", "fix it", "small", "M003");
519
+
520
+ stampCaptureMilestone(tmp, id, "M004");
521
+
522
+ const all = loadAllCaptures(tmp);
523
+ assert.strictEqual(all[0].resolvedInMilestone, "M003", "should keep original milestone");
524
+ });
@@ -0,0 +1,47 @@
1
+ /**
2
+ * cli-provider-rate-limit.test.ts — Verify rate-limit backoff capping
3
+ * for CLI-style providers (openai-codex, google-gemini-cli). (#2922)
4
+ *
5
+ * These providers use per-user quotas with shorter windows, so the
6
+ * default 60s backoff should be capped at 30s to avoid leaving users
7
+ * stuck in an apparent permanent "rate limit" state.
8
+ */
9
+
10
+ import test from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { readFileSync } from "node:fs";
13
+ import { join, dirname } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+ const RECOVERY_PATH = join(__dirname, "..", "bootstrap", "agent-end-recovery.ts");
18
+
19
+ function getRecoverySource(): string {
20
+ return readFileSync(RECOVERY_PATH, "utf-8");
21
+ }
22
+
23
+ test("agent-end-recovery references openai-codex for rate-limit handling (#2922)", () => {
24
+ const src = getRecoverySource();
25
+ assert.ok(
26
+ src.includes("openai-codex"),
27
+ 'agent-end-recovery.ts must reference "openai-codex" for CLI provider rate-limit handling (#2922)',
28
+ );
29
+ });
30
+
31
+ test("agent-end-recovery references google-gemini-cli for rate-limit handling (#2922)", () => {
32
+ const src = getRecoverySource();
33
+ assert.ok(
34
+ src.includes("google-gemini-cli"),
35
+ 'agent-end-recovery.ts must reference "google-gemini-cli" for CLI provider rate-limit handling (#2922)',
36
+ );
37
+ });
38
+
39
+ test("agent-end-recovery caps rate-limit backoff for CLI providers (#2922)", () => {
40
+ const src = getRecoverySource();
41
+ // Must have a Math.min capping pattern for CLI provider rate-limit backoff
42
+ const cappingRe = /Math\.min\s*\(/;
43
+ assert.ok(
44
+ cappingRe.test(src),
45
+ 'agent-end-recovery.ts must cap rate-limit backoff with Math.min for CLI providers (#2922)',
46
+ );
47
+ });
@@ -237,6 +237,33 @@ describe("complete-milestone", () => {
237
237
  }
238
238
  });
239
239
 
240
+ test("step 11 specifies write tool for PROJECT.md update (#2946)", () => {
241
+ const prompt = loadPromptFromWorktree("complete-milestone", {
242
+ workingDirectory: "/tmp/test-project",
243
+ milestoneId: "M001",
244
+ milestoneTitle: "Tool Guidance Test",
245
+ roadmapPath: ".gsd/milestones/M001/M001-ROADMAP.md",
246
+ inlinedContext: "context",
247
+ milestoneSummaryPath: ".gsd/milestones/M001/M001-SUMMARY.md",
248
+ skillActivation: "",
249
+ });
250
+
251
+ // Step 11 must explicitly name the `write` tool so the LLM doesn't
252
+ // confuse it with `edit` (which requires path + oldText + newText).
253
+ // See: https://github.com/gsd-build/gsd-2/issues/2946
254
+ assert.ok(
255
+ /PROJECT\.md.*\bwrite\b/i.test(prompt) || /\bwrite\b.*PROJECT\.md/i.test(prompt),
256
+ "step 11 must name the `write` tool when updating PROJECT.md",
257
+ );
258
+
259
+ // The prompt must NOT leave tool choice ambiguous for PROJECT.md
260
+ // Verify it mentions the required parameter (`content` or `path`)
261
+ assert.ok(
262
+ prompt.includes("`.gsd/PROJECT.md`") || prompt.includes('".gsd/PROJECT.md"'),
263
+ "step 11 must reference the PROJECT.md path explicitly",
264
+ );
265
+ });
266
+
240
267
  test("deriveState completing-milestone integration", async () => {
241
268
  const { deriveState, isMilestoneComplete } = await import("../state.ts");
242
269
  const { invalidateAllCaches: invalidateAllCachesDynamic } = await import("../cache.ts");
@@ -406,6 +406,27 @@ console.log('\n=== complete-slice: handler with missing roadmap ===');
406
406
  cleanup(dbPath);
407
407
  }
408
408
 
409
+ // ═══════════════════════════════════════════════════════════════════════════
410
+ // complete-slice: step 13 specifies write tool for PROJECT.md (#2946)
411
+ // ═══════════════════════════════════════════════════════════════════════════
412
+
413
+ console.log('\n=== complete-slice: step 13 specifies write tool for PROJECT.md (#2946) ===');
414
+ {
415
+ const promptPath = path.join(
416
+ path.dirname(new URL(import.meta.url).pathname),
417
+ '..', 'prompts', 'complete-slice.md',
418
+ );
419
+ const prompt = fs.readFileSync(promptPath, 'utf-8');
420
+
421
+ // Step 13 must explicitly name the `write` tool so the LLM doesn't
422
+ // confuse it with `edit` (which requires path + oldText + newText).
423
+ // See: https://github.com/gsd-build/gsd-2/issues/2946
424
+ const mentionsWriteTool =
425
+ /PROJECT\.md.*\bwrite\b/i.test(prompt) ||
426
+ /\bwrite\b.*PROJECT\.md/i.test(prompt);
427
+ assertTrue(mentionsWriteTool, 'step 13 must name the `write` tool when updating PROJECT.md');
428
+ }
429
+
409
430
  // ═══════════════════════════════════════════════════════════════════════════
410
431
 
411
432
  report();
@@ -0,0 +1,192 @@
1
+ // GSD State Machine Regression Tests — Completion Hierarchy & State Derivation (#3161)
2
+
3
+ import { describe, test, beforeEach, afterEach } from "node:test";
4
+ import assert from "node:assert/strict";
5
+
6
+ import {
7
+ openDatabase,
8
+ closeDatabase,
9
+ insertMilestone,
10
+ insertSlice,
11
+ insertTask,
12
+ getTask,
13
+ getSlice,
14
+ getMilestone,
15
+ getSliceTasks,
16
+ updateTaskStatus,
17
+ updateSliceStatus,
18
+ } from "../gsd-db.ts";
19
+ import { isClosedStatus } from "../status-guards.ts";
20
+
21
+ // ─── Setup / Teardown ──────────────────────────────────────────────────────
22
+
23
+ beforeEach(() => {
24
+ openDatabase(":memory:");
25
+ });
26
+
27
+ afterEach(() => {
28
+ try { closeDatabase(); } catch { /* swallow */ }
29
+ });
30
+
31
+ // ═══════════════════════════════════════════════════════════════════════════
32
+ // Tests
33
+ // ═══════════════════════════════════════════════════════════════════════════
34
+
35
+ describe("completion-hierarchy-guards", () => {
36
+
37
+ // ─── Test 1: isClosedStatus ─────────────────────────────────────────────
38
+ test("isClosedStatus returns true for 'complete' and 'done'", () => {
39
+ assert.ok(isClosedStatus("complete"), "'complete' should be closed");
40
+ assert.ok(isClosedStatus("done"), "'done' should be closed");
41
+ assert.ok(!isClosedStatus("pending"), "'pending' should not be closed");
42
+ assert.ok(!isClosedStatus("in-progress"), "'in-progress' should not be closed");
43
+ assert.ok(!isClosedStatus("blocked"), "'blocked' should not be closed");
44
+ assert.ok(!isClosedStatus(""), "empty string should not be closed");
45
+ assert.ok(!isClosedStatus("active"), "'active' should not be closed");
46
+ });
47
+
48
+ // ─── Test 2: vacuous truth guard — slice with zero tasks ───────────────
49
+ test("cannot complete slice with zero tasks — vacuous truth guard", () => {
50
+ insertMilestone({ id: "M001" });
51
+ insertSlice({ id: "S01", milestoneId: "M001" });
52
+
53
+ const tasks = getSliceTasks("M001", "S01");
54
+ assert.equal(tasks.length, 0, "newly inserted slice has zero tasks");
55
+
56
+ // The guard: a slice with no tasks is not completable.
57
+ // isSliceComplete from state.ts: plan.tasks.length > 0 && every done.
58
+ // Here we replicate the DB-side equivalent: zero tasks means guard fires.
59
+ const isCompletable = tasks.length > 0 && tasks.every(t => isClosedStatus(t.status));
60
+ assert.equal(isCompletable, false, "vacuous truth guard: zero tasks → not completable");
61
+ });
62
+
63
+ // ─── Test 3: cannot complete slice with incomplete tasks ─────────────────
64
+ test("cannot complete slice with incomplete tasks", () => {
65
+ insertMilestone({ id: "M001" });
66
+ insertSlice({ id: "S01", milestoneId: "M001" });
67
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", status: "done" });
68
+ insertTask({ id: "T02", sliceId: "S01", milestoneId: "M001", status: "pending" });
69
+
70
+ const tasks = getSliceTasks("M001", "S01");
71
+ assert.equal(tasks.length, 2, "slice has 2 tasks");
72
+
73
+ const incompleteTasks = tasks.filter(t => !isClosedStatus(t.status));
74
+ assert.equal(incompleteTasks.length, 1, "exactly one task is not closed");
75
+ assert.equal(incompleteTasks[0]?.id, "T02", "the incomplete task is T02");
76
+ assert.equal(incompleteTasks[0]?.status, "pending", "incomplete task status is 'pending'");
77
+ });
78
+
79
+ // ─── Test 4: phantom parent milestone and slice (H6) ────────────────────
80
+ test("task completion auto-creates phantom parent milestone and slice (H6)", () => {
81
+ // H6 finding: insertMilestone/insertSlice accept empty titles — phantom
82
+ // parents can be created without substantive content.
83
+ insertMilestone({ id: "M001" });
84
+ insertSlice({ id: "S01", milestoneId: "M001" });
85
+
86
+ const milestone = getMilestone("M001");
87
+ assert.ok(milestone !== null, "phantom milestone M001 should exist in DB");
88
+ assert.equal(milestone!.title, "", "phantom milestone has empty title by default");
89
+
90
+ const slice = getSlice("M001", "S01");
91
+ assert.ok(slice !== null, "phantom slice S01 should exist in DB");
92
+ assert.equal(slice!.title, "", "phantom slice has empty title by default");
93
+
94
+ // This documents the H6 finding: the DB allows phantom parents with
95
+ // no meaningful content, which can silently accept task completion calls.
96
+ });
97
+
98
+ // ─── Test 5: double task completion is detectable via isClosedStatus ────
99
+ test("double task completion is detectable via isClosedStatus", () => {
100
+ insertMilestone({ id: "M001" });
101
+ insertSlice({ id: "S01", milestoneId: "M001" });
102
+ insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", status: "done" });
103
+
104
+ const task = getTask("M001", "S01", "T01");
105
+ assert.ok(task !== null, "task T01 should exist");
106
+ assert.ok(
107
+ isClosedStatus(task!.status),
108
+ "isClosedStatus detects already-closed task — prevents double completion",
109
+ );
110
+
111
+ // The guard that prevents double completion: check isClosedStatus before
112
+ // calling updateTaskStatus again.
113
+ const wouldDoubleComplete = isClosedStatus(task!.status);
114
+ assert.ok(wouldDoubleComplete, "guard fires: task is already closed");
115
+ });
116
+
117
+ // ─── Test 6: updateSliceStatus rollback loses original status (M11) ─────
118
+ test("updateSliceStatus rollback goes to 'pending' not original status (M11)", () => {
119
+ insertMilestone({ id: "M001" });
120
+ // Insert with an explicit non-pending status to simulate an in-progress slice
121
+ insertSlice({ id: "S01", milestoneId: "M001", status: "pending" });
122
+
123
+ // Manually advance to "in_progress" equivalent via updateSliceStatus
124
+ updateSliceStatus("M001", "S01", "in_progress");
125
+ const afterProgress = getSlice("M001", "S01");
126
+ assert.equal(afterProgress!.status, "in_progress", "slice is in_progress after update");
127
+
128
+ // Simulate completion
129
+ updateSliceStatus("M001", "S01", "complete", new Date().toISOString());
130
+ const afterComplete = getSlice("M001", "S01");
131
+ assert.equal(afterComplete!.status, "complete", "slice is complete after completion");
132
+
133
+ // Simulate rollback — the DB only stores current status, not history.
134
+ // Rolling back means setting to "pending" — the original "in_progress" is lost.
135
+ updateSliceStatus("M001", "S01", "pending");
136
+ const afterRollback = getSlice("M001", "S01");
137
+ assert.equal(
138
+ afterRollback!.status,
139
+ "pending",
140
+ "M11: rollback sets status to 'pending', original 'in_progress' is lost",
141
+ );
142
+ // Document: there is no completed_at or status history to recover from.
143
+ // The rollback silently discards the in_progress state.
144
+ });
145
+
146
+ // ─── Test 7: milestone completion requires all slices closed ─────────────
147
+ test("milestone completion requires all slices closed", () => {
148
+ insertMilestone({ id: "M001" });
149
+ insertSlice({ id: "S01", milestoneId: "M001", status: "done" });
150
+ insertSlice({ id: "S02", milestoneId: "M001", status: "pending" });
151
+
152
+ const s01 = getSlice("M001", "S01");
153
+ const s02 = getSlice("M001", "S02");
154
+
155
+ assert.ok(s01 !== null, "S01 exists");
156
+ assert.ok(s02 !== null, "S02 exists");
157
+
158
+ const slices = [s01!, s02!];
159
+ const incompleteSlices = slices.filter(s => !isClosedStatus(s.status));
160
+ assert.ok(
161
+ incompleteSlices.length > 0,
162
+ "milestone is not completable — has incomplete slices",
163
+ );
164
+ assert.equal(incompleteSlices[0]?.id, "S02", "S02 is the incomplete slice");
165
+ assert.equal(incompleteSlices[0]?.status, "pending", "S02 status is 'pending'");
166
+ });
167
+
168
+ // ─── Test 8: closed parent blocks child completion ───────────────────────
169
+ test("closed parent blocks child completion", () => {
170
+ // Insert a milestone already in 'complete' state
171
+ insertMilestone({ id: "M001", status: "complete" });
172
+ insertSlice({ id: "S01", milestoneId: "M001" });
173
+
174
+ const milestone = getMilestone("M001");
175
+ assert.ok(milestone !== null, "milestone M001 exists");
176
+ assert.ok(
177
+ isClosedStatus(milestone!.status),
178
+ "parent milestone is closed — isClosedStatus returns true",
179
+ );
180
+
181
+ // The guard in complete-slice checks parent status via isClosedStatus.
182
+ // If isClosedStatus(milestone.status) === true, the child cannot be completed.
183
+ const parentIsClosed = isClosedStatus(milestone!.status);
184
+ assert.ok(parentIsClosed, "closed parent guard fires: milestone.status is 'complete'");
185
+
186
+ // Verify the slice itself is not yet closed
187
+ const slice = getSlice("M001", "S01");
188
+ assert.ok(slice !== null, "slice S01 exists");
189
+ assert.ok(!isClosedStatus(slice!.status), "slice S01 is not yet closed (parent is already closed)");
190
+ });
191
+
192
+ });