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
@@ -6,8 +6,14 @@
6
6
  import { readUnitRuntimeRecord, writeUnitRuntimeRecord, formatExecuteTaskRecoveryStatus, inspectExecuteTaskDurability, } from "./unit-runtime.js";
7
7
  import { resolveExpectedArtifactPath, diagnoseExpectedArtifact, writeBlockerPlaceholder, } from "./auto-recovery.js";
8
8
  import { existsSync } from "node:fs";
9
- import { resolveAgentEnd } from "./auto-loop.js";
9
+ import { bumpAndResolveSynthetic } from "./auto/resolve.js";
10
10
  export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rctx) {
11
+ // Note on turn epoch: the bump is intentionally NOT unconditional at
12
+ // function entry. Two branches below (the "steering retry" paths) keep
13
+ // the same LLM turn alive and let it try again — they must NOT bump,
14
+ // otherwise the retry's legitimate writes get marked stale and drop.
15
+ // Each advance branch calls `bumpAndResolveSynthetic` to bump+resolve
16
+ // atomically. Search for that helper to find all supersede sites.
11
17
  const { basePath, verbose, currentUnitStartedAt, unitRecoveryCount } = rctx;
12
18
  const runtime = readUnitRuntimeRecord(basePath, unitType, unitId);
13
19
  const recoveryAttempts = runtime?.recoveryAttempts ?? 0;
@@ -36,7 +42,7 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
36
42
  });
37
43
  ctx.ui.notify(`${reason === "idle" ? "Idle" : "Timeout"} recovery: ${unitType} ${unitId} already completed on disk. Continuing auto-mode. (attempt ${attemptNumber})`, "info");
38
44
  unitRecoveryCount.delete(recoveryKey);
39
- resolveAgentEnd({ messages: [], _synthetic: "timeout-recovery" });
45
+ bumpAndResolveSynthetic(`timeout-recovery:${reason}:${unitType}/${unitId}`);
40
46
  return "recovered";
41
47
  }
42
48
  if (recoveryAttempts < maxRecoveryAttempts) {
@@ -90,7 +96,7 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
90
96
  });
91
97
  ctx.ui.notify(`${unitType} ${unitId} skipped after ${maxRecoveryAttempts} recovery attempts (${diagnostic}). Blocker artifacts written. Advancing pipeline. (attempt ${attemptNumber})`, "warning");
92
98
  unitRecoveryCount.delete(recoveryKey);
93
- resolveAgentEnd({ messages: [], _synthetic: "timeout-recovery" });
99
+ bumpAndResolveSynthetic(`timeout-recovery:${reason}:${unitType}/${unitId}`);
94
100
  return "recovered";
95
101
  }
96
102
  // Fallback: couldn't write skip artifacts — pause as before.
@@ -115,7 +121,7 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
115
121
  });
116
122
  ctx.ui.notify(`${reason === "idle" ? "Idle" : "Timeout"} recovery: ${unitType} ${unitId} artifact already exists on disk. Advancing. (attempt ${attemptNumber})`, "info");
117
123
  unitRecoveryCount.delete(recoveryKey);
118
- resolveAgentEnd({ messages: [], _synthetic: "timeout-recovery" });
124
+ bumpAndResolveSynthetic(`timeout-recovery:${reason}:${unitType}/${unitId}`);
119
125
  return "recovered";
120
126
  }
121
127
  if (recoveryAttempts < maxRecoveryAttempts) {
@@ -180,7 +186,7 @@ export async function recoverTimedOutUnit(ctx, pi, unitType, unitId, reason, rct
180
186
  });
181
187
  ctx.ui.notify(`${unitType} ${unitId} skipped after ${maxRecoveryAttempts} recovery attempts. Blocker placeholder written to ${placeholder}. Advancing pipeline. (attempt ${attemptNumber})`, "warning");
182
188
  unitRecoveryCount.delete(recoveryKey);
183
- resolveAgentEnd({ messages: [], _synthetic: "timeout-recovery" });
189
+ bumpAndResolveSynthetic(`timeout-recovery:${reason}:${unitType}/${unitId}`);
184
190
  return "recovered";
185
191
  }
186
192
  // Fallback: couldn't resolve artifact path — pause as before.
@@ -20,9 +20,18 @@ export async function closeoutUnit(ctx, basePath, unitType, unitId, startedAt, o
20
20
  const { buildMemoryLLMCall, extractMemoriesFromUnit } = await import('./memory-extractor.js');
21
21
  const llmCallFn = buildMemoryLLMCall(ctx);
22
22
  if (llmCallFn) {
23
- extractMemoriesFromUnit(activityFile, unitType, unitId, llmCallFn).catch((err) => {
23
+ // Awaited: a fire-and-forget here lets memory-extractor writes land in
24
+ // .gsd/ after closeoutUnit returns but before the milestone merge
25
+ // runs, which made the working tree appear dirty to `git merge
26
+ // --squash` (root cause class of #4704). Completion latency is now
27
+ // bounded by the extractor's LLM call, which is the acceptable price
28
+ // for not racing the merge boundary.
29
+ try {
30
+ await extractMemoriesFromUnit(activityFile, unitType, unitId, llmCallFn);
31
+ }
32
+ catch (err) {
24
33
  logWarning("engine", `memory extraction failed for ${unitType}/${unitId}: ${err.message}`);
25
- });
34
+ }
26
35
  }
27
36
  }
28
37
  catch (err) { /* non-fatal */
@@ -9,7 +9,7 @@ import { existsSync, cpSync, readFileSync, readdirSync, mkdirSync, realpathSync,
9
9
  import { isAbsolute, join, sep as pathSep } from "node:path";
10
10
  import { homedir } from "node:os";
11
11
  import { GSDError, GSD_IO_ERROR, GSD_GIT_ERROR } from "./errors.js";
12
- import { reconcileWorktreeDb, isDbAvailable, getMilestone, getMilestoneSlices, } from "./gsd-db.js";
12
+ import { reconcileWorktreeDb, isDbAvailable, getMilestone, getMilestoneSlices, closeDatabase, openDatabase, getDbPath, } from "./gsd-db.js";
13
13
  import { atomicWriteSync } from "./atomic-write.js";
14
14
  import { execFileSync } from "node:child_process";
15
15
  import { safeCopy, safeCopyRecursive } from "./safe-fs.js";
@@ -180,14 +180,6 @@ function clearProjectRootStateFiles(basePath, milestoneId) {
180
180
  }
181
181
  }
182
182
  }
183
- function isProjectGsdSymlink(basePath) {
184
- try {
185
- return lstatSyncFn(join(basePath, ".gsd")).isSymbolicLink();
186
- }
187
- catch {
188
- return false;
189
- }
190
- }
191
183
  // ─── Build Artifact Auto-Resolve ─────────────────────────────────────────────
192
184
  /** Patterns for machine-generated build artifacts that can be safely
193
185
  * auto-resolved by accepting --theirs during merge. These files are
@@ -1429,73 +1421,65 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1429
1421
  });
1430
1422
  }
1431
1423
  }
1432
- // 7. Stash any pre-existing dirty files so the squash merge is not
1433
- // blocked by unrelated local changes (#2151). clearProjectRootStateFiles
1434
- // only removes untracked .gsd/ files; tracked dirty files elsewhere (e.g.
1435
- // .planning/work-state.json with stash conflict markers) are invisible to
1436
- // that cleanup but will cause `git merge --squash` to reject.
1437
- let stashed = false;
1438
- try {
1439
- const status = execFileSync("git", ["status", "--porcelain"], {
1440
- cwd: originalBasePath_,
1441
- stdio: ["ignore", "pipe", "pipe"],
1442
- encoding: "utf-8",
1443
- }).trim();
1444
- if (status) {
1445
- // Use --include-untracked to stash untracked files that would block
1446
- // the squash merge, but EXCLUDE .gsd/milestones/ (#2505).
1447
- // --include-untracked without exclusion sweeps queued milestone
1448
- // CONTEXT files into the stash. If stash pop later fails, those files
1449
- // are permanently trapped in the stash entry and lost on the next
1450
- // stash push or drop.
1451
- //
1452
- // When `.gsd` itself is a symlink, Git rejects pathspecs below it
1453
- // ("beyond a symbolic link"). In that layout, exclude the whole symlink
1454
- // and keep stashing real project files that could block the merge.
1455
- const stashPathspecs = isProjectGsdSymlink(originalBasePath_)
1456
- ? [".", ":(exclude).gsd"]
1457
- : [":(exclude).gsd/milestones"];
1458
- execFileSync("git", [
1459
- "stash", "push", "--include-untracked",
1460
- "-m", `gsd: pre-merge stash for ${milestoneId}`,
1461
- "--", ...stashPathspecs,
1462
- ], { cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
1463
- stashed = true;
1464
- }
1465
- }
1466
- catch (err) {
1467
- // Stash failure is non-fatal — proceed without stash and let the merge
1468
- // report the dirty tree if it fails.
1469
- logWarning("worktree", `git stash failed: ${err instanceof Error ? err.message : String(err)}`);
1470
- }
1471
- // 7a. Shelter queued milestone directories before the squash merge (#2505).
1424
+ // 7. Shelter queued milestone directories before the squash merge (#2505).
1472
1425
  // The milestone branch may contain copies of queued milestone dirs (via
1473
1426
  // copyPlanningArtifacts), so `git merge --squash` rejects when those same
1474
1427
  // files exist as untracked in the working tree. Temporarily move them to
1475
1428
  // a backup location, then restore after the merge+commit.
1429
+ //
1430
+ // MUST run BEFORE the pre-merge stash (step 7a) so `--include-untracked`
1431
+ // does not sweep queued CONTEXT files into the stash. If stash pop later
1432
+ // fails, files trapped inside the stash are permanently lost (#2505).
1476
1433
  const milestonesDir = join(gsdRoot(originalBasePath_), "milestones");
1477
1434
  const shelterDir = join(gsdRoot(originalBasePath_), ".milestone-shelter");
1478
1435
  const shelteredDirs = [];
1436
+ let shelterRestored = false;
1479
1437
  // Helper: restore sheltered milestone directories (#2505).
1480
1438
  // Called on both success and error paths to ensure queued CONTEXT files
1481
- // are never permanently lost.
1439
+ // are never permanently lost. Idempotent — the error path may fire after
1440
+ // the success path has already restored and removed the shelter dir; a
1441
+ // second call is a no-op instead of logging a misleading "shelter restore
1442
+ // failed: ENOENT" error for shelter sources that were cleaned up legitimately.
1482
1443
  const restoreShelter = () => {
1444
+ if (shelterRestored)
1445
+ return;
1446
+ shelterRestored = true;
1483
1447
  if (shelteredDirs.length === 0)
1484
1448
  return;
1449
+ let restoreFailed = false;
1485
1450
  for (const dirName of shelteredDirs) {
1451
+ const src = join(shelterDir, dirName);
1452
+ // If the shelter source is missing the restore cannot proceed for this
1453
+ // entry. Distinguish "legitimately missing" (shelter dir removed by a
1454
+ // prior successful restore or never copied) from a surprising ENOENT
1455
+ // inside an otherwise-populated shelter.
1456
+ if (!existsSync(src)) {
1457
+ logWarning("worktree", `shelter source missing for ${dirName}; skipping restore (shelter already cleaned or entry never staged)`);
1458
+ continue;
1459
+ }
1486
1460
  try {
1487
1461
  mkdirSync(milestonesDir, { recursive: true });
1488
- cpSync(join(shelterDir, dirName), join(milestonesDir, dirName), { recursive: true, force: true });
1462
+ cpSync(src, join(milestonesDir, dirName), { recursive: true, force: true });
1489
1463
  }
1490
1464
  catch (err) { /* best-effort */
1491
- logError("worktree", `shelter restore failed: ${err instanceof Error ? err.message : String(err)}`);
1465
+ restoreFailed = true;
1466
+ logError("worktree", `shelter restore failed (${dirName}): ${err instanceof Error ? err.message : String(err)}`);
1492
1467
  }
1493
1468
  }
1494
- try {
1495
- rmSync(shelterDir, { recursive: true, force: true });
1469
+ // Preserve the shelter if any per-entry restore failed — it is the only
1470
+ // surviving copy of the queued milestone dirs (sources were deleted during
1471
+ // shelter). Deleting it here would permanently lose those files (#2505).
1472
+ if (restoreFailed) {
1473
+ logWarning("worktree", `shelter retained at ${shelterDir} — manual recovery required for unrestored entries`);
1474
+ return;
1496
1475
  }
1497
- catch (err) { /* best-effort */
1498
- logWarning("worktree", `shelter cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
1476
+ if (existsSync(shelterDir)) {
1477
+ try {
1478
+ rmSync(shelterDir, { recursive: true, force: true });
1479
+ }
1480
+ catch (err) { /* best-effort */
1481
+ logWarning("worktree", `shelter cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
1482
+ }
1499
1483
  }
1500
1484
  };
1501
1485
  try {
@@ -1526,6 +1510,54 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1526
1510
  // Non-fatal — proceed with merge; untracked files may block it
1527
1511
  logWarning("worktree", `milestone shelter operation failed: ${err instanceof Error ? err.message : String(err)}`);
1528
1512
  }
1513
+ // 7a. Stash pre-existing dirty files so the squash merge is not blocked by
1514
+ // unrelated local changes (#2151). Includes untracked files to handle
1515
+ // locally-added files that conflict with tracked files on the milestone
1516
+ // branch. Passing NO pathspec lets git skip gitignored paths silently;
1517
+ // adding an explicit pathspec trips a `git add`-style fatal on ignored
1518
+ // entries (e.g. a gitignored `.gsd` symlink under ADR-002) (#4573).
1519
+ // Queued CONTEXT files under `.gsd/milestones/*` are already sheltered
1520
+ // in step 7 above, so they won't be swept into the stash.
1521
+ // On Windows, SQLite holds mandatory file locks on the gsd.db WAL/SHM
1522
+ // sidecars while the connection is open. `git stash --include-untracked`
1523
+ // walks those files and fails with EBUSY (#4704). Close the DB before
1524
+ // stashing so Windows releases the handles; reopen after. No-op on
1525
+ // POSIX, where advisory locks don't block git.
1526
+ const needsDbCycle = process.platform === "win32" && isDbAvailable();
1527
+ const dbPathToReopen = needsDbCycle ? getDbPath() : null;
1528
+ if (needsDbCycle) {
1529
+ try {
1530
+ closeDatabase();
1531
+ }
1532
+ catch (err) {
1533
+ logWarning("worktree", `pre-stash db close failed: ${err instanceof Error ? err.message : String(err)}`);
1534
+ }
1535
+ }
1536
+ let stashed = false;
1537
+ try {
1538
+ const status = execFileSync("git", ["status", "--porcelain"], {
1539
+ cwd: originalBasePath_,
1540
+ stdio: ["ignore", "pipe", "pipe"],
1541
+ encoding: "utf-8",
1542
+ }).trim();
1543
+ if (status) {
1544
+ execFileSync("git", ["stash", "push", "--include-untracked", "-m", `gsd: pre-merge stash for ${milestoneId}`], { cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
1545
+ stashed = true;
1546
+ }
1547
+ }
1548
+ catch (err) {
1549
+ // Stash failure is non-fatal — proceed without stash and let the merge
1550
+ // report the dirty tree if it fails.
1551
+ logWarning("worktree", `git stash failed: ${err instanceof Error ? err.message : String(err)}`);
1552
+ }
1553
+ if (needsDbCycle && dbPathToReopen) {
1554
+ try {
1555
+ openDatabase(dbPathToReopen);
1556
+ }
1557
+ catch (err) {
1558
+ logWarning("worktree", `post-stash db reopen failed: ${err instanceof Error ? err.message : String(err)}`);
1559
+ }
1560
+ }
1529
1561
  // 7b. Clean up stale merge state before attempting squash merge (#2912).
1530
1562
  // A leftover MERGE_HEAD (from a previous failed merge, libgit2 native path,
1531
1563
  // or interrupted operation) causes `git merge --squash` to refuse with
@@ -1761,16 +1793,32 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1761
1793
  // When a milestone only produced .gsd/ metadata (summaries, roadmaps) but no
1762
1794
  // real code, the user sees "milestone complete" but nothing changed in their
1763
1795
  // codebase. Surface this so the caller can warn the user.
1796
+ //
1797
+ // Bug #4385 fix: use `git diff-tree --root` instead of `git diff HEAD~1 HEAD`.
1798
+ // `HEAD~1` does not exist on initial commits and is unreliable on shallow clones
1799
+ // and merge commits. `diff-tree --root` handles all three cases correctly.
1800
+ // The empty-tree hash (4b825dc…) is the universal fallback for refs that don't exist.
1801
+ const GIT_EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
1764
1802
  let codeFilesChanged = false;
1765
1803
  if (!nothingToCommit) {
1766
1804
  try {
1767
- const mergedFiles = nativeDiffNumstat(originalBasePath_, "HEAD~1", "HEAD");
1768
- codeFilesChanged = mergedFiles.some((entry) => !entry.path.startsWith(".gsd/"));
1805
+ const diffTreeOutput = execFileSync("git", ["diff-tree", "--root", "--no-commit-id", "-r", "--name-only", "HEAD"], { cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
1806
+ const mergedFiles = diffTreeOutput ? diffTreeOutput.split("\n").filter(Boolean) : [];
1807
+ codeFilesChanged = mergedFiles.some((f) => !f.startsWith(".gsd/"));
1769
1808
  }
1770
1809
  catch (e) {
1771
- // If HEAD~1 doesn't exist (first commit), assume code was changed
1772
- logWarning("worktree", `diff numstat failed (assuming code changed): ${e.message}`);
1773
- codeFilesChanged = true;
1810
+ // diff-tree failed (e.g. unborn HEAD in a brand-new repo) fall back to
1811
+ // comparing against the empty tree so initial-commit repos still report changes.
1812
+ try {
1813
+ const fallbackOutput = execFileSync("git", ["diff", "--name-only", GIT_EMPTY_TREE, "HEAD"], { cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
1814
+ const fallbackFiles = fallbackOutput ? fallbackOutput.split("\n").filter(Boolean) : [];
1815
+ codeFilesChanged = fallbackFiles.some((f) => !f.startsWith(".gsd/"));
1816
+ }
1817
+ catch {
1818
+ // Truly unable to determine — assume code was changed to avoid silent data loss
1819
+ logWarning("worktree", `diff-tree and empty-tree fallback both failed (assuming code changed): ${e.message}`);
1820
+ codeFilesChanged = true;
1821
+ }
1774
1822
  }
1775
1823
  }
1776
1824
  // 10. Auto-push if enabled
@@ -37,8 +37,9 @@ import { getRtkSessionSavings } from "../shared/rtk-session-stats.js";
37
37
  import { deactivateGSD } from "../shared/gsd-phase-state.js";
38
38
  import { initMetrics, resetMetrics, getLedger, getProjectTotals, formatCost, formatTokenCount, } from "./metrics.js";
39
39
  import { setLogBasePath, logWarning } from "./workflow-logger.js";
40
+ import { preflightCleanRoot, postflightPopStash } from "./clean-root-preflight.js";
40
41
  import { homedir } from "node:os";
41
- import { join } from "node:path";
42
+ import { isAbsolute, join } from "node:path";
42
43
  import { pathToFileURL } from "node:url";
43
44
  import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs";
44
45
  import { atomicWriteSync } from "./atomic-write.js";
@@ -50,16 +51,24 @@ import { pruneQueueOrder } from "./queue-order.js";
50
51
  import { startCommandPolling as _startCommandPolling, isRemoteConfigured } from "../remote-questions/manager.js";
51
52
  import { debugLog, isDebugEnabled, writeDebugSummary } from "./debug-logger.js";
52
53
  import { reconcileMergeState, } from "./auto-recovery.js";
54
+ import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
53
55
  import { resolveDispatch, DISPATCH_RULES } from "./auto-dispatch.js";
54
56
  import { getErrorMessage } from "./error-utils.js";
55
57
  import { recoverFailedMigration } from "./migrate-external.js";
56
58
  import { initRegistry, convertDispatchRules } from "./rule-registry.js";
57
59
  import { emitJournalEvent as _emitJournalEvent } from "./journal.js";
58
- import { updateProgressWidget as _updateProgressWidget, updateSliceProgressCache, clearSliceProgressCache, hideFooter, } from "./auto-dashboard.js";
60
+ import { updateProgressWidget as _updateProgressWidget, updateSliceProgressCache, clearSliceProgressCache, } from "./auto-dashboard.js";
59
61
  import { registerSigtermHandler as _registerSigtermHandler, deregisterSigtermHandler as _deregisterSigtermHandler, } from "./auto-supervisor.js";
60
62
  import { isDbAvailable, getMilestone } from "./gsd-db.js";
61
63
  import { countPendingCaptures } from "./captures.js";
62
- import { clearCmuxSidebar, logCmuxEvent, syncCmuxSidebar } from "../cmux/index.js";
64
+ import { CMUX_CHANNELS } from "../shared/cmux-events.js";
65
+ function makeCmuxEmitters(pi) {
66
+ return {
67
+ syncCmuxSidebar: (preferences, state) => pi.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "sync", preferences, state }),
68
+ logCmuxEvent: (preferences, message, level) => pi.events.emit(CMUX_CHANNELS.LOG, { preferences, message, level: level ?? "info" }),
69
+ clearCmuxSidebar: (preferences) => pi.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "clear", preferences }),
70
+ };
71
+ }
63
72
  // ── Extracted modules ──────────────────────────────────────────────────────
64
73
  import { startUnitSupervision } from "./auto-timers.js";
65
74
  import { runPostUnitVerification } from "./auto-verification.js";
@@ -136,6 +145,24 @@ function restoreMilestoneLockEnv() {
136
145
  s.hadMilestoneLockEnv = false;
137
146
  s.milestoneLockEnvCaptured = false;
138
147
  }
148
+ function normalizeSessionFilePath(raw) {
149
+ if (typeof raw !== "string")
150
+ return null;
151
+ const trimmed = raw.trim();
152
+ if (!trimmed)
153
+ return null;
154
+ const firstLine = trimmed.split(/\r?\n/, 1)[0]?.trim() ?? "";
155
+ if (!firstLine)
156
+ return null;
157
+ // Guard against accidental message concatenation by trimming to .jsonl.
158
+ const jsonlIndex = firstLine.toLowerCase().indexOf(".jsonl");
159
+ const candidate = jsonlIndex >= 0 ? firstLine.slice(0, jsonlIndex + ".jsonl".length) : firstLine;
160
+ if (!isAbsolute(candidate))
161
+ return null;
162
+ if (!candidate.toLowerCase().endsWith(".jsonl"))
163
+ return null;
164
+ return candidate;
165
+ }
139
166
  export function startAutoDetached(ctx, pi, base, verboseMode, options) {
140
167
  void startAuto(ctx, pi, base, verboseMode, options).catch((err) => {
141
168
  const message = getErrorMessage(err);
@@ -248,6 +275,10 @@ export function getAutoDashboardData() {
248
275
  export function isAutoActive() {
249
276
  return s.active;
250
277
  }
278
+ /** Test-only seam for validating auto-mode guards (#4704). Do not use in production code. */
279
+ export function _setAutoActiveForTest(active) {
280
+ s.active = active;
281
+ }
251
282
  export function isAutoPaused() {
252
283
  return s.paused;
253
284
  }
@@ -427,7 +458,6 @@ function handleLostSessionLock(ctx, lockStatus) {
427
458
  restoreProjectRootEnv();
428
459
  restoreMilestoneLockEnv();
429
460
  deregisterSigtermHandler();
430
- clearCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences);
431
461
  const base = lockBase();
432
462
  const lockFilePath = base ? join(gsdRoot(base), "auto.lock") : "unknown";
433
463
  const recoverySuggestion = "\nTo recover, run: gsd doctor --fix";
@@ -443,7 +473,6 @@ function handleLostSessionLock(ctx, lockStatus) {
443
473
  ctx?.ui.notify(message, "error");
444
474
  ctx?.ui.setStatus("gsd-auto", undefined);
445
475
  ctx?.ui.setWidget("gsd-progress", undefined);
446
- ctx?.ui.setFooter(undefined);
447
476
  if (ctx)
448
477
  initHealthWidget(ctx);
449
478
  }
@@ -480,7 +509,6 @@ function cleanupAfterLoopExit(ctx) {
480
509
  if (!s.paused) {
481
510
  ctx.ui.setStatus("gsd-auto", undefined);
482
511
  ctx.ui.setWidget("gsd-progress", undefined);
483
- ctx.ui.setFooter(undefined);
484
512
  initHealthWidget(ctx);
485
513
  }
486
514
  // Restore CWD out of worktree back to original project root
@@ -657,8 +685,12 @@ export async function stopAuto(ctx, pi, reason) {
657
685
  }
658
686
  // ── Step 9: Cmux sidebar / event log ──
659
687
  try {
660
- clearCmuxSidebar(loadedPreferences);
661
- logCmuxEvent(loadedPreferences, `Auto-mode stopped${reasonSuffix || ""}.`, reason?.startsWith("Blocked:") ? "warning" : "info");
688
+ pi?.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "clear", preferences: loadedPreferences });
689
+ pi?.events.emit(CMUX_CHANNELS.LOG, {
690
+ preferences: loadedPreferences,
691
+ message: `Auto-mode stopped${reasonSuffix || ""}.`,
692
+ level: reason?.startsWith("Blocked:") ? "warning" : "info",
693
+ });
662
694
  }
663
695
  catch (e) {
664
696
  debugLog("stop-cleanup-cmux", { error: e instanceof Error ? e.message : String(e) });
@@ -743,7 +775,6 @@ export async function stopAuto(ctx, pi, reason) {
743
775
  // UI cleanup
744
776
  ctx?.ui.setStatus("gsd-auto", undefined);
745
777
  ctx?.ui.setWidget("gsd-progress", undefined);
746
- ctx?.ui.setFooter(undefined);
747
778
  if (ctx)
748
779
  initHealthWidget(ctx);
749
780
  restoreProjectRootEnv();
@@ -778,7 +809,7 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
778
809
  // Pass errorContext so runUnitPhase can distinguish user-initiated pause
779
810
  // from provider-error pause and avoid hard-stopping (#2762).
780
811
  resolveAgentEndCancelled(_errorContext);
781
- s.pausedSessionFile = ctx?.sessionManager?.getSessionFile() ?? null;
812
+ s.pausedSessionFile = normalizeSessionFilePath(ctx?.sessionManager?.getSessionFile() ?? null);
782
813
  // Persist paused-session metadata so resume survives /exit (#1383).
783
814
  // The fresh-start bootstrap checks for this file and restores worktree context.
784
815
  try {
@@ -832,7 +863,6 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
832
863
  s.verificationRetryCount.clear();
833
864
  ctx?.ui.setStatus("gsd-auto", "paused");
834
865
  ctx?.ui.setWidget("gsd-progress", undefined);
835
- ctx?.ui.setFooter(undefined);
836
866
  if (ctx)
837
867
  initHealthWidget(ctx);
838
868
  const resumeCmd = s.stepMode ? "/gsd next" : "/gsd auto";
@@ -877,11 +907,12 @@ function buildResolver() {
877
907
  * Build the LoopDeps object from auto.ts private scope.
878
908
  * This bundles all private functions that autoLoop needs without exporting them.
879
909
  */
880
- function buildLoopDeps() {
910
+ function buildLoopDeps(pi) {
881
911
  // Initialize the unified rule registry with converted dispatch rules.
882
912
  // Must happen before LoopDeps is assembled so facade functions
883
913
  // (resolveDispatch, runPreDispatchHooks, etc.) delegate to the registry.
884
914
  initRegistry(convertDispatchRules(DISPATCH_RULES));
915
+ const cmux = makeCmuxEmitters(pi);
885
916
  return {
886
917
  lockBase,
887
918
  buildSnapshotOpts,
@@ -889,8 +920,11 @@ function buildLoopDeps() {
889
920
  pauseAuto,
890
921
  clearUnitTimeout,
891
922
  updateProgressWidget,
892
- syncCmuxSidebar,
893
- logCmuxEvent,
923
+ ...cmux,
924
+ handleLostSessionLock: (ctx, lockStatus) => {
925
+ cmux.clearCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences);
926
+ handleLostSessionLock(ctx, lockStatus);
927
+ },
894
928
  // State and cache
895
929
  invalidateAllCaches,
896
930
  deriveState,
@@ -905,7 +939,6 @@ function buildLoopDeps() {
905
939
  // Session lock
906
940
  validateSessionLock: getSessionLockStatus,
907
941
  updateSessionLock,
908
- handleLostSessionLock,
909
942
  // Milestone transition
910
943
  sendDesktopNotification,
911
944
  setActiveMilestoneId,
@@ -978,6 +1011,9 @@ function buildLoopDeps() {
978
1011
  },
979
1012
  // Journal
980
1013
  emitJournalEvent: (entry) => _emitJournalEvent(s.basePath, entry),
1014
+ // Clean-root preflight gate (#2909)
1015
+ preflightCleanRoot,
1016
+ postflightPopStash,
981
1017
  };
982
1018
  }
983
1019
  /**
@@ -1034,7 +1070,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1034
1070
  unlinkSync(pausedPath);
1035
1071
  }
1036
1072
  catch (e) {
1037
- logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
1073
+ if (e.code !== "ENOENT") {
1074
+ logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
1075
+ }
1038
1076
  }
1039
1077
  ctx.ui.notify(`Resuming paused custom workflow${meta.activeRunDir ? ` (${meta.activeRunDir})` : ""}.`, "info");
1040
1078
  }
@@ -1047,12 +1085,23 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1047
1085
  // Validate the milestone still exists and isn't already complete (#1664).
1048
1086
  const mDir = resolveMilestonePath(base, meta.milestoneId);
1049
1087
  const summaryFile = resolveMilestoneFile(base, meta.milestoneId, "SUMMARY");
1050
- if (!mDir || summaryFile) {
1088
+ let summaryIsTerminal = false;
1089
+ if (summaryFile) {
1090
+ try {
1091
+ summaryIsTerminal = classifyMilestoneSummaryContent(readFileSync(summaryFile, "utf-8")) !== "failure";
1092
+ }
1093
+ catch {
1094
+ summaryIsTerminal = false;
1095
+ }
1096
+ }
1097
+ if (!mDir || summaryIsTerminal) {
1051
1098
  try {
1052
1099
  unlinkSync(pausedPath);
1053
1100
  }
1054
1101
  catch (err) {
1055
- logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1102
+ if (err.code !== "ENOENT") {
1103
+ logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1104
+ }
1056
1105
  }
1057
1106
  ctx.ui.notify(`Paused milestone ${meta.milestoneId} is ${!mDir ? "missing" : "already complete"}. Starting fresh.`, "info");
1058
1107
  }
@@ -1060,7 +1109,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1060
1109
  s.currentMilestoneId = meta.milestoneId;
1061
1110
  s.originalBasePath = meta.originalBasePath || base;
1062
1111
  s.stepMode = meta.stepMode ?? requestedStepMode;
1063
- s.pausedSessionFile = meta.sessionFile ?? null;
1112
+ s.pausedSessionFile = normalizeSessionFilePath(meta.sessionFile ?? null);
1064
1113
  s.pausedUnitType = meta.unitType ?? null;
1065
1114
  s.pausedUnitId = meta.unitId ?? null;
1066
1115
  s.autoStartTime = meta.autoStartTime || Date.now();
@@ -1070,7 +1119,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1070
1119
  unlinkSync(pausedPath);
1071
1120
  }
1072
1121
  catch (e) {
1073
- logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
1122
+ if (e.code !== "ENOENT") {
1123
+ logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
1124
+ }
1074
1125
  }
1075
1126
  ctx.ui.notify(`Resuming paused session for ${meta.milestoneId}${meta.worktreePath && existsSync(meta.worktreePath) ? ` (worktree)` : ""}.`, "info");
1076
1127
  }
@@ -1080,7 +1131,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1080
1131
  unlinkSync(pausedPath);
1081
1132
  }
1082
1133
  catch (e) {
1083
- logWarning("session", `stale pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
1134
+ if (e.code !== "ENOENT") {
1135
+ logWarning("session", `stale pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
1136
+ }
1084
1137
  }
1085
1138
  }
1086
1139
  }
@@ -1136,7 +1189,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1136
1189
  unlinkSync(s.pausedSessionFile);
1137
1190
  }
1138
1191
  catch (err) {
1139
- logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1192
+ if (err.code !== "ENOENT") {
1193
+ logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1194
+ }
1140
1195
  }
1141
1196
  s.pausedSessionFile = null;
1142
1197
  }
@@ -1146,6 +1201,17 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1146
1201
  s.stepMode = requestedStepMode;
1147
1202
  s.cmdCtx = ctx;
1148
1203
  s.basePath = base;
1204
+ // ── Resume worktree: if the paused session was inside a milestone worktree,
1205
+ // apply that path as the dispatch basePath immediately (#3723).
1206
+ // This ensures the dispatch loop runs from the worktree directory even when
1207
+ // enterMilestone guard conditions differ between the original and resumed
1208
+ // session (e.g. isolation mode changed, detectWorktreeName differs across
1209
+ // process restarts). We guard with existsSync so a stale or deleted
1210
+ // worktree directory safely falls back to the project root.
1211
+ const resumeWorktreePath = freshStartAssessment.pausedSession?.worktreePath;
1212
+ if (resumeWorktreePath && existsSync(resumeWorktreePath)) {
1213
+ s.basePath = resumeWorktreePath;
1214
+ }
1149
1215
  // Ensure the workflow-logger audit log is pinned to the project root
1150
1216
  // even when auto-mode is entered via a path that bypasses the
1151
1217
  // bootstrap/dynamic-tools ensureDbOpen() → setLogBasePath() chain
@@ -1175,7 +1241,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1175
1241
  }
1176
1242
  registerSigtermHandler(lockBase());
1177
1243
  ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
1178
- ctx.ui.setFooter(hideFooter);
1244
+ ctx.ui.setWidget("gsd-health", undefined);
1179
1245
  ctx.ui.notify(s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "info");
1180
1246
  restoreHookState(s.basePath);
1181
1247
  // Re-sync managed resources on resume so long-lived auto sessions pick up
@@ -1197,7 +1263,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1197
1263
  await openProjectDbIfPresent(s.basePath);
1198
1264
  try {
1199
1265
  await rebuildState(s.basePath);
1200
- syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
1266
+ pi.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "sync", preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, state: await deriveState(s.basePath) });
1201
1267
  }
1202
1268
  catch (e) {
1203
1269
  debugLog("resume-rebuild-state-failed", {
@@ -1227,14 +1293,14 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1227
1293
  }
1228
1294
  updateSessionLock(lockBase(), "resuming", s.currentMilestoneId ?? "unknown");
1229
1295
  writeLock(lockBase(), "resuming", s.currentMilestoneId ?? "unknown");
1230
- logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
1296
+ pi.events.emit(CMUX_CHANNELS.LOG, { preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, message: s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", level: "progress" });
1231
1297
  captureProjectRootEnv(s.originalBasePath || s.basePath);
1232
1298
  startAutoCommandPolling(s.basePath);
1233
1299
  await runAutoLoopWithUok({
1234
1300
  ctx,
1235
1301
  pi,
1236
1302
  s,
1237
- deps: buildLoopDeps(),
1303
+ deps: buildLoopDeps(pi),
1238
1304
  runKernelLoop: runUokKernelLoop,
1239
1305
  runLegacyLoop: runLegacyAutoLoop,
1240
1306
  });
@@ -1253,20 +1319,20 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1253
1319
  return;
1254
1320
  captureProjectRootEnv(s.originalBasePath || s.basePath);
1255
1321
  try {
1256
- syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
1322
+ pi.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "sync", preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, state: await deriveState(s.basePath) });
1257
1323
  }
1258
1324
  catch (err) {
1259
1325
  // Best-effort only — sidebar sync must never block auto-mode startup
1260
1326
  logWarning("engine", `cmux sync failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1261
1327
  }
1262
- logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
1328
+ pi.events.emit(CMUX_CHANNELS.LOG, { preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, message: requestedStepMode ? "Step-mode started." : "Auto-mode started.", level: "progress" });
1263
1329
  startAutoCommandPolling(s.basePath);
1264
1330
  // Dispatch the first unit
1265
1331
  await runAutoLoopWithUok({
1266
1332
  ctx,
1267
1333
  pi,
1268
1334
  s,
1269
- deps: buildLoopDeps(),
1335
+ deps: buildLoopDeps(pi),
1270
1336
  runKernelLoop: runUokKernelLoop,
1271
1337
  runLegacyLoop: runLegacyAutoLoop,
1272
1338
  });
@@ -1364,8 +1430,8 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
1364
1430
  `Ensure the model is defined in models.json and has auth configured.`, "warning");
1365
1431
  }
1366
1432
  }
1367
- const sessionFile = ctx.sessionManager.getSessionFile();
1368
- writeLock(lockBase(), hookUnitType, triggerUnitId, sessionFile);
1433
+ const sessionFile = normalizeSessionFilePath(ctx.sessionManager.getSessionFile());
1434
+ writeLock(lockBase(), hookUnitType, triggerUnitId, sessionFile ?? undefined);
1369
1435
  clearUnitTimeout();
1370
1436
  const supervisor = resolveAutoSupervisorConfig();
1371
1437
  const hookHardTimeoutMs = (supervisor.hard_timeout_minutes ?? 30) * 60 * 1000;