gsd-pi 2.76.0-dev.fe143342a → 2.77.0-dev.1d17f366c

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 (597) hide show
  1. package/README.md +17 -35
  2. package/dist/claude-cli-check.js +32 -3
  3. package/dist/cli-web-branch.d.ts +1 -0
  4. package/dist/cli-web-branch.js +3 -0
  5. package/dist/cli.js +38 -2
  6. package/dist/extension-discovery.d.ts +6 -0
  7. package/dist/extension-discovery.js +37 -0
  8. package/dist/extension-registry.d.ts +3 -0
  9. package/dist/extension-sort.d.ts +18 -0
  10. package/dist/extension-sort.js +114 -0
  11. package/dist/extension-validator.d.ts +47 -0
  12. package/dist/extension-validator.js +127 -0
  13. package/dist/loader.js +35 -7
  14. package/dist/onboarding.js +45 -0
  15. package/dist/provider-migrations.d.ts +18 -0
  16. package/dist/provider-migrations.js +14 -0
  17. package/dist/resources/extensions/claude-code-cli/readiness.js +4 -3
  18. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +78 -59
  19. package/dist/resources/extensions/cmux/index.js +20 -0
  20. package/dist/resources/extensions/github-sync/templates.js +103 -0
  21. package/dist/resources/extensions/google-search/extension-manifest.json +5 -4
  22. package/dist/resources/extensions/google-search/index.js +3 -375
  23. package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +90 -2
  25. package/dist/resources/extensions/gsd/auto/phases.js +95 -21
  26. package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
  27. package/dist/resources/extensions/gsd/auto/run-unit.js +48 -4
  28. package/dist/resources/extensions/gsd/auto/session.js +18 -1
  29. package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
  30. package/dist/resources/extensions/gsd/auto-dispatch.js +115 -17
  31. package/dist/resources/extensions/gsd/auto-loop.js +1 -1
  32. package/dist/resources/extensions/gsd/auto-model-selection.js +1 -1
  33. package/dist/resources/extensions/gsd/auto-post-unit.js +90 -2
  34. package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
  35. package/dist/resources/extensions/gsd/auto-recovery.js +46 -1
  36. package/dist/resources/extensions/gsd/auto-start.js +45 -39
  37. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
  38. package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
  39. package/dist/resources/extensions/gsd/auto-worktree.js +109 -61
  40. package/dist/resources/extensions/gsd/auto.js +97 -31
  41. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +27 -1
  42. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +4 -2
  43. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +11 -0
  44. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -6
  45. package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -6
  46. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
  47. package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
  48. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
  49. package/dist/resources/extensions/gsd/commands-cmux.js +9 -6
  50. package/dist/resources/extensions/gsd/commands-extensions.js +634 -43
  51. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
  52. package/dist/resources/extensions/gsd/dispatch-guard.js +29 -3
  53. package/dist/resources/extensions/gsd/file-lock.js +49 -9
  54. package/dist/resources/extensions/gsd/git-service.js +1 -0
  55. package/dist/resources/extensions/gsd/gitignore.js +2 -0
  56. package/dist/resources/extensions/gsd/gsd-db.js +90 -30
  57. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
  58. package/dist/resources/extensions/gsd/guided-flow.js +212 -9
  59. package/dist/resources/extensions/gsd/health-widget.js +4 -1
  60. package/dist/resources/extensions/gsd/journal.js +17 -2
  61. package/dist/resources/extensions/gsd/key-manager.js +22 -0
  62. package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
  63. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  64. package/dist/resources/extensions/gsd/model-router.js +36 -3
  65. package/dist/resources/extensions/gsd/notifications.js +30 -16
  66. package/dist/resources/extensions/gsd/pre-execution-checks.js +31 -6
  67. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  68. package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
  69. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  70. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  71. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  72. package/dist/resources/extensions/gsd/reports.js +5 -4
  73. package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
  74. package/dist/resources/extensions/gsd/safety/file-change-validator.js +12 -4
  75. package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
  76. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  77. package/dist/resources/extensions/gsd/state.js +25 -25
  78. package/dist/resources/extensions/gsd/token-counter.js +22 -5
  79. package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
  80. package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
  81. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
  82. package/dist/resources/extensions/gsd/uok/audit.js +18 -2
  83. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  84. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  85. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  86. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  87. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  88. package/dist/resources/extensions/gsd/uok/plan-v2.js +30 -7
  89. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  90. package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
  91. package/dist/resources/extensions/gsd/worktree-manager.js +1 -0
  92. package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
  93. package/dist/resources/extensions/mcp-client/auth.js +10 -1
  94. package/dist/resources/extensions/mcp-client/index.js +118 -9
  95. package/dist/resources/extensions/shared/cmux-events.js +12 -0
  96. package/dist/resources/extensions/shared/rtk-session-stats.js +1 -2
  97. package/dist/resources/skills/create-skill/SKILL.md +2 -2
  98. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  99. package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  100. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  101. package/dist/resources/skills/verify-before-complete/SKILL.md +2 -1
  102. package/dist/resources/skills/write-docs/SKILL.md +2 -1
  103. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  104. package/dist/web/standalone/.next/BUILD_ID +1 -1
  105. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  106. package/dist/web/standalone/.next/build-manifest.json +3 -3
  107. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  108. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/index.html +1 -1
  190. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  191. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  192. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  193. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  194. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  195. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  196. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  197. package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
  198. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  199. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  201. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  203. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  204. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  205. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  206. package/dist/web/standalone/.next/static/chunks/{webpack-5fc74f13a25fa1bb.js → webpack-2e68521d7c82f7c2.js} +1 -1
  207. package/dist/welcome-screen.js +6 -1
  208. package/dist/wizard.js +2 -0
  209. package/package.json +16 -14
  210. package/packages/daemon/package.json +2 -2
  211. package/packages/mcp-server/README.md +3 -3
  212. package/packages/mcp-server/dist/env-writer.d.ts +1 -0
  213. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
  214. package/packages/mcp-server/dist/env-writer.js +74 -6
  215. package/packages/mcp-server/dist/env-writer.js.map +1 -1
  216. package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
  217. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
  218. package/packages/mcp-server/dist/remote-questions.js +732 -0
  219. package/packages/mcp-server/dist/remote-questions.js.map +1 -0
  220. package/packages/mcp-server/dist/server.d.ts +7 -0
  221. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  222. package/packages/mcp-server/dist/server.js +95 -10
  223. package/packages/mcp-server/dist/server.js.map +1 -1
  224. package/packages/mcp-server/dist/session-manager.d.ts +14 -0
  225. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
  226. package/packages/mcp-server/dist/session-manager.js +49 -1
  227. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  228. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  229. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  230. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  231. package/packages/mcp-server/package.json +9 -3
  232. package/packages/mcp-server/src/env-writer.test.ts +79 -1
  233. package/packages/mcp-server/src/env-writer.ts +76 -6
  234. package/packages/mcp-server/src/mcp-server.test.ts +67 -0
  235. package/packages/mcp-server/src/readers/readers.test.ts +5 -1
  236. package/packages/mcp-server/src/remote-questions.test.ts +294 -0
  237. package/packages/mcp-server/src/remote-questions.ts +916 -0
  238. package/packages/mcp-server/src/server.ts +118 -16
  239. package/packages/mcp-server/src/session-manager.ts +43 -1
  240. package/packages/mcp-server/src/workflow-tools.test.ts +44 -0
  241. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  242. package/packages/mcp-server/tsconfig.test.json +19 -0
  243. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  244. package/packages/native/package.json +6 -1
  245. package/packages/native/src/__tests__/clipboard.test.mjs +69 -23
  246. package/packages/native/tsconfig.tsbuildinfo +1 -1
  247. package/packages/pi-agent-core/package.json +6 -1
  248. package/packages/pi-agent-core/src/agent-loop.test.ts +220 -15
  249. package/packages/pi-ai/dist/models/custom.d.ts +38 -0
  250. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/models/custom.js +41 -0
  252. package/packages/pi-ai/dist/models/custom.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
  254. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  255. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  256. package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
  257. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  258. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  259. package/packages/pi-ai/dist/providers/anthropic.js +8 -3
  260. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  261. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
  262. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
  263. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
  264. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
  265. package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
  266. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  267. package/packages/pi-ai/dist/providers/simple-options.js +16 -1
  268. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  269. package/packages/pi-ai/package.json +6 -1
  270. package/packages/pi-ai/src/models/custom.ts +42 -0
  271. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
  272. package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
  273. package/packages/pi-ai/src/providers/anthropic.ts +9 -3
  274. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
  275. package/packages/pi-ai/src/providers/simple-options.ts +17 -1
  276. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  277. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
  278. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
  280. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/agent-session.js +7 -0
  282. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +25 -0
  284. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +105 -6
  286. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +230 -28
  288. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +30 -2
  290. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/compaction/utils.js +113 -12
  292. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
  294. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +29 -18
  296. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
  298. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
  299. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
  300. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
  301. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +56 -1
  302. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +8 -15
  304. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  305. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts +25 -0
  306. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts.map +1 -0
  307. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js +109 -0
  308. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js.map +1 -0
  309. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts +67 -0
  310. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts.map +1 -0
  311. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js +167 -0
  312. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js.map +1 -0
  313. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +3 -2
  314. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  315. package/packages/pi-coding-agent/dist/core/extensions/loader.js +24 -8
  316. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
  318. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +14 -0
  321. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  323. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +11 -0
  324. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  325. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -2
  326. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
  328. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
  329. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
  330. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
  331. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/model-registry.js +14 -0
  333. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/resource-loader.js +1 -1
  335. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  336. package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
  337. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  338. package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
  339. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  340. package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
  341. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/session-manager.js +1 -1
  343. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  344. package/packages/pi-coding-agent/dist/core/session-manager.test.js +21 -1
  345. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  346. package/packages/pi-coding-agent/dist/core/system-prompt.js +3 -3
  347. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js +2 -1
  349. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
  351. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
  352. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
  354. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
  356. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  357. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
  358. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  359. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -0
  360. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  361. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
  363. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  364. package/packages/pi-coding-agent/package.json +6 -1
  365. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
  366. package/packages/pi-coding-agent/src/core/agent-session.ts +11 -0
  367. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +368 -28
  368. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +122 -6
  369. package/packages/pi-coding-agent/src/core/compaction/utils.ts +111 -13
  370. package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
  371. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +32 -18
  372. package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +68 -1
  373. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +9 -18
  374. package/packages/pi-coding-agent/src/core/extensions/extension-discovery.ts +119 -0
  375. package/packages/pi-coding-agent/src/core/extensions/extension-registry.ts +222 -0
  376. package/packages/pi-coding-agent/src/core/extensions/loader.ts +24 -11
  377. package/packages/pi-coding-agent/src/core/extensions/runner.ts +2 -0
  378. package/packages/pi-coding-agent/src/core/extensions/types.ts +15 -0
  379. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +13 -0
  380. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -2
  381. package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
  382. package/packages/pi-coding-agent/src/core/model-registry.ts +16 -0
  383. package/packages/pi-coding-agent/src/core/resource-loader.ts +1 -1
  384. package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
  385. package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
  386. package/packages/pi-coding-agent/src/core/session-manager.test.ts +30 -1
  387. package/packages/pi-coding-agent/src/core/session-manager.ts +1 -1
  388. package/packages/pi-coding-agent/src/core/system-prompt.ts +3 -3
  389. package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +2 -1
  390. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
  391. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
  392. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
  393. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +14 -0
  394. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
  395. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  396. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +12 -5
  397. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  398. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +21 -0
  399. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  400. package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
  401. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  402. package/packages/pi-tui/dist/stdin-buffer.js +20 -0
  403. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  404. package/packages/pi-tui/package.json +6 -1
  405. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -5
  406. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +27 -0
  407. package/packages/pi-tui/src/stdin-buffer.ts +26 -0
  408. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  409. package/packages/rpc-client/package.json +6 -1
  410. package/pkg/package.json +1 -1
  411. package/scripts/install.js +512 -0
  412. package/scripts/lib/workspace-manifest.cjs +86 -0
  413. package/scripts/link-workspace-packages.cjs +5 -17
  414. package/scripts/postinstall.js +9 -178
  415. package/src/resources/extensions/claude-code-cli/readiness.ts +4 -3
  416. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +91 -63
  417. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +114 -12
  418. package/src/resources/extensions/cmux/index.ts +35 -10
  419. package/src/resources/extensions/github-sync/templates.ts +151 -0
  420. package/src/resources/extensions/github-sync/tests/templates.test.ts +59 -0
  421. package/src/resources/extensions/google-search/extension-manifest.json +5 -4
  422. package/src/resources/extensions/google-search/index.ts +9 -470
  423. package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
  424. package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -1
  425. package/src/resources/extensions/gsd/auto/loop.ts +104 -2
  426. package/src/resources/extensions/gsd/auto/phases.ts +123 -21
  427. package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
  428. package/src/resources/extensions/gsd/auto/run-unit.ts +56 -4
  429. package/src/resources/extensions/gsd/auto/session.ts +28 -1
  430. package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
  431. package/src/resources/extensions/gsd/auto/types.ts +1 -1
  432. package/src/resources/extensions/gsd/auto-dispatch.ts +117 -16
  433. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  434. package/src/resources/extensions/gsd/auto-model-selection.ts +1 -1
  435. package/src/resources/extensions/gsd/auto-post-unit.ts +92 -3
  436. package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
  437. package/src/resources/extensions/gsd/auto-recovery.ts +40 -1
  438. package/src/resources/extensions/gsd/auto-start.ts +48 -52
  439. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
  440. package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
  441. package/src/resources/extensions/gsd/auto-worktree.ts +122 -68
  442. package/src/resources/extensions/gsd/auto.ts +105 -35
  443. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -1
  444. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -2
  445. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +11 -0
  446. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -6
  447. package/src/resources/extensions/gsd/bootstrap/system-context.ts +13 -9
  448. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
  449. package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
  450. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
  451. package/src/resources/extensions/gsd/commands-cmux.ts +10 -6
  452. package/src/resources/extensions/gsd/commands-extensions.ts +747 -41
  453. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
  454. package/src/resources/extensions/gsd/dispatch-guard.ts +26 -2
  455. package/src/resources/extensions/gsd/file-lock.ts +84 -11
  456. package/src/resources/extensions/gsd/git-service.ts +1 -0
  457. package/src/resources/extensions/gsd/gitignore.ts +2 -1
  458. package/src/resources/extensions/gsd/gsd-db.ts +92 -32
  459. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
  460. package/src/resources/extensions/gsd/guided-flow.ts +259 -10
  461. package/src/resources/extensions/gsd/health-widget.ts +3 -1
  462. package/src/resources/extensions/gsd/journal.ts +29 -3
  463. package/src/resources/extensions/gsd/key-manager.ts +22 -0
  464. package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
  465. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  466. package/src/resources/extensions/gsd/model-router.ts +42 -1
  467. package/src/resources/extensions/gsd/notifications.ts +27 -15
  468. package/src/resources/extensions/gsd/pre-execution-checks.ts +33 -7
  469. package/src/resources/extensions/gsd/preferences-types.ts +8 -0
  470. package/src/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  471. package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
  472. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  473. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  474. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  475. package/src/resources/extensions/gsd/reports.ts +5 -4
  476. package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
  477. package/src/resources/extensions/gsd/safety/file-change-validator.ts +16 -3
  478. package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
  479. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  480. package/src/resources/extensions/gsd/state.ts +35 -30
  481. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +238 -4
  482. package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
  483. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
  484. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +122 -0
  485. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
  486. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +63 -0
  487. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
  488. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
  489. package/src/resources/extensions/gsd/tests/cmux.test.ts +5 -9
  490. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +15 -0
  491. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
  492. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  493. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  494. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +161 -0
  495. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  496. package/src/resources/extensions/gsd/tests/derive-state.test.ts +1 -2
  497. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +14 -9
  498. package/src/resources/extensions/gsd/tests/dispatch-guard-summary-db-mismatch.test.ts +77 -0
  499. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  500. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  501. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +31 -0
  502. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
  503. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +1 -1
  504. package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
  505. package/src/resources/extensions/gsd/tests/exec-history.test.ts +113 -0
  506. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  507. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +38 -0
  508. package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
  509. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +131 -0
  510. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +296 -1
  511. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  512. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
  513. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +4 -2
  514. package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
  515. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
  516. package/src/resources/extensions/gsd/tests/integration/worktree-e2e.test.ts +11 -0
  517. package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
  518. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +66 -0
  519. package/src/resources/extensions/gsd/tests/key-manager.test.ts +2 -0
  520. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +76 -0
  521. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  522. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
  523. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  524. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +3 -3
  525. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  526. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +4 -2
  527. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +5 -0
  528. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
  529. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +150 -0
  530. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
  531. package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
  532. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +337 -0
  533. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
  534. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +39 -25
  535. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +181 -0
  536. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
  537. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
  538. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
  539. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
  540. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
  541. package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
  542. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
  543. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
  544. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
  545. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  546. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
  547. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +24 -0
  548. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  549. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
  550. package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
  551. package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
  552. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
  553. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
  554. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  555. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  556. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  557. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  558. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +42 -2
  559. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  560. package/src/resources/extensions/gsd/tests/validate-extension-package.test.ts +168 -0
  561. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +138 -5
  562. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +25 -2
  563. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
  564. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
  565. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
  566. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
  567. package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
  568. package/src/resources/extensions/gsd/token-counter.ts +22 -5
  569. package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
  570. package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
  571. package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
  572. package/src/resources/extensions/gsd/uok/audit.ts +20 -2
  573. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  574. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  575. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  576. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  577. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  578. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  579. package/src/resources/extensions/gsd/uok/plan-v2.ts +39 -8
  580. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  581. package/src/resources/extensions/gsd/workflow-logger.ts +23 -3
  582. package/src/resources/extensions/gsd/worktree-manager.ts +1 -0
  583. package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
  584. package/src/resources/extensions/mcp-client/auth.ts +12 -1
  585. package/src/resources/extensions/mcp-client/index.ts +129 -10
  586. package/src/resources/extensions/shared/cmux-events.ts +59 -0
  587. package/src/resources/extensions/shared/rtk-session-stats.ts +1 -2
  588. package/src/resources/skills/create-skill/SKILL.md +2 -2
  589. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  590. package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  591. package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  592. package/src/resources/skills/verify-before-complete/SKILL.md +2 -1
  593. package/src/resources/skills/write-docs/SKILL.md +2 -1
  594. package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
  595. package/dist/web/standalone/.next/static/chunks/2826.e59e8578e2e28639.js +0 -9
  596. /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_buildManifest.js +0 -0
  597. /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_ssgManifest.js +0 -0
@@ -18,10 +18,12 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
18
18
  import { logWarning, logError } from "./workflow-logger.js";
19
19
  import { join } from "node:path";
20
20
  import { hasImplementationArtifacts } from "./auto-recovery.js";
21
+ import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
21
22
  import { buildDiscussMilestonePrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildRefineSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, buildParallelResearchSlicesPrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
22
23
  import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
23
24
  import { resolveUokFlags } from "./uok/flags.js";
24
25
  import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
26
+ import { EXECUTION_ENTRY_PHASES, hasFinalizedMilestoneContext } from "./uok/plan-v2.js";
25
27
  function missingSliceStop(mid, phase) {
26
28
  return {
27
29
  action: "stop",
@@ -155,6 +157,35 @@ export const DISPATCH_RULES = [
155
157
  };
156
158
  },
157
159
  },
160
+ {
161
+ // #4671 — Recovery path for execution-entry phases with missing CONTEXT.md.
162
+ //
163
+ // Once `deriveStateFromDb` returns an execution-entry phase (executing /
164
+ // summarizing / validating-milestone / completing-milestone), the
165
+ // pre-planning guard at `pre-planning (no context) → discuss-milestone`
166
+ // no longer fires. The plan-v2 gate correctly detects the missing context
167
+ // but can only block — it cannot redispatch. Without this rule the
168
+ // milestone is stuck until `/gsd doctor heal` repairs it (and heal
169
+ // historically missed this check too).
170
+ //
171
+ // Fire BEFORE the execution-entry phase rules so we redispatch to
172
+ // `discuss-milestone` instead of hitting the plan-v2 gate.
173
+ name: "execution-entry phase (no context) → discuss-milestone",
174
+ match: async ({ state, mid, midTitle, basePath, structuredQuestionsAvailable }) => {
175
+ if (!EXECUTION_ENTRY_PHASES.has(state.phase))
176
+ return null;
177
+ // Align with the plan-v2 gate's lookup semantics: whitespace-only counts
178
+ // as missing, and an auto worktree may fall back to GSD_PROJECT_ROOT.
179
+ if (hasFinalizedMilestoneContext(basePath, mid))
180
+ return null;
181
+ return {
182
+ action: "dispatch",
183
+ unitType: "discuss-milestone",
184
+ unitId: mid,
185
+ prompt: await buildDiscussMilestonePrompt(mid, midTitle, basePath, structuredQuestionsAvailable),
186
+ };
187
+ },
188
+ },
158
189
  {
159
190
  name: "summarizing → complete-slice",
160
191
  match: async ({ state, mid, midTitle, basePath }) => {
@@ -319,6 +350,30 @@ export const DISPATCH_RULES = [
319
350
  };
320
351
  },
321
352
  },
353
+ {
354
+ name: "planning (require_slice_discussion) → pause for discussion (#3454)",
355
+ match: async ({ state, mid, basePath, prefs }) => {
356
+ if (state.phase !== "planning")
357
+ return null;
358
+ if (!prefs?.phases?.require_slice_discussion)
359
+ return null;
360
+ if (!state.activeSlice)
361
+ return null;
362
+ // Only pause if the slice has no context file yet (discussion not done).
363
+ // resolveSliceFile returns null when the file does not exist on disk,
364
+ // but cachedReaddir could return a stale hit — verify with existsSync
365
+ // so the guard is defence-in-depth and the contract is explicit at the
366
+ // call site.
367
+ const sliceContextFile = resolveSliceFile(basePath, mid, state.activeSlice.id, "CONTEXT");
368
+ if (sliceContextFile && existsSync(sliceContextFile))
369
+ return null; // discussion already done, proceed
370
+ return {
371
+ action: "stop",
372
+ reason: `Slice ${state.activeSlice.id} requires discussion before planning (require_slice_discussion is enabled). Run /gsd discuss to discuss this slice, then /gsd auto to resume.`,
373
+ level: "info",
374
+ };
375
+ },
376
+ },
322
377
  {
323
378
  // Keep this rule before the single-slice research rule so the multi-slice
324
379
  // path wins whenever 2+ slices are ready.
@@ -451,18 +506,31 @@ export const DISPATCH_RULES = [
451
506
  },
452
507
  {
453
508
  name: "planning → plan-slice",
454
- match: async ({ state, mid, midTitle, basePath, sessionContextWindow, modelRegistry }) => {
509
+ match: async ({ state, mid, midTitle, basePath, sessionContextWindow, modelRegistry, session }) => {
455
510
  if (state.phase !== "planning")
456
511
  return null;
457
512
  if (!state.activeSlice)
458
513
  return missingSliceStop(mid, state.phase);
459
514
  const sid = state.activeSlice.id;
460
515
  const sTitle = state.activeSlice.title;
516
+ // #4551: Consume any persisted pre-exec failure for this slice so the
517
+ // re-dispatched prompt includes the exact blocked references. Clear the
518
+ // field immediately after reading to prevent stale context leaking into
519
+ // a later, unrelated plan-slice run.
520
+ const unitId = `${mid}/${sid}`;
521
+ let priorPreExecFailure;
522
+ if (session?.lastPreExecFailure?.unitId === unitId) {
523
+ priorPreExecFailure = {
524
+ blockingFindings: session.lastPreExecFailure.blockingFindings,
525
+ verdictExcerpt: session.lastPreExecFailure.verdictExcerpt,
526
+ };
527
+ session.lastPreExecFailure = null;
528
+ }
461
529
  return {
462
530
  action: "dispatch",
463
531
  unitType: "plan-slice",
464
- unitId: `${mid}/${sid}`,
465
- prompt: await buildPlanSlicePrompt(mid, midTitle, sid, sTitle, basePath, undefined, { sessionContextWindow, modelRegistry }),
532
+ unitId,
533
+ prompt: await buildPlanSlicePrompt(mid, midTitle, sid, sTitle, basePath, undefined, { sessionContextWindow, modelRegistry, priorPreExecFailure }),
466
534
  };
467
535
  },
468
536
  },
@@ -689,22 +757,13 @@ export const DISPATCH_RULES = [
689
757
  return { action: "skip" };
690
758
  }
691
759
  }
692
- // Reconciliation guard (#4324): when the SUMMARY file already exists
693
- // on disk but the DB says the milestone is not complete, the DB is
694
- // out of sync (e.g. journal reset, partial merge, crash recovery).
695
- // Reconcile the DB status directly instead of re-dispatching the
696
- // tool, which would overwrite the richer on-disk SUMMARY with a
697
- // thinner regenerated version — causing silent data loss.
698
760
  const existingSummary = resolveMilestoneFile(basePath, mid, "SUMMARY");
699
- if (existingSummary && isDbAvailable()) {
700
- try {
701
- updateMilestoneStatus(mid, "complete", new Date().toISOString());
702
- logWarning("dispatch", `Milestone ${mid} has SUMMARY on disk but DB status was not complete — reconciled DB to complete (#4324)`);
703
- }
704
- catch (err) {
705
- logWarning("dispatch", `Failed to reconcile milestone ${mid} status: ${err instanceof Error ? err.message : String(err)}`);
761
+ let summaryOutcome = "unknown";
762
+ if (existingSummary) {
763
+ const summaryContent = await loadFile(existingSummary);
764
+ if (summaryContent) {
765
+ summaryOutcome = classifyMilestoneSummaryContent(summaryContent);
706
766
  }
707
- return { action: "skip" };
708
767
  }
709
768
  // Safety guard (#2675): block completion when VALIDATION verdict is
710
769
  // needs-remediation. The state machine treats needs-remediation as
@@ -782,6 +841,45 @@ export const DISPATCH_RULES = [
782
841
  catch (err) { /* fall through — don't block on DB errors */
783
842
  logWarning("dispatch", `verification class check failed: ${err instanceof Error ? err.message : String(err)}`);
784
843
  }
844
+ // Disk/DB mismatch handling (#4658): SUMMARY presence alone is not enough.
845
+ // Apply post-gate policy:
846
+ // - success summary: reconcile DB and skip re-dispatch
847
+ // - failure summary: pause/fail-closed
848
+ // - unknown summary: pause/fail-closed
849
+ if (existingSummary) {
850
+ const milestone = isDbAvailable() ? getMilestone(mid) : null;
851
+ const status = milestone?.status ?? (isDbAvailable() ? "missing" : "unavailable");
852
+ if (summaryOutcome === "success") {
853
+ if (!isDbAvailable()) {
854
+ logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB is unavailable — skipping duplicate complete-milestone dispatch`);
855
+ return { action: "skip" };
856
+ }
857
+ try {
858
+ updateMilestoneStatus(mid, "complete", new Date().toISOString());
859
+ logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB status was "${status}" — reconciled DB to complete (#4658)`);
860
+ return { action: "skip" };
861
+ }
862
+ catch (err) {
863
+ return {
864
+ action: "stop",
865
+ level: "warning",
866
+ reason: `Milestone ${mid} SUMMARY indicates completion but DB reconciliation failed (${err instanceof Error ? err.message : String(err)}). Auto-mode paused for manual review.`,
867
+ };
868
+ }
869
+ }
870
+ if (summaryOutcome === "failure") {
871
+ return {
872
+ action: "stop",
873
+ level: "warning",
874
+ reason: `Milestone ${mid} has a failure-path SUMMARY while DB status is "${status}". Auto-mode will not promote completion from failure artifacts. Re-run complete-milestone only after blockers are resolved and verification passes.`,
875
+ };
876
+ }
877
+ return {
878
+ action: "stop",
879
+ level: "warning",
880
+ reason: `Milestone ${mid} has an ambiguous SUMMARY while DB status is "${status}". Auto-mode paused instead of promoting completion from file presence alone.`,
881
+ };
882
+ }
785
883
  return {
786
884
  action: "dispatch",
787
885
  unitType: "complete-milestone",
@@ -8,6 +8,6 @@
8
8
  */
9
9
  export { autoLoop, runUokKernelLoop, runLegacyAutoLoop } from "./auto/loop.js";
10
10
  export { isInfrastructureError, INFRA_ERROR_CODES } from "./auto/infra-errors.js";
11
- export { resolveAgentEnd, resolveAgentEndCancelled, isSessionSwitchInFlight, _resetPendingResolve, _setActiveSession } from "./auto/resolve.js";
11
+ export { resolveAgentEnd, resolveAgentEndCancelled, isSessionSwitchInFlight, _hasPendingResolveForTest, _resetPendingResolve, _setActiveSession } from "./auto/resolve.js";
12
12
  export { detectStuck } from "./auto/detect-stuck.js";
13
13
  export { runUnit } from "./auto/run-unit.js";
@@ -291,7 +291,7 @@ autoModeStartThinkingLevel) {
291
291
  // ADR-005: Adjust active tool set for the selected model's provider capabilities.
292
292
  // Hard-filter incompatible tools, then let extensions override via adjust_tool_set hook.
293
293
  const activeToolNames = pi.getActiveTools();
294
- const { toolNames: compatibleTools, removedTools } = adjustToolSet(activeToolNames, model.api);
294
+ const { toolNames: compatibleTools, removedTools } = adjustToolSet(activeToolNames, model.api, model.provider);
295
295
  let finalToolNames = compatibleTools;
296
296
  // Fire adjust_tool_set hook — extensions can override the filtered tool set
297
297
  if (routingConfig.hooks !== false) {
@@ -30,7 +30,7 @@ import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookSta
30
30
  import { hasPendingCaptures, loadPendingCaptures, revertExecutorResolvedCaptures } from "./captures.js";
31
31
  import { debugLog } from "./debug-logger.js";
32
32
  import { runSafely } from "./auto-utils.js";
33
- import { getEvidence } from "./safety/evidence-collector.js";
33
+ import { getEvidence, clearEvidenceFromDisk } from "./safety/evidence-collector.js";
34
34
  import { validateFileChanges } from "./safety/file-change-validator.js";
35
35
  // crossReferenceEvidence available for future use when verification_evidence is stored in DB
36
36
  // import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js";
@@ -45,8 +45,24 @@ import { ensureCodebaseMapFresh } from "./codebase-generator.js";
45
45
  import { resolveUokFlags } from "./uok/flags.js";
46
46
  import { UokGateRunner } from "./uok/gate-runner.js";
47
47
  import { writeTurnGitTransaction } from "./uok/gitops.js";
48
+ import { isClosedStatus } from "./status-guards.js";
49
+ import { detectAbandonMilestone } from "./abandon-detect.js";
48
50
  /** Maximum verification retry attempts before escalating to blocker placeholder (#2653). */
49
51
  const MAX_VERIFICATION_RETRIES = 3;
52
+ const COMPLETE_MILESTONE_DB_SETTLE_MS = 1500;
53
+ const COMPLETE_MILESTONE_DB_SETTLE_POLL_MS = 100;
54
+ async function waitForMilestoneDbClose(mid) {
55
+ const deadline = Date.now() + COMPLETE_MILESTONE_DB_SETTLE_MS;
56
+ while (Date.now() < deadline) {
57
+ if (!isDbAvailable())
58
+ return false;
59
+ const milestone = getMilestone(mid);
60
+ if (milestone && isClosedStatus(milestone.status))
61
+ return true;
62
+ await new Promise((resolve) => setTimeout(resolve, COMPLETE_MILESTONE_DB_SETTLE_POLL_MS));
63
+ }
64
+ return false;
65
+ }
50
66
  /** Enqueue a sidecar item (hook, triage, or quick-task) for the main loop to
51
67
  * drain via runUnit. Logs the enqueue event and notifies the UI. */
52
68
  function enqueueSidecar(s, ctx, entry, debugExtra, notification) {
@@ -457,6 +473,36 @@ export async function postUnitPreVerification(pctx, opts) {
457
473
  // Rewrite-docs completion
458
474
  if (s.currentUnit.type === "rewrite-docs") {
459
475
  await runSafely("postUnit", "rewrite-docs-resolve", async () => {
476
+ // Detect abandon/descope overrides BEFORE resolving them (#3490).
477
+ // If an override is about abandoning the milestone, park it so the
478
+ // state engine skips it. Without this, rewrite-docs only edits
479
+ // markdown but the DB still has the milestone as active.
480
+ try {
481
+ const { loadActiveOverrides } = await import("./files.js");
482
+ const overrides = await loadActiveOverrides(s.basePath);
483
+ const decision = detectAbandonMilestone(overrides, s.currentMilestoneId);
484
+ if (decision.shouldPark && s.currentMilestoneId) {
485
+ const { parkMilestone } = await import("./milestone-actions.js");
486
+ const parked = parkMilestone(s.basePath, s.currentMilestoneId, decision.reason);
487
+ if (parked) {
488
+ ctx.ui.notify(`Milestone ${s.currentMilestoneId} parked: "${decision.reason}"`, "info");
489
+ }
490
+ else {
491
+ // Park refused: milestone directory missing, milestone already
492
+ // completed (SUMMARY present), or PARKED.md already exists.
493
+ // resolveAllOverrides below will still consume the override —
494
+ // surface this loudly so the user notices state drift rather
495
+ // than silently losing the abandon directive.
496
+ const msg = `Abandon detected for ${s.currentMilestoneId} but park refused (milestone is completed, already parked, or missing). Override will be resolved anyway — verify state is correct.`;
497
+ logError("engine", msg);
498
+ ctx.ui.notify(msg, "warning");
499
+ }
500
+ }
501
+ }
502
+ catch (err) {
503
+ logError("engine", `abandon-detect failed: ${err.message}`);
504
+ ctx.ui.notify(`Abandon detection failed — check logs. Overrides will still be resolved.`, "warning");
505
+ }
460
506
  await resolveAllOverrides(s.basePath);
461
507
  // Reset both disk and in-memory counters. Disk counter is authoritative
462
508
  // (survives restarts); in-memory is kept in sync for the current session.
@@ -535,7 +581,7 @@ export async function postUnitPreVerification(pctx, opts) {
535
581
  if (taskRow) {
536
582
  const expectedOutput = taskRow.expected_output ?? [];
537
583
  const plannedFiles = taskRow.files ?? [];
538
- const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles);
584
+ const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, safetyConfig.file_change_allowlist);
539
585
  if (audit && audit.violations.length > 0) {
540
586
  const warnings = audit.violations.filter(v => v.severity === "warning");
541
587
  for (const v of warnings) {
@@ -588,6 +634,16 @@ export async function postUnitPreVerification(pctx, opts) {
588
634
  debugLog("postUnit", { phase: "safety-content-validation", error: String(e) });
589
635
  }
590
636
  }
637
+ // Clear persisted evidence file now that post-unit processing is complete
638
+ // (Bug #4385 — prevents stale evidence from affecting retries of same unit ID).
639
+ if (safetyConfig.evidence_collection && s.currentUnit.type === "execute-task" && sMid && sSid && sTid) {
640
+ try {
641
+ clearEvidenceFromDisk(s.basePath, sMid, sSid, sTid);
642
+ }
643
+ catch (e) {
644
+ debugLog("postUnit", { phase: "safety-evidence-clear", error: String(e) });
645
+ }
646
+ }
591
647
  }
592
648
  }
593
649
  catch (e) {
@@ -607,6 +663,25 @@ export async function postUnitPreVerification(pctx, opts) {
607
663
  }
608
664
  // If verification failed, attempt to regenerate missing projection files
609
665
  // from DB data before giving up (e.g. research-slice produces PLAN from engine).
666
+ if (!triggerArtifactVerified) {
667
+ if (s.currentUnit.type === "complete-milestone") {
668
+ try {
669
+ const { milestone: mid } = parseUnitId(s.currentUnit.id);
670
+ if (mid) {
671
+ const settled = await waitForMilestoneDbClose(mid);
672
+ if (settled) {
673
+ triggerArtifactVerified = verifyExpectedArtifact(s.currentUnit.type, s.currentUnit.id, s.basePath);
674
+ if (triggerArtifactVerified) {
675
+ invalidateAllCaches();
676
+ }
677
+ }
678
+ }
679
+ }
680
+ catch (e) {
681
+ debugLog("postUnit", { phase: "artifact-verify-settle-db", error: String(e) });
682
+ }
683
+ }
684
+ }
610
685
  if (!triggerArtifactVerified) {
611
686
  try {
612
687
  const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
@@ -950,12 +1025,25 @@ export async function postUnitPostVerification(pctx) {
950
1025
  const suffix = blockingChecks.length > 3 ? `\n \u2022 ...and ${blockingChecks.length - 3} more` : "";
951
1026
  const evidenceNote = `\nSee ${sid}-PRE-EXEC-VERIFY.json for full details.`;
952
1027
  ctx.ui.notify(`Pre-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found\n${details}${suffix}${evidenceNote}`, "error");
1028
+ // Persist failure context so the next plan-slice re-dispatch can inject
1029
+ // it into the prompt and break the infinite loop (#4551).
1030
+ s.lastPreExecFailure = {
1031
+ unitId: currentUnit.id,
1032
+ blockingFindings: blockingChecks.map(c => `[${c.category}] ${c.target}: ${c.message}`),
1033
+ verdictExcerpt: `status=${result.status}; ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} detected`,
1034
+ };
953
1035
  preExecPauseNeeded = true;
954
1036
  }
955
1037
  else if (result.status === "warn") {
956
1038
  ctx.ui.notify(`Pre-execution checks passed with warnings`, "warning");
957
1039
  // Strict mode: treat warnings as blocking
958
1040
  if (prefs?.enhanced_verification_strict === true) {
1041
+ const warnChecks = result.checks.filter(c => !c.passed);
1042
+ s.lastPreExecFailure = {
1043
+ unitId: currentUnit.id,
1044
+ blockingFindings: warnChecks.map(c => `[${c.category}] ${c.target}: ${c.message}`),
1045
+ verdictExcerpt: `status=${result.status} (strict mode); ${warnChecks.length} warning${warnChecks.length === 1 ? "" : "s"} treated as blocking`,
1046
+ };
959
1047
  preExecPauseNeeded = true;
960
1048
  }
961
1049
  }
@@ -1223,6 +1223,20 @@ export async function buildPlanSlicePrompt(mid, _midTitle, sid, sTitle, base, le
1223
1223
  prependBlocks.push(`## Prior Sketch Scope (soft hint — non-binding)\n\n${options.softScopeHint.trim()}\n\n` +
1224
1224
  `This scope was captured during an earlier progressive-planning pass that was later disabled. Treat it as context only — you may plan beyond it if the work genuinely requires more scope. Do NOT treat this as a hard boundary.`);
1225
1225
  }
1226
+ // #4551: inject pre-exec failure context so the re-dispatched plan-slice
1227
+ // addresses the exact blocked references rather than reproducing the same plan.
1228
+ if (options?.priorPreExecFailure) {
1229
+ const { blockingFindings, verdictExcerpt } = options.priorPreExecFailure;
1230
+ const findingsList = blockingFindings.length > 0
1231
+ ? blockingFindings.map(f => `- ${f}`).join("\n")
1232
+ : "- (no specific findings recorded)";
1233
+ prependBlocks.push(`## Fix these specific issues from the prior pre-exec check\n\n` +
1234
+ `The previous plan-slice attempt was blocked by pre-execution validation.\n` +
1235
+ `Gate verdict: ${verdictExcerpt}\n\n` +
1236
+ `Blocked references that must be resolved in this plan:\n${findingsList}\n\n` +
1237
+ `Revise the plan so that every reference listed above is satisfied before execution begins. ` +
1238
+ `Do not reproduce the same file paths, package names, or task ordering that caused these failures.`);
1239
+ }
1226
1240
  return renderSlicePrompt({
1227
1241
  mid, sid, sTitle, base,
1228
1242
  level: level ?? resolveInlineLevel(),
@@ -11,18 +11,21 @@ import { appendEvent } from "./workflow-events.js";
11
11
  import { atomicWriteSync } from "./atomic-write.js";
12
12
  import { clearParseCache } from "./files.js";
13
13
  import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
14
- import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGates, updateTaskStatus, updateSliceStatus } from "./gsd-db.js";
14
+ import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGates, updateTaskStatus, updateSliceStatus, insertSlice, getMilestone } from "./gsd-db.js";
15
15
  import { isValidationTerminal } from "./state.js";
16
16
  import { getErrorMessage } from "./error-utils.js";
17
17
  import { logWarning, logError } from "./workflow-logger.js";
18
+ import { isClosedStatus } from "./status-guards.js";
18
19
  import { nativeConflictFiles, nativeCommit, nativeCheckoutTheirs, nativeAddPaths, nativeMergeAbort, nativeResetHard, } from "./native-git-bridge.js";
19
20
  import { resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, relMilestoneFile, relSliceFile, buildSliceFileName, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
20
21
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, } from "node:fs";
21
22
  import { execFileSync } from "node:child_process";
22
23
  import { dirname, join } from "node:path";
23
24
  import { resolveExpectedArtifactPath, diagnoseExpectedArtifact, } from "./auto-artifact-paths.js";
25
+ import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
24
26
  // Re-export so existing consumers of auto-recovery.ts keep working.
25
27
  export { resolveExpectedArtifactPath, diagnoseExpectedArtifact };
28
+ export { classifyMilestoneSummaryContent, } from "./milestone-summary-classifier.js";
26
29
  // ─── Artifact Resolution & Verification ───────────────────────────────────────
27
30
  /**
28
31
  * Check whether a milestone produced implementation artifacts (non-`.gsd/` files)
@@ -220,12 +223,25 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
220
223
  // RESEARCH file. Without this, resolveExpectedArtifactPath returns null and
221
224
  // the retry/escalation machinery silently re-dispatches forever.
222
225
  //
226
+ // #4068: Also treat a PARALLEL-BLOCKER placeholder as a terminal completion
227
+ // so that timeout-recovery can write the blocker, have verifyExpectedArtifact
228
+ // return true, and let the dispatch loop advance past this unit. Without
229
+ // this, the blocker is written but verification still returns false, the unit
230
+ // is never cleared from unitDispatchCount, and on the next iteration the
231
+ // dispatch rule (which correctly skips parallel-research when PARALLEL-BLOCKER
232
+ // exists) returns null — leaving the loop stuck re-deriving indefinitely.
233
+ //
223
234
  // NOTE: this predicate mirrors the dispatch rule at
224
235
  // auto-dispatch.ts parallel-research-slices — keep the two in sync.
225
236
  if (unitType === "research-slice" && unitId.endsWith("/parallel-research")) {
226
237
  const { milestone: mid } = parseUnitId(unitId);
227
238
  if (!mid)
228
239
  return false;
240
+ // #4068: PARALLEL-BLOCKER written by timeout-recovery is a terminal state.
241
+ const blockerPath = resolveExpectedArtifactPath(unitType, unitId, base);
242
+ if (blockerPath && existsSync(blockerPath)) {
243
+ return true;
244
+ }
229
245
  const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
230
246
  if (!roadmapFile || !existsSync(roadmapFile)) {
231
247
  logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap missing`);
@@ -420,6 +436,17 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
420
436
  // A milestone with only .gsd/ plan files and zero implementation code is
421
437
  // not genuinely complete — the LLM wrote plan files but skipped actual work.
422
438
  if (unitType === "complete-milestone") {
439
+ const summaryOutcome = classifyMilestoneSummaryContent(readFileSync(absPath, "utf-8"));
440
+ if (summaryOutcome === "failure")
441
+ return false;
442
+ const { milestone: mid } = parseUnitId(unitId);
443
+ if (mid && isDbAvailable()) {
444
+ const dbMilestone = getMilestone(mid);
445
+ if (!dbMilestone)
446
+ return false;
447
+ if (!isClosedStatus(dbMilestone.status) && summaryOutcome !== "success")
448
+ return false;
449
+ }
423
450
  if (hasImplementationArtifacts(base) === "absent")
424
451
  return false;
425
452
  }
@@ -497,6 +524,24 @@ export function writeBlockerPlaceholder(unitType, unitId, base, reason) {
497
524
  logWarning("recovery", `appendEvent failed for slice recovery: ${e instanceof Error ? e.message : String(e)}`);
498
525
  }
499
526
  }
527
+ // Insert a placeholder complete slice so deriveState sees activeMilestoneSlices.length > 0
528
+ // and exits the pre-planning phase. Without this, activeMilestoneSlices stays empty
529
+ // after the blocker ROADMAP.md is written, causing deriveState to return phase:'pre-planning'
530
+ // indefinitely and re-dispatching plan-milestone in an infinite loop (#4378).
531
+ if (unitType === "plan-milestone" && mid) {
532
+ try {
533
+ insertSlice({ id: "S00-blocker", milestoneId: mid, title: "Blocker placeholder — planning failed", status: "complete", sequence: 0 });
534
+ }
535
+ catch (e) {
536
+ logWarning("recovery", `insertSlice placeholder failed for plan-milestone recovery: ${e instanceof Error ? e.message : String(e)}`);
537
+ }
538
+ try {
539
+ appendEvent(base, { cmd: "plan-milestone", params: { milestoneId: mid }, ts, actor: "system", trigger_reason: "blocker-placeholder-recovery" });
540
+ }
541
+ catch (e) {
542
+ logWarning("recovery", `appendEvent failed for plan-milestone recovery: ${e instanceof Error ? e.message : String(e)}`);
543
+ }
544
+ }
500
545
  }
501
546
  return diagnoseExpectedArtifact(unitType, unitId, base);
502
547
  }
@@ -31,10 +31,11 @@ import { restoreHookState, resetHookState } from "./post-unit-hooks.js";
31
31
  import { resetProactiveHealing, setLevelChangeCallback } from "./doctor-proactive.js";
32
32
  import { snapshotSkills } from "./skill-discovery.js";
33
33
  import { isDbAvailable, getMilestone, openDatabase, getDbStatus } from "./gsd-db.js";
34
- import { hideFooter } from "./auto-dashboard.js";
34
+ import { isClosedStatus } from "./status-guards.js";
35
+ import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
35
36
  import { debugLog, enableDebug, isDebugEnabled, getDebugLogPath, } from "./debug-logger.js";
36
37
  import { logWarning, logError } from "./workflow-logger.js";
37
- import { existsSync, mkdirSync, readdirSync, rmSync, statSync, unlinkSync, } from "node:fs";
38
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, unlinkSync, } from "node:fs";
38
39
  import { join } from "node:path";
39
40
  import { sep as pathSep } from "node:path";
40
41
  import { resolveProjectRootDbPath } from "./bootstrap/dynamic-tools.js";
@@ -312,11 +313,32 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
312
313
  }
313
314
  // Invalidate caches before initial state derivation
314
315
  invalidateAllCaches();
315
- // Clean stale runtime unit files for completed milestones (#887)
316
- cleanStaleRuntimeUnits(gsdRoot(base), (mid) => !!resolveMilestoneFile(base, mid, "SUMMARY"));
317
316
  // Open the project-root DB before deriveState so DB-backed state
318
317
  // derivation (queue-order, task status) works on a cold start (#2841).
318
+ // Must happen before cleanStaleRuntimeUnits so the cleanup predicate can
319
+ // consult DB status and avoid clearing runtime units for milestones that
320
+ // only have a failure-path SUMMARY on disk (#4663).
319
321
  await openProjectDbIfPresent(base);
322
+ // Clean stale runtime unit files for completed milestones (#887).
323
+ // DB-authoritative: when DB is available, require DB status to be closed
324
+ // before clearing runtime units. A SUMMARY file alone is no longer
325
+ // trusted as proof of completion (#4663). Fall back to SUMMARY-file
326
+ // presence only when DB is unavailable (legacy/pre-migration).
327
+ cleanStaleRuntimeUnits(gsdRoot(base), (mid) => {
328
+ if (isDbAvailable()) {
329
+ const row = getMilestone(mid);
330
+ return !!row && isClosedStatus(row.status);
331
+ }
332
+ const summaryFile = resolveMilestoneFile(base, mid, "SUMMARY");
333
+ if (!summaryFile)
334
+ return false;
335
+ try {
336
+ return classifyMilestoneSummaryContent(readFileSync(summaryFile, "utf-8")) !== "failure";
337
+ }
338
+ catch {
339
+ return false;
340
+ }
341
+ });
320
342
  // ── Orphaned milestone branch audit ──
321
343
  // Catches completed milestones whose teardown (merge + branch delete)
322
344
  // was lost due to session ending between completion and teardown.
@@ -416,29 +438,15 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
416
438
  }
417
439
  const { showSmartEntry } = await import("./guided-flow.js");
418
440
  await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
419
- invalidateAllCaches();
420
- const postState = await deriveState(base);
421
- if (postState.activeMilestone &&
422
- postState.phase !== "complete" &&
423
- postState.phase !== "pre-planning") {
424
- s.consecutiveCompleteBootstraps = 0; // Successfully advanced past "complete"
425
- state = postState;
426
- }
427
- else if (postState.activeMilestone &&
428
- postState.phase === "pre-planning") {
429
- const contextFile = resolveMilestoneFile(base, postState.activeMilestone.id, "CONTEXT");
430
- const hasContext = !!(contextFile && (await loadFile(contextFile)));
431
- if (hasContext) {
432
- state = postState;
433
- }
434
- else {
435
- ctx.ui.notify("Discussion completed but no milestone context was written. Run /gsd to try the discussion again, or /gsd auto after creating the milestone manually.", "warning");
436
- return releaseLockAndReturn();
437
- }
438
- }
439
- else {
440
- return releaseLockAndReturn();
441
- }
441
+ // showSmartEntry dispatches via pi.sendMessage() which is fire-and-forget:
442
+ // it queues the message and returns immediately, before the LLM turn runs.
443
+ // Checking postState here would always see the pre-dispatch state, causing
444
+ // the premature "Discussion completed but..." warning (#3420).
445
+ //
446
+ // checkAutoStartAfterDiscuss (in guided-flow.ts) already handles re-entering
447
+ // auto-mode by calling startAutoDetached after the discussion completes.
448
+ // Release the lock and let the async dispatch proceed.
449
+ return releaseLockAndReturn();
442
450
  }
443
451
  // Active milestone exists but has no roadmap
444
452
  if (state.phase === "pre-planning") {
@@ -448,15 +456,16 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
448
456
  if (!hasContext) {
449
457
  const { showSmartEntry } = await import("./guided-flow.js");
450
458
  await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
451
- invalidateAllCaches();
452
- const postState = await deriveState(base);
453
- if (postState.activeMilestone && postState.phase !== "pre-planning") {
454
- state = postState;
455
- }
456
- else {
457
- ctx.ui.notify("Discussion completed but milestone context is still missing. Run /gsd to try again.", "warning");
458
- return releaseLockAndReturn();
459
- }
459
+ // showSmartEntry dispatches via pi.sendMessage() which is fire-and-forget:
460
+ // it queues the message and returns immediately, before the LLM turn runs.
461
+ // Checking postState here fires before the LLM has had a turn, so the
462
+ // pre-planning phase would still appear unchanged and a premature warning
463
+ // would be emitted (#3420).
464
+ //
465
+ // checkAutoStartAfterDiscuss (in guided-flow.ts) already handles re-entering
466
+ // auto-mode by calling startAutoDetached after the discussion completes.
467
+ // Release the lock and let the async dispatch proceed.
468
+ return releaseLockAndReturn();
460
469
  }
461
470
  }
462
471
  // Active milestone has CONTEXT-DRAFT but no full context — needs discussion
@@ -650,9 +659,6 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
650
659
  snapshotSkills();
651
660
  }
652
661
  ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
653
- ctx.ui.setFooter(hideFooter);
654
- // Hide gsd-health during AUTO — gsd-progress is the single source of truth
655
- // for last-commit / cost / health signal while auto is running.
656
662
  ctx.ui.setWidget("gsd-health", undefined);
657
663
  const modeLabel = s.stepMode ? "Step-mode" : "Auto-mode";
658
664
  const pendingCount = (state.registry ?? []).filter((m) => m.status !== "complete" && m.status !== "parked").length;