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,107 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { readFileSync } from "node:fs";
4
+ import { join, dirname } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const gsdDir = join(__dirname, "..");
9
+
10
+ /**
11
+ * Regression tests for #2826: hook/* completed-unit keys were parsed
12
+ * incorrectly by forensics + doctor, causing false-positive missing-artifact
13
+ * errors for all hook units.
14
+ *
15
+ * The root cause: `key.indexOf("/")` splits "hook/telegram-progress/M007/S01"
16
+ * into unitType="hook" + unitId="telegram-progress/M007/S01" instead of
17
+ * unitType="hook/telegram-progress" + unitId="M007/S01".
18
+ */
19
+
20
+ describe("splitCompletedKey (#2826)", () => {
21
+ it("is exported from forensics.ts", () => {
22
+ const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
23
+ assert.ok(
24
+ source.includes("export function splitCompletedKey"),
25
+ "forensics.ts must export splitCompletedKey helper",
26
+ );
27
+ });
28
+
29
+ it("splits simple unit types correctly", async () => {
30
+ const { splitCompletedKey } = await import("../forensics.ts");
31
+ const result = splitCompletedKey("execute-task/M007/S01/T01");
32
+ assert.deepStrictEqual(result, {
33
+ unitType: "execute-task",
34
+ unitId: "M007/S01/T01",
35
+ });
36
+ });
37
+
38
+ it("splits hook unit types preserving the compound hook/<hookName> prefix", async () => {
39
+ const { splitCompletedKey } = await import("../forensics.ts");
40
+ const result = splitCompletedKey("hook/telegram-progress/M007/S01");
41
+ assert.deepStrictEqual(result, {
42
+ unitType: "hook/telegram-progress",
43
+ unitId: "M007/S01",
44
+ });
45
+ });
46
+
47
+ it("splits hook unit types with task-level unitId", async () => {
48
+ const { splitCompletedKey } = await import("../forensics.ts");
49
+ const result = splitCompletedKey("hook/telegram-progress/M007/S02/T01");
50
+ assert.deepStrictEqual(result, {
51
+ unitType: "hook/telegram-progress",
52
+ unitId: "M007/S02/T01",
53
+ });
54
+ });
55
+
56
+ it("returns null for malformed keys without a slash", async () => {
57
+ const { splitCompletedKey } = await import("../forensics.ts");
58
+ assert.strictEqual(splitCompletedKey("noslash"), null);
59
+ });
60
+
61
+ it("returns null for malformed hook keys with only 'hook/' and no more segments", async () => {
62
+ const { splitCompletedKey } = await import("../forensics.ts");
63
+ // "hook/someName" has no unitId segment after the hook name
64
+ assert.strictEqual(splitCompletedKey("hook/someName"), null);
65
+ });
66
+ });
67
+
68
+ describe("forensics detectMissingArtifacts uses splitCompletedKey (#2826)", () => {
69
+ it("does not use indexOf for key splitting", () => {
70
+ const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
71
+ // Extract only the detectMissingArtifacts function body
72
+ const fnStart = source.indexOf("function detectMissingArtifacts");
73
+ assert.ok(fnStart !== -1, "detectMissingArtifacts must exist");
74
+ const fnBody = source.slice(fnStart, source.indexOf("\n}\n", fnStart) + 3);
75
+
76
+ assert.ok(
77
+ !fnBody.includes('key.indexOf("/")'),
78
+ "detectMissingArtifacts must not use key.indexOf('/') — use splitCompletedKey instead",
79
+ );
80
+ assert.ok(
81
+ fnBody.includes("splitCompletedKey"),
82
+ "detectMissingArtifacts must use splitCompletedKey helper",
83
+ );
84
+ });
85
+ });
86
+
87
+ describe("doctor-runtime-checks uses splitCompletedKey (#2826)", () => {
88
+ it("does not use indexOf for key splitting in orphaned-key check", () => {
89
+ const source = readFileSync(
90
+ join(gsdDir, "doctor-runtime-checks.ts"),
91
+ "utf-8",
92
+ );
93
+ // Find the orphaned completed-units section
94
+ const sectionStart = source.indexOf("Orphaned completed-units");
95
+ assert.ok(sectionStart !== -1, "orphaned completed-units section must exist");
96
+ const sectionBody = source.slice(sectionStart, source.indexOf("} catch", sectionStart));
97
+
98
+ assert.ok(
99
+ !sectionBody.includes('key.indexOf("/")'),
100
+ "doctor orphaned-key check must not use key.indexOf('/') — use splitCompletedKey instead",
101
+ );
102
+ assert.ok(
103
+ sectionBody.includes("splitCompletedKey"),
104
+ "doctor orphaned-key check must use splitCompletedKey helper",
105
+ );
106
+ });
107
+ });
@@ -111,7 +111,51 @@ test("resolveExpectedArtifactPath returns correct path for all slice-level types
111
111
 
112
112
  const uatResult = resolveExpectedArtifactPath("run-uat", "M001/S01", base);
113
113
  assert.ok(uatResult);
114
- assert.ok(uatResult!.includes("UAT"));
114
+ assert.ok(uatResult!.includes("ASSESSMENT"));
115
+ });
116
+
117
+ // ─── run-uat artifact path contract (#2873) ──────────────────────────────
118
+
119
+ test("resolveExpectedArtifactPath for run-uat returns ASSESSMENT path, not UAT (#2873)", (t) => {
120
+ // The run-uat prompt instructs the agent to call gsd_summary_save with
121
+ // artifact_type: "ASSESSMENT", which writes S##-ASSESSMENT.md. The artifact
122
+ // verification path must match — otherwise verification fails and auto-mode
123
+ // retries the unit in an infinite loop.
124
+ const base = makeTmpBase();
125
+ t.after(() => cleanup(base));
126
+
127
+ const result = resolveExpectedArtifactPath("run-uat", "M001/S01", base);
128
+ assert.ok(result, "run-uat should resolve to a non-null artifact path");
129
+ assert.ok(
130
+ result!.endsWith("S01-ASSESSMENT.md"),
131
+ `run-uat artifact path should end with S01-ASSESSMENT.md, got: ${result}`,
132
+ );
133
+ });
134
+
135
+ test("diagnoseExpectedArtifact for run-uat references ASSESSMENT (#2873)", (t) => {
136
+ const base = makeTmpBase();
137
+ t.after(() => cleanup(base));
138
+
139
+ const diag = diagnoseExpectedArtifact("run-uat", "M001/S01", base);
140
+ assert.ok(diag, "run-uat should have a diagnostic message");
141
+ assert.ok(
142
+ diag!.includes("ASSESSMENT"),
143
+ `run-uat diagnostic should reference ASSESSMENT, got: ${diag}`,
144
+ );
145
+ });
146
+
147
+ test("verifyExpectedArtifact passes for run-uat when ASSESSMENT file exists (#2873)", (t) => {
148
+ // Regression test: run-uat writes S##-ASSESSMENT.md via gsd_summary_save,
149
+ // but verification looked for S##-UAT.md, causing false stuck retries.
150
+ const base = makeTmpBase();
151
+ t.after(() => cleanup(base));
152
+
153
+ // Write the ASSESSMENT file (what gsd_summary_save actually produces)
154
+ const assessPath = join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-ASSESSMENT.md");
155
+ writeFileSync(assessPath, "---\nverdict: PASS\n---\n# UAT Assessment\n");
156
+
157
+ const verified = verifyExpectedArtifact("run-uat", "M001/S01", base);
158
+ assert.ok(verified, "verifyExpectedArtifact should pass when ASSESSMENT file exists");
115
159
  });
116
160
 
117
161
  // ─── diagnoseExpectedArtifact ─────────────────────────────────────────────
@@ -697,6 +741,72 @@ test("verifyExpectedArtifact complete-milestone fails with only .gsd/ files (#17
697
741
  assert.equal(result, false, "complete-milestone should fail verification when only .gsd/ files present");
698
742
  });
699
743
 
744
+ // ─── reconcileMergeState: silent nativeCommit failure (#2542) ─────────────
745
+
746
+ import { reconcileMergeState } from "../../auto-recovery.ts";
747
+ import { chmodSync } from "node:fs";
748
+
749
+ function makeMockCtx(): { ctx: any; notifications: Array<{ msg: string; level: string }> } {
750
+ const notifications: Array<{ msg: string; level: string }> = [];
751
+ const ctx = {
752
+ ui: {
753
+ notify(msg: string, level: string) {
754
+ notifications.push({ msg, level });
755
+ },
756
+ },
757
+ };
758
+ return { ctx, notifications };
759
+ }
760
+
761
+ test("reconcileMergeState returns false and notifies error when nativeCommit fails (#2542)", (t) => {
762
+ const base = makeGitBase();
763
+ t.after(() => cleanup(base));
764
+
765
+ // Create a second branch with a commit, then start a merge on main
766
+ execFileSync("git", ["checkout", "-b", "feature"], { cwd: base, stdio: "ignore" });
767
+ writeFileSync(join(base, "feature.txt"), "feature content");
768
+ execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
769
+ execFileSync("git", ["commit", "-m", "add feature"], { cwd: base, stdio: "ignore" });
770
+ execFileSync("git", ["checkout", "main"], { cwd: base, stdio: "ignore" });
771
+
772
+ // Start merge (no conflicts — fast path with MERGE_HEAD)
773
+ execFileSync("git", ["merge", "--no-ff", "--no-commit", "feature"], { cwd: base, stdio: "ignore" });
774
+
775
+ // Verify MERGE_HEAD exists
776
+ assert.ok(existsSync(join(base, ".git", "MERGE_HEAD")), "MERGE_HEAD should exist");
777
+
778
+ // Make .git/objects read-only so git cannot write the commit object,
779
+ // causing nativeCommit to throw a non-"nothing to commit" error.
780
+ const objectsDir = join(base, ".git", "objects");
781
+ chmodSync(objectsDir, 0o444);
782
+ t.after(() => { try { chmodSync(objectsDir, 0o755); } catch { /* cleanup */ } });
783
+
784
+ const { ctx, notifications } = makeMockCtx();
785
+ const result = reconcileMergeState(base, ctx);
786
+
787
+ // The function should return false to signal reconciliation failure
788
+ // (Currently it silently swallows the error and returns true — this test should FAIL before the fix)
789
+ assert.equal(result, false, "reconcileMergeState should return false when nativeCommit fails");
790
+ const errorNotifications = notifications.filter(n => n.level === "error");
791
+ assert.ok(errorNotifications.length > 0, "should notify an error when nativeCommit fails");
792
+ assert.ok(
793
+ errorNotifications[0].msg.includes("Failed to finalize"),
794
+ "error notification should describe the commit failure",
795
+ );
796
+ });
797
+
798
+ test("reconcileMergeState returns true when no merge state present", (t) => {
799
+ // When there's no MERGE_HEAD or SQUASH_MSG, reconcileMergeState returns false (no dirty state)
800
+ const base = makeGitBase();
801
+ t.after(() => cleanup(base));
802
+
803
+ const { ctx, notifications } = makeMockCtx();
804
+ const result = reconcileMergeState(base, ctx);
805
+
806
+ assert.equal(result, false, "should return false when no merge state exists");
807
+ assert.equal(notifications.length, 0, "should not notify when no merge state present");
808
+ });
809
+
700
810
  test("verifyExpectedArtifact complete-milestone passes with impl files (#1703)", (t) => {
701
811
  const base = makeGitBase();
702
812
  t.after(() => cleanup(base));
@@ -638,6 +638,107 @@ describe("auto-worktree-milestone-merge", { timeout: 300_000 }, () => {
638
638
  "#1906: codeFilesChanged must be false when only .gsd/ files were merged");
639
639
  });
640
640
 
641
+ test("#2912: MERGE_HEAD cleaned up after squash-merge conflict", () => {
642
+ const repo = freshRepo();
643
+ const wtPath = createAutoWorktree(repo, "M291");
644
+
645
+ // Create a file on main that will conflict with the milestone branch
646
+ run("git checkout main", repo);
647
+ writeFileSync(join(repo, "conflict.ts"), "// main version\nexport const x = 1;\n");
648
+ run("git add .", repo);
649
+ run("git commit -m 'add conflict.ts on main'", repo);
650
+
651
+ // Switch back to milestone branch and create conflicting content
652
+ run("git checkout milestone/M291", wtPath);
653
+ writeFileSync(join(wtPath, "conflict.ts"), "// milestone version\nexport const x = 2;\n");
654
+ run("git add .", wtPath);
655
+ run("git commit -m 'add conflict.ts on milestone'", wtPath);
656
+
657
+ const roadmap = makeRoadmap("M291", "Conflict milestone", [
658
+ { id: "S01", title: "Conflict test" },
659
+ ]);
660
+
661
+ // The merge should throw MergeConflictError due to conflict.ts
662
+ let threw = false;
663
+ try {
664
+ mergeMilestoneToMain(repo, "M291", roadmap);
665
+ } catch (err: unknown) {
666
+ threw = true;
667
+ // Verify it's a merge conflict error
668
+ assert.ok(
669
+ err instanceof Error && err.message.includes("conflict"),
670
+ "should throw a conflict-related error",
671
+ );
672
+ }
673
+ assert.ok(threw, "mergeMilestoneToMain must throw on code conflict");
674
+
675
+ // BUG #2912: MERGE_HEAD must NOT be left on disk after the error
676
+ const mergeHeadPath = join(repo, ".git", "MERGE_HEAD");
677
+ assert.ok(
678
+ !existsSync(mergeHeadPath),
679
+ "#2912: MERGE_HEAD must be cleaned up after merge conflict error",
680
+ );
681
+ });
682
+
683
+ test("#2912: stale MERGE_HEAD from native merge is cleaned after successful commit", () => {
684
+ const repo = freshRepo();
685
+ const wtPath = createAutoWorktree(repo, "M292");
686
+
687
+ addSliceToMilestone(repo, wtPath, "M292", "S01", "Feature A", [
688
+ { file: "feature-a.ts", content: "export const a = true;\n", message: "add feature a" },
689
+ ]);
690
+
691
+ const roadmap = makeRoadmap("M292", "Clean merge", [
692
+ { id: "S01", title: "Feature A" },
693
+ ]);
694
+
695
+ // Simulate what libgit2's merge implementation does: it creates MERGE_HEAD
696
+ // even for squash merges (unlike CLI git). We plant MERGE_HEAD before calling
697
+ // mergeMilestoneToMain to verify the success path cleans it up.
698
+ // We cannot plant it before the call because the function manages checkout
699
+ // internally, so instead we verify after the call.
700
+ mergeMilestoneToMain(repo, "M292", roadmap);
701
+
702
+ // After successful merge+commit, MERGE_HEAD must not linger
703
+ const mergeHeadPath = join(repo, ".git", "MERGE_HEAD");
704
+ assert.ok(
705
+ !existsSync(mergeHeadPath),
706
+ "#2912: MERGE_HEAD must be cleaned up after successful merge",
707
+ );
708
+ });
709
+
710
+ test("#2912: planted MERGE_HEAD is cleaned up in success path", () => {
711
+ // This test directly verifies the cleanup code handles a MERGE_HEAD file
712
+ // left by the native (libgit2) merge path. We hook into the merge by
713
+ // planting MERGE_HEAD right after nativeMergeSquash would create it.
714
+ const repo = freshRepo();
715
+ const wtPath = createAutoWorktree(repo, "M293");
716
+
717
+ addSliceToMilestone(repo, wtPath, "M293", "S01", "Feature B", [
718
+ { file: "feature-b.ts", content: "export const b = true;\n", message: "add feature b" },
719
+ ]);
720
+
721
+ const roadmap = makeRoadmap("M293", "Planted MERGE_HEAD", [
722
+ { id: "S01", title: "Feature B" },
723
+ ]);
724
+
725
+ // Plant a fake MERGE_HEAD in the git dir to simulate libgit2 behavior.
726
+ // We need to do this after the function checks out main but before it
727
+ // commits. Since we can't intercept mid-function, we plant it before
728
+ // the call. If the function cleans it up, the test passes.
729
+ const gitDir = join(repo, ".git");
730
+ const fakeHead = run("git rev-parse HEAD", repo);
731
+ writeFileSync(join(gitDir, "MERGE_HEAD"), fakeHead + "\n");
732
+
733
+ mergeMilestoneToMain(repo, "M293", roadmap);
734
+
735
+ // The planted MERGE_HEAD must be cleaned up
736
+ assert.ok(
737
+ !existsSync(join(gitDir, "MERGE_HEAD")),
738
+ "#2912: planted MERGE_HEAD must be removed by success-path cleanup",
739
+ );
740
+ });
741
+
641
742
  test("#1906: codeFilesChanged=true when real code is merged", () => {
642
743
  const repo = freshRepo();
643
744
  const wtPath = createAutoWorktree(repo, "M190");
@@ -20,6 +20,7 @@ import {
20
20
  enterAutoWorktree,
21
21
  getAutoWorktreeOriginalBase,
22
22
  getActiveAutoWorktreeContext,
23
+ syncGsdStateToWorktree,
23
24
  } from "../../auto-worktree.ts";
24
25
 
25
26
  // Note: execSync is used intentionally in tests for git operations with
@@ -286,4 +287,62 @@ describe("auto-worktree lifecycle", () => {
286
287
  teardownAutoWorktree(tempDir, "M004");
287
288
  }
288
289
  });
290
+
291
+ test("#2791: mcp.json copied into worktree via copyPlanningArtifacts", () => {
292
+ tempDir = createTempRepo();
293
+ const msDir = join(tempDir, ".gsd", "milestones", "M003");
294
+ mkdirSync(msDir, { recursive: true });
295
+ writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
296
+ run("git add .", tempDir);
297
+ run("git commit -m \"add milestone\"", tempDir);
298
+
299
+ // Create mcp.json in .gsd/ AFTER the commit (untracked, like real usage).
300
+ // copyPlanningArtifacts should copy it into the worktree's .gsd/.
301
+ writeFileSync(
302
+ join(tempDir, ".gsd", "mcp.json"),
303
+ JSON.stringify({ servers: { test: { command: "echo" } } }),
304
+ );
305
+
306
+ const wtPath = createAutoWorktree(tempDir, "M003");
307
+
308
+ try {
309
+ assert.ok(
310
+ existsSync(join(wtPath, ".gsd", "mcp.json")),
311
+ "mcp.json should be copied into worktree .gsd/ on creation",
312
+ );
313
+ } finally {
314
+ teardownAutoWorktree(tempDir, "M003");
315
+ }
316
+ });
317
+
318
+ test("#2791: mcp.json synced via syncGsdStateToWorktree (ROOT_STATE_FILES)", () => {
319
+ tempDir = createTempRepo();
320
+ const msDir = join(tempDir, ".gsd", "milestones", "M003");
321
+ mkdirSync(msDir, { recursive: true });
322
+ writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
323
+ run("git add .", tempDir);
324
+ run("git commit -m \"add milestone\"", tempDir);
325
+
326
+ // Create worktree first (no mcp.json yet)
327
+ const wtPath = createAutoWorktree(tempDir, "M003");
328
+
329
+ try {
330
+ // Now add mcp.json to the main .gsd/ after worktree was created
331
+ writeFileSync(
332
+ join(tempDir, ".gsd", "mcp.json"),
333
+ JSON.stringify({ servers: { test: { command: "echo" } } }),
334
+ );
335
+
336
+ // Sync should pick up the new mcp.json
337
+ const { synced } = syncGsdStateToWorktree(tempDir, wtPath);
338
+
339
+ assert.ok(synced.includes("mcp.json"), "mcp.json should be in the synced list");
340
+ assert.ok(
341
+ existsSync(join(wtPath, ".gsd", "mcp.json")),
342
+ "mcp.json should exist in worktree after sync",
343
+ );
344
+ } finally {
345
+ teardownAutoWorktree(tempDir, "M003");
346
+ }
347
+ });
289
348
  });
@@ -0,0 +1,243 @@
1
+ import { describe, test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync, existsSync, readdirSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+
7
+ import { runGSDDoctor } from "../../doctor.js";
8
+ import { parsePlan } from "../../parsers-legacy.js";
9
+
10
+ // ── Helpers ─────────────────────────────────────────────────────────────────
11
+
12
+ function makeBase(): { base: string; gsd: string; mDir: string } {
13
+ const base = mkdtempSync(join(tmpdir(), "gsd-doctor-fp-"));
14
+ const gsd = join(base, ".gsd");
15
+ const mDir = join(gsd, "milestones", "M001");
16
+ mkdirSync(join(mDir, "slices"), { recursive: true });
17
+ return { base, gsd, mDir };
18
+ }
19
+
20
+ function writeRoadmap(mDir: string, content: string): void {
21
+ writeFileSync(join(mDir, "M001-ROADMAP.md"), content);
22
+ }
23
+
24
+ function writeSlice(mDir: string, sliceId: string, planContent: string): string {
25
+ const sDir = join(mDir, "slices", sliceId);
26
+ const tDir = join(sDir, "tasks");
27
+ mkdirSync(tDir, { recursive: true });
28
+ writeFileSync(join(sDir, `${sliceId}-PLAN.md`), planContent);
29
+ return sDir;
30
+ }
31
+
32
+ describe('doctor false-positives (#3105)', async () => {
33
+
34
+ // ═══════════════════════════════════════════════════════════════════════════
35
+ // Bug 1: Orphaned worktree directory recreated by appendDoctorHistory
36
+ // ═══════════════════════════════════════════════════════════════════════════
37
+
38
+ test('Bug 1: orphaned worktree check ignores dirs containing only .gsd/doctor-history.jsonl', async () => {
39
+ // Simulate: a worktree dir that only contains .gsd/doctor-history.jsonl
40
+ // (created by appendDoctorHistory writing to the worktree-scoped path).
41
+ // The orphan check should NOT warn about this directory.
42
+ const { base, gsd } = makeBase();
43
+ writeRoadmap(join(gsd, "milestones", "M001"), `# M001: Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
44
+ writeSlice(join(gsd, "milestones", "M001"), "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
45
+
46
+ // Create a worktree directory that only has .gsd/doctor-history.jsonl
47
+ const wtDir = join(gsd, "worktrees", "M042");
48
+ const wtGsdDir = join(wtDir, ".gsd");
49
+ mkdirSync(wtGsdDir, { recursive: true });
50
+ writeFileSync(join(wtGsdDir, "doctor-history.jsonl"), '{"ts":"2026-01-01","ok":true}\n');
51
+
52
+ const result = await runGSDDoctor(base, { fix: false });
53
+
54
+ // Should NOT produce worktree_directory_orphaned for a dir that only has doctor history
55
+ const orphanIssues = result.issues.filter(
56
+ i => i.code === "worktree_directory_orphaned" && i.unitId === "M042"
57
+ );
58
+ assert.equal(orphanIssues.length, 0,
59
+ "should not warn about worktree dir that only contains .gsd/doctor-history.jsonl");
60
+
61
+ rmSync(base, { recursive: true, force: true });
62
+ });
63
+
64
+ // ═══════════════════════════════════════════════════════════════════════════
65
+ // Bug 2: blocker_discovered + all tasks done = unfixable deadlock
66
+ // ═══════════════════════════════════════════════════════════════════════════
67
+
68
+ test('Bug 2: blocker_discovered with all tasks done should not warn (implicitly resolved)', async () => {
69
+ // Scenario: blocker was discovered and resolved within the same task.
70
+ // blocker_discovered: true, no REPLAN, but all tasks are done.
71
+ // Neither blocker_discovered_no_replan nor stale_replan_file should fire.
72
+ const { base, mDir } = makeBase();
73
+ writeRoadmap(mDir, `# M001: Blocker Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
74
+ const sDir = writeSlice(mDir, "S01",
75
+ "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [x] **T01: Task** `est:10m`\n Done.\n");
76
+ writeFileSync(join(sDir, "tasks", "T01-SUMMARY.md"), `---
77
+ id: T01
78
+ parent: S01
79
+ milestone: M001
80
+ provides: []
81
+ requires: []
82
+ affects: []
83
+ key_files: []
84
+ key_decisions: []
85
+ patterns_established: []
86
+ observability_surfaces: []
87
+ drill_down_paths: []
88
+ duration: 10m
89
+ verification_result: passed
90
+ completed_at: 2026-01-01T00:00:00Z
91
+ blocker_discovered: true
92
+ ---
93
+
94
+ # T01: Task
95
+
96
+ **Done**
97
+
98
+ ## What Happened
99
+ Found a blocker, resolved it in-task.
100
+
101
+ ## Diagnostics
102
+ - log
103
+ `);
104
+
105
+ const result = await runGSDDoctor(base, { fix: false });
106
+
107
+ // Should NOT produce blocker_discovered_no_replan when all tasks are done
108
+ const blockerIssues = result.issues.filter(i => i.code === "blocker_discovered_no_replan");
109
+ assert.equal(blockerIssues.length, 0,
110
+ "should not warn about blocker_discovered when all tasks are done (blocker was implicitly resolved)");
111
+
112
+ // Also should NOT produce stale_replan_file (no REPLAN exists, so this shouldn't fire anyway)
113
+ const staleReplanIssues = result.issues.filter(i => i.code === "stale_replan_file");
114
+ assert.equal(staleReplanIssues.length, 0,
115
+ "should not produce stale_replan_file when no REPLAN exists");
116
+
117
+ rmSync(base, { recursive: true, force: true });
118
+ });
119
+
120
+ test('Bug 2: blocker_discovered with incomplete tasks should still warn', async () => {
121
+ // Sanity check: when there IS an incomplete task and blocker_discovered, warn as before.
122
+ const { base, mDir } = makeBase();
123
+ writeRoadmap(mDir, `# M001: Blocker Warn Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
124
+ const sDir = writeSlice(mDir, "S01",
125
+ "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [x] **T01: Task A** `est:10m`\n Done.\n- [ ] **T02: Task B** `est:10m`\n Pending.\n");
126
+ writeFileSync(join(sDir, "tasks", "T01-SUMMARY.md"), `---
127
+ id: T01
128
+ parent: S01
129
+ milestone: M001
130
+ provides: []
131
+ requires: []
132
+ affects: []
133
+ key_files: []
134
+ key_decisions: []
135
+ patterns_established: []
136
+ observability_surfaces: []
137
+ drill_down_paths: []
138
+ duration: 10m
139
+ verification_result: passed
140
+ completed_at: 2026-01-01T00:00:00Z
141
+ blocker_discovered: true
142
+ ---
143
+
144
+ # T01: Task A
145
+
146
+ **Done**
147
+
148
+ ## What Happened
149
+ Found blocker, but T02 is still pending.
150
+
151
+ ## Diagnostics
152
+ - log
153
+ `);
154
+
155
+ const result = await runGSDDoctor(base, { fix: false });
156
+
157
+ const blockerIssues = result.issues.filter(i => i.code === "blocker_discovered_no_replan");
158
+ assert.ok(blockerIssues.length > 0,
159
+ "should still warn about blocker_discovered when some tasks are not done");
160
+
161
+ rmSync(base, { recursive: true, force: true });
162
+ });
163
+
164
+ // ═══════════════════════════════════════════════════════════════════════════
165
+ // Bug 3: Multi-task plan — T02+ outside ## Tasks section
166
+ // ═══════════════════════════════════════════════════════════════════════════
167
+
168
+ test('Bug 3: parsePlan finds all tasks even when interleaved with detail sections', () => {
169
+ // Multi-task plan where T02 checkbox appears after T01's ## Steps heading,
170
+ // which ends the ## Tasks section for extractSection().
171
+ const planContent = `# S01: Demo Slice
172
+
173
+ **Goal:** Build the demo
174
+ **Demo:** Run it
175
+
176
+ ## Must-Haves
177
+ - Feature A
178
+
179
+ ## Tasks
180
+ - [x] **T01: First task** \`est:30m\`
181
+ Implement the first thing.
182
+ ## Steps
183
+ 1. Step one
184
+ 2. Step two
185
+ ## Must-Haves
186
+ - Requirement A
187
+ - [x] **T02: Second task** \`est:1h\`
188
+ Implement the second thing.
189
+ ## Steps
190
+ 1. Step one
191
+ 2. Step two
192
+ `;
193
+
194
+ const plan = parsePlan(planContent);
195
+ const taskIds = plan.tasks.map(t => t.id);
196
+
197
+ assert.ok(taskIds.includes("T01"), "should find T01");
198
+ assert.ok(taskIds.includes("T02"), "should find T02 even when after T01 detail headings");
199
+ assert.equal(plan.tasks.length, 2, "should find exactly 2 tasks");
200
+ });
201
+
202
+ test('Bug 3: task_file_not_in_plan should not fire for T02 in multi-task plan', async () => {
203
+ const { base, mDir } = makeBase();
204
+ writeRoadmap(mDir, `# M001: Multi-Task Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
205
+
206
+ // Plan with interleaved headings (the problematic format)
207
+ const sDir = writeSlice(mDir, "S01", `# S01: Demo Slice
208
+
209
+ **Goal:** Build the demo
210
+ **Demo:** Run it
211
+
212
+ ## Must-Haves
213
+ - Feature A
214
+
215
+ ## Tasks
216
+ - [x] **T01: First task** \`est:30m\`
217
+ Implement the first thing.
218
+ ## Steps
219
+ 1. Step one
220
+ ## Must-Haves
221
+ - Req A
222
+ - [x] **T02: Second task** \`est:1h\`
223
+ Implement the second thing.
224
+ ## Steps
225
+ 1. Step one
226
+ `);
227
+
228
+ // Both tasks have summaries on disk
229
+ writeFileSync(join(sDir, "tasks", "T01-SUMMARY.md"), "---\nstatus: done\ncompleted_at: 2026-01-01T00:00:00Z\n---\n# T01\nDone.\n");
230
+ writeFileSync(join(sDir, "tasks", "T02-SUMMARY.md"), "---\nstatus: done\ncompleted_at: 2026-01-01T00:00:00Z\n---\n# T02\nDone.\n");
231
+
232
+ const result = await runGSDDoctor(base, { fix: false });
233
+
234
+ // T02 should NOT be flagged as "not in plan"
235
+ const notInPlan = result.issues.filter(
236
+ i => i.code === "task_file_not_in_plan" && i.message.includes("T02")
237
+ );
238
+ assert.equal(notInPlan.length, 0,
239
+ "should not report T02 as 'not in plan' when it exists in the interleaved plan format");
240
+
241
+ rmSync(base, { recursive: true, force: true });
242
+ });
243
+ });