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
@@ -126,8 +126,9 @@ import {
126
126
  formatTokenCount,
127
127
  } from "./metrics.js";
128
128
  import { setLogBasePath, logWarning, logError } from "./workflow-logger.js";
129
+ import { preflightCleanRoot, postflightPopStash } from "./clean-root-preflight.js";
129
130
  import { homedir } from "node:os";
130
- import { join } from "node:path";
131
+ import { isAbsolute, join } from "node:path";
131
132
  import { pathToFileURL } from "node:url";
132
133
  import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs";
133
134
  import { atomicWriteSync } from "./atomic-write.js";
@@ -168,6 +169,7 @@ import {
168
169
  buildLoopRemediationSteps,
169
170
  reconcileMergeState,
170
171
  } from "./auto-recovery.js";
172
+ import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
171
173
  import { resolveDispatch, DISPATCH_RULES } from "./auto-dispatch.js";
172
174
  import { getErrorMessage } from "./error-utils.js";
173
175
  import { recoverFailedMigration } from "./migrate-external.js";
@@ -182,7 +184,6 @@ import {
182
184
  unitVerb,
183
185
  formatAutoElapsed as _formatAutoElapsed,
184
186
  formatWidgetTokens,
185
- hideFooter,
186
187
  type WidgetStateAccessors,
187
188
  } from "./auto-dashboard.js";
188
189
  import {
@@ -192,7 +193,18 @@ import {
192
193
  } from "./auto-supervisor.js";
193
194
  import { isDbAvailable, getMilestone } from "./gsd-db.js";
194
195
  import { countPendingCaptures } from "./captures.js";
195
- import { clearCmuxSidebar, logCmuxEvent, syncCmuxSidebar } from "../cmux/index.js";
196
+ import { CMUX_CHANNELS, type CmuxLogLevel } from "../shared/cmux-events.js";
197
+
198
+ function makeCmuxEmitters(pi: ExtensionAPI) {
199
+ return {
200
+ syncCmuxSidebar: (preferences: GSDPreferences | undefined, state: GSDState) =>
201
+ pi.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "sync" as const, preferences, state }),
202
+ logCmuxEvent: (preferences: GSDPreferences | undefined, message: string, level?: CmuxLogLevel) =>
203
+ pi.events.emit(CMUX_CHANNELS.LOG, { preferences, message, level: level ?? "info" }),
204
+ clearCmuxSidebar: (preferences: GSDPreferences | undefined) =>
205
+ pi.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "clear" as const, preferences }),
206
+ };
207
+ }
196
208
 
197
209
  // ── Extracted modules ──────────────────────────────────────────────────────
198
210
  import { startUnitSupervision } from "./auto-timers.js";
@@ -310,6 +322,21 @@ function restoreMilestoneLockEnv(): void {
310
322
  s.milestoneLockEnvCaptured = false;
311
323
  }
312
324
 
325
+ function normalizeSessionFilePath(raw: unknown): string | null {
326
+ if (typeof raw !== "string") return null;
327
+ const trimmed = raw.trim();
328
+ if (!trimmed) return null;
329
+ const firstLine = trimmed.split(/\r?\n/, 1)[0]?.trim() ?? "";
330
+ if (!firstLine) return null;
331
+
332
+ // Guard against accidental message concatenation by trimming to .jsonl.
333
+ const jsonlIndex = firstLine.toLowerCase().indexOf(".jsonl");
334
+ const candidate = jsonlIndex >= 0 ? firstLine.slice(0, jsonlIndex + ".jsonl".length) : firstLine;
335
+ if (!isAbsolute(candidate)) return null;
336
+ if (!candidate.toLowerCase().endsWith(".jsonl")) return null;
337
+ return candidate;
338
+ }
339
+
313
340
  export function startAutoDetached(
314
341
  ctx: ExtensionCommandContext,
315
342
  pi: ExtensionAPI,
@@ -459,6 +486,11 @@ export function isAutoActive(): boolean {
459
486
  return s.active;
460
487
  }
461
488
 
489
+ /** Test-only seam for validating auto-mode guards (#4704). Do not use in production code. */
490
+ export function _setAutoActiveForTest(active: boolean): void {
491
+ s.active = active;
492
+ }
493
+
462
494
  export function isAutoPaused(): boolean {
463
495
  return s.paused;
464
496
  }
@@ -686,7 +718,6 @@ function handleLostSessionLock(
686
718
  restoreProjectRootEnv();
687
719
  restoreMilestoneLockEnv();
688
720
  deregisterSigtermHandler();
689
- clearCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences);
690
721
  const base = lockBase();
691
722
  const lockFilePath = base ? join(gsdRoot(base), "auto.lock") : "unknown";
692
723
  const recoverySuggestion = "\nTo recover, run: gsd doctor --fix";
@@ -706,7 +737,6 @@ function handleLostSessionLock(
706
737
  );
707
738
  ctx?.ui.setStatus("gsd-auto", undefined);
708
739
  ctx?.ui.setWidget("gsd-progress", undefined);
709
- ctx?.ui.setFooter(undefined);
710
740
  if (ctx) initHealthWidget(ctx);
711
741
  }
712
742
 
@@ -742,7 +772,6 @@ function cleanupAfterLoopExit(ctx: ExtensionContext): void {
742
772
  if (!s.paused) {
743
773
  ctx.ui.setStatus("gsd-auto", undefined);
744
774
  ctx.ui.setWidget("gsd-progress", undefined);
745
- ctx.ui.setFooter(undefined);
746
775
  initHealthWidget(ctx);
747
776
  }
748
777
 
@@ -929,12 +958,12 @@ export async function stopAuto(
929
958
 
930
959
  // ── Step 9: Cmux sidebar / event log ──
931
960
  try {
932
- clearCmuxSidebar(loadedPreferences);
933
- logCmuxEvent(
934
- loadedPreferences,
935
- `Auto-mode stopped${reasonSuffix || ""}.`,
936
- reason?.startsWith("Blocked:") ? "warning" : "info",
937
- );
961
+ pi?.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "clear" as const, preferences: loadedPreferences });
962
+ pi?.events.emit(CMUX_CHANNELS.LOG, {
963
+ preferences: loadedPreferences,
964
+ message: `Auto-mode stopped${reasonSuffix || ""}.`,
965
+ level: reason?.startsWith("Blocked:") ? "warning" : "info",
966
+ });
938
967
  } catch (e) {
939
968
  debugLog("stop-cleanup-cmux", { error: e instanceof Error ? e.message : String(e) });
940
969
  }
@@ -1018,7 +1047,6 @@ export async function stopAuto(
1018
1047
  // UI cleanup
1019
1048
  ctx?.ui.setStatus("gsd-auto", undefined);
1020
1049
  ctx?.ui.setWidget("gsd-progress", undefined);
1021
- ctx?.ui.setFooter(undefined);
1022
1050
  if (ctx) initHealthWidget(ctx);
1023
1051
  restoreProjectRootEnv();
1024
1052
  restoreMilestoneLockEnv();
@@ -1059,7 +1087,7 @@ export async function pauseAuto(
1059
1087
  // from provider-error pause and avoid hard-stopping (#2762).
1060
1088
  resolveAgentEndCancelled(_errorContext);
1061
1089
 
1062
- s.pausedSessionFile = ctx?.sessionManager?.getSessionFile() ?? null;
1090
+ s.pausedSessionFile = normalizeSessionFilePath(ctx?.sessionManager?.getSessionFile() ?? null);
1063
1091
 
1064
1092
  // Persist paused-session metadata so resume survives /exit (#1383).
1065
1093
  // The fresh-start bootstrap checks for this file and restores worktree context.
@@ -1121,7 +1149,6 @@ export async function pauseAuto(
1121
1149
  s.verificationRetryCount.clear();
1122
1150
  ctx?.ui.setStatus("gsd-auto", "paused");
1123
1151
  ctx?.ui.setWidget("gsd-progress", undefined);
1124
- ctx?.ui.setFooter(undefined);
1125
1152
  if (ctx) initHealthWidget(ctx);
1126
1153
  const resumeCmd = s.stepMode ? "/gsd next" : "/gsd auto";
1127
1154
  ctx?.ui.notify(
@@ -1174,12 +1201,14 @@ function buildResolver(): WorktreeResolver {
1174
1201
  * Build the LoopDeps object from auto.ts private scope.
1175
1202
  * This bundles all private functions that autoLoop needs without exporting them.
1176
1203
  */
1177
- function buildLoopDeps(): LoopDeps {
1204
+ function buildLoopDeps(pi: ExtensionAPI): LoopDeps {
1178
1205
  // Initialize the unified rule registry with converted dispatch rules.
1179
1206
  // Must happen before LoopDeps is assembled so facade functions
1180
1207
  // (resolveDispatch, runPreDispatchHooks, etc.) delegate to the registry.
1181
1208
  initRegistry(convertDispatchRules(DISPATCH_RULES));
1182
1209
 
1210
+ const cmux = makeCmuxEmitters(pi);
1211
+
1183
1212
  return {
1184
1213
  lockBase,
1185
1214
  buildSnapshotOpts,
@@ -1187,8 +1216,11 @@ function buildLoopDeps(): LoopDeps {
1187
1216
  pauseAuto,
1188
1217
  clearUnitTimeout,
1189
1218
  updateProgressWidget,
1190
- syncCmuxSidebar,
1191
- logCmuxEvent,
1219
+ ...cmux,
1220
+ handleLostSessionLock: (ctx: ExtensionContext | undefined, lockStatus: SessionLockStatus | undefined) => {
1221
+ cmux.clearCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences);
1222
+ handleLostSessionLock(ctx, lockStatus);
1223
+ },
1192
1224
 
1193
1225
  // State and cache
1194
1226
  invalidateAllCaches,
@@ -1208,7 +1240,6 @@ function buildLoopDeps(): LoopDeps {
1208
1240
  // Session lock
1209
1241
  validateSessionLock: getSessionLockStatus,
1210
1242
  updateSessionLock,
1211
- handleLostSessionLock,
1212
1243
 
1213
1244
  // Milestone transition
1214
1245
  sendDesktopNotification,
@@ -1292,6 +1323,10 @@ function buildLoopDeps(): LoopDeps {
1292
1323
 
1293
1324
  // Journal
1294
1325
  emitJournalEvent: (entry: JournalEntry) => _emitJournalEvent(s.basePath, entry),
1326
+
1327
+ // Clean-root preflight gate (#2909)
1328
+ preflightCleanRoot,
1329
+ postflightPopStash,
1295
1330
  } as unknown as LoopDeps;
1296
1331
  }
1297
1332
 
@@ -1364,7 +1399,11 @@ export async function startAuto(
1364
1399
  s.autoStartTime = meta.autoStartTime || Date.now();
1365
1400
  s.sessionMilestoneLock = meta.milestoneLock ?? null;
1366
1401
  s.paused = true;
1367
- try { unlinkSync(pausedPath); } catch (e) { logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" }); }
1402
+ try { unlinkSync(pausedPath); } catch (e) {
1403
+ if ((e as NodeJS.ErrnoException).code !== "ENOENT") {
1404
+ logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
1405
+ }
1406
+ }
1368
1407
  ctx.ui.notify(
1369
1408
  `Resuming paused custom workflow${meta.activeRunDir ? ` (${meta.activeRunDir})` : ""}.`,
1370
1409
  "info",
@@ -1381,9 +1420,19 @@ export async function startAuto(
1381
1420
  // Validate the milestone still exists and isn't already complete (#1664).
1382
1421
  const mDir = resolveMilestonePath(base, meta.milestoneId);
1383
1422
  const summaryFile = resolveMilestoneFile(base, meta.milestoneId, "SUMMARY");
1384
- if (!mDir || summaryFile) {
1423
+ let summaryIsTerminal = false;
1424
+ if (summaryFile) {
1425
+ try {
1426
+ summaryIsTerminal = classifyMilestoneSummaryContent(readFileSync(summaryFile, "utf-8")) !== "failure";
1427
+ } catch {
1428
+ summaryIsTerminal = false;
1429
+ }
1430
+ }
1431
+ if (!mDir || summaryIsTerminal) {
1385
1432
  try { unlinkSync(pausedPath); } catch (err) {
1386
- logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1433
+ if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
1434
+ logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1435
+ }
1387
1436
  }
1388
1437
  ctx.ui.notify(
1389
1438
  `Paused milestone ${meta.milestoneId} is ${!mDir ? "missing" : "already complete"}. Starting fresh.`,
@@ -1393,20 +1442,28 @@ export async function startAuto(
1393
1442
  s.currentMilestoneId = meta.milestoneId;
1394
1443
  s.originalBasePath = meta.originalBasePath || base;
1395
1444
  s.stepMode = meta.stepMode ?? requestedStepMode;
1396
- s.pausedSessionFile = meta.sessionFile ?? null;
1445
+ s.pausedSessionFile = normalizeSessionFilePath(meta.sessionFile ?? null);
1397
1446
  s.pausedUnitType = meta.unitType ?? null;
1398
1447
  s.pausedUnitId = meta.unitId ?? null;
1399
1448
  s.autoStartTime = meta.autoStartTime || Date.now();
1400
1449
  s.sessionMilestoneLock = meta.milestoneLock ?? null;
1401
1450
  s.paused = true;
1402
- try { unlinkSync(pausedPath); } catch (e) { logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" }); }
1451
+ try { unlinkSync(pausedPath); } catch (e) {
1452
+ if ((e as NodeJS.ErrnoException).code !== "ENOENT") {
1453
+ logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
1454
+ }
1455
+ }
1403
1456
  ctx.ui.notify(
1404
1457
  `Resuming paused session for ${meta.milestoneId}${meta.worktreePath && existsSync(meta.worktreePath) ? ` (worktree)` : ""}.`,
1405
1458
  "info",
1406
1459
  );
1407
1460
  }
1408
1461
  } else if (existsSync(pausedPath)) {
1409
- try { unlinkSync(pausedPath); } catch (e) { logWarning("session", `stale pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" }); }
1462
+ try { unlinkSync(pausedPath); } catch (e) {
1463
+ if ((e as NodeJS.ErrnoException).code !== "ENOENT") {
1464
+ logWarning("session", `stale pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
1465
+ }
1466
+ }
1410
1467
  }
1411
1468
  }
1412
1469
  } catch (err) {
@@ -1465,7 +1522,9 @@ export async function startAuto(
1465
1522
  // Lock acquired — now safe to delete the pause file
1466
1523
  if (s.pausedSessionFile) {
1467
1524
  try { unlinkSync(s.pausedSessionFile); } catch (err) {
1468
- logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1525
+ if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
1526
+ logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1527
+ }
1469
1528
  }
1470
1529
  s.pausedSessionFile = null;
1471
1530
  }
@@ -1476,6 +1535,17 @@ export async function startAuto(
1476
1535
  s.stepMode = requestedStepMode;
1477
1536
  s.cmdCtx = ctx;
1478
1537
  s.basePath = base;
1538
+ // ── Resume worktree: if the paused session was inside a milestone worktree,
1539
+ // apply that path as the dispatch basePath immediately (#3723).
1540
+ // This ensures the dispatch loop runs from the worktree directory even when
1541
+ // enterMilestone guard conditions differ between the original and resumed
1542
+ // session (e.g. isolation mode changed, detectWorktreeName differs across
1543
+ // process restarts). We guard with existsSync so a stale or deleted
1544
+ // worktree directory safely falls back to the project root.
1545
+ const resumeWorktreePath = freshStartAssessment.pausedSession?.worktreePath;
1546
+ if (resumeWorktreePath && existsSync(resumeWorktreePath)) {
1547
+ s.basePath = resumeWorktreePath;
1548
+ }
1479
1549
  // Ensure the workflow-logger audit log is pinned to the project root
1480
1550
  // even when auto-mode is entered via a path that bypasses the
1481
1551
  // bootstrap/dynamic-tools ensureDbOpen() → setLogBasePath() chain
@@ -1509,7 +1579,7 @@ export async function startAuto(
1509
1579
  registerSigtermHandler(lockBase());
1510
1580
 
1511
1581
  ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
1512
- ctx.ui.setFooter(hideFooter);
1582
+ ctx.ui.setWidget("gsd-health", undefined);
1513
1583
  ctx.ui.notify(
1514
1584
  s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.",
1515
1585
  "info",
@@ -1534,7 +1604,7 @@ export async function startAuto(
1534
1604
  await openProjectDbIfPresent(s.basePath);
1535
1605
  try {
1536
1606
  await rebuildState(s.basePath);
1537
- syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
1607
+ pi.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "sync" as const, preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, state: await deriveState(s.basePath) });
1538
1608
  } catch (e) {
1539
1609
  debugLog("resume-rebuild-state-failed", {
1540
1610
  error: e instanceof Error ? e.message : String(e),
@@ -1584,7 +1654,7 @@ export async function startAuto(
1584
1654
  "resuming",
1585
1655
  s.currentMilestoneId ?? "unknown",
1586
1656
  );
1587
- logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
1657
+ pi.events.emit(CMUX_CHANNELS.LOG, { preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, message: s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", level: "progress" });
1588
1658
 
1589
1659
  captureProjectRootEnv(s.originalBasePath || s.basePath);
1590
1660
  startAutoCommandPolling(s.basePath);
@@ -1592,7 +1662,7 @@ export async function startAuto(
1592
1662
  ctx,
1593
1663
  pi,
1594
1664
  s,
1595
- deps: buildLoopDeps(),
1665
+ deps: buildLoopDeps(pi),
1596
1666
  runKernelLoop: runUokKernelLoop,
1597
1667
  runLegacyLoop: runLegacyAutoLoop,
1598
1668
  });
@@ -1622,12 +1692,12 @@ export async function startAuto(
1622
1692
 
1623
1693
  captureProjectRootEnv(s.originalBasePath || s.basePath);
1624
1694
  try {
1625
- syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
1695
+ pi.events.emit(CMUX_CHANNELS.SIDEBAR, { action: "sync" as const, preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, state: await deriveState(s.basePath) });
1626
1696
  } catch (err) {
1627
1697
  // Best-effort only — sidebar sync must never block auto-mode startup
1628
1698
  logWarning("engine", `cmux sync failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1629
1699
  }
1630
- logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
1700
+ pi.events.emit(CMUX_CHANNELS.LOG, { preferences: loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, message: requestedStepMode ? "Step-mode started." : "Auto-mode started.", level: "progress" });
1631
1701
 
1632
1702
  startAutoCommandPolling(s.basePath);
1633
1703
 
@@ -1636,7 +1706,7 @@ export async function startAuto(
1636
1706
  ctx,
1637
1707
  pi,
1638
1708
  s,
1639
- deps: buildLoopDeps(),
1709
+ deps: buildLoopDeps(pi),
1640
1710
  runKernelLoop: runUokKernelLoop,
1641
1711
  runLegacyLoop: runLegacyAutoLoop,
1642
1712
  });
@@ -1776,12 +1846,12 @@ export async function dispatchHookUnit(
1776
1846
  }
1777
1847
  }
1778
1848
 
1779
- const sessionFile = ctx.sessionManager.getSessionFile();
1849
+ const sessionFile = normalizeSessionFilePath(ctx.sessionManager.getSessionFile());
1780
1850
  writeLock(
1781
1851
  lockBase(),
1782
1852
  hookUnitType,
1783
1853
  triggerUnitId,
1784
- sessionFile,
1854
+ sessionFile ?? undefined,
1785
1855
  );
1786
1856
 
1787
1857
  clearUnitTimeout();
@@ -1,7 +1,13 @@
1
1
  import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
2
2
 
3
3
  import { logWarning } from "../workflow-logger.js";
4
- import { checkAutoStartAfterDiscuss } from "../guided-flow.js";
4
+ import {
5
+ checkAutoStartAfterDiscuss,
6
+ maybeHandleReadyPhraseWithoutFiles,
7
+ maybeHandleEmptyIntentTurn,
8
+ resetEmptyTurnCounter,
9
+ } from "../guided-flow.js";
10
+ import { clearPathCache } from "../paths.js";
5
11
  import { getAutoDashboardData, getAutoModeStartModel, isAutoActive, pauseAuto, setCurrentDispatchedModelId } from "../auto.js";
6
12
  import { getNextFallbackModel, resolveModelWithFallbacksForUnit } from "../preferences.js";
7
13
  import { pauseAutoForProviderError } from "../provider-error-pause.js";
@@ -71,10 +77,34 @@ export async function handleAgentEnd(
71
77
  event: { messages: any[] },
72
78
  ctx: ExtensionContext,
73
79
  ): Promise<void> {
80
+ // #4648 — Invalidate the directory-listing cache before any artifact-existence
81
+ // checks. The LLM may have written milestone files (CONTEXT.md, ROADMAP.md,
82
+ // PROJECT.md, REQUIREMENTS.md) via tool calls during the turn that just
83
+ // ended. `paths.ts` caches readdir() results without a TTL, so without this
84
+ // flush, `resolveMilestoneFile` returns the pre-write listing and the guards
85
+ // below (`checkAutoStartAfterDiscuss` and `maybeHandleReadyPhraseWithoutFiles`)
86
+ // falsely report files as missing — producing a spurious "ready signal
87
+ // rejected" loop even though the files are on disk.
88
+ clearPathCache();
89
+
74
90
  if (checkAutoStartAfterDiscuss()) {
75
91
  clearDiscussionFlowState();
76
92
  return;
77
93
  }
94
+
95
+ // #4573 — When the LLM emits "Milestone X ready." but the required files
96
+ // are missing, `checkAutoStartAfterDiscuss` returns false silently. Surface
97
+ // that and nudge the LLM to complete the writes before the user hits the
98
+ // downstream "All milestones complete" warning loop.
99
+ if (maybeHandleReadyPhraseWithoutFiles(event)) return;
100
+
101
+ // #4573 — Empty-turn recovery: if the LLM announced intent in prose but
102
+ // emitted no tool calls, nudge it to execute. Fires only when auto-mode is
103
+ // active or a discussion autostart is pending (non-auto interactive discuss
104
+ // is user-driven). Runs before `isAutoActive` early return so pending
105
+ // discussions (where isAutoActive may be false) still get recovered.
106
+ if (maybeHandleEmptyIntentTurn(event, isAutoActive())) return;
107
+
78
108
  if (!isAutoActive()) return;
79
109
  if (isSessionSwitchInFlight()) return;
80
110
 
@@ -336,6 +366,9 @@ export async function handleAgentEnd(
336
366
  // ── Success path ─────────────────────────────────────────────────────────
337
367
  try {
338
368
  resetRetryState(retryState);
369
+ // #4573 — Reset the empty-turn counter on any successful agent turn so
370
+ // transient stalls don't accumulate across independent units.
371
+ resetEmptyTurnCounter();
339
372
  resolveAgentEnd(event);
340
373
  } catch (err) {
341
374
  const message = err instanceof Error ? err.message : String(err);
@@ -12,6 +12,8 @@ type AutoResumeSnapshot = Pick<AutoDashboardData, "active" | "paused" | "stepMod
12
12
 
13
13
  export interface ProviderErrorResumeDeps {
14
14
  getSnapshot(): AutoResumeSnapshot;
15
+ resetTransientRetryState(): void;
16
+ resetSessionTimeoutState(): void;
15
17
  startAuto(
16
18
  ctx: ExtensionCommandContext,
17
19
  pi: ExtensionAPI,
@@ -23,6 +25,8 @@ export interface ProviderErrorResumeDeps {
23
25
 
24
26
  const defaultDeps: ProviderErrorResumeDeps = {
25
27
  getSnapshot: () => getAutoDashboardData(),
28
+ resetTransientRetryState,
29
+ resetSessionTimeoutState,
26
30
  startAuto,
27
31
  };
28
32
 
@@ -47,8 +51,8 @@ export async function resumeAutoAfterProviderDelay(
47
51
  // Reset retry counters before restarting — without this, counters
48
52
  // accumulate across pause/resume cycles and permanently lock out
49
53
  // auto-resume after their respective MAX thresholds.
50
- resetTransientRetryState();
51
- resetSessionTimeoutState();
54
+ deps.resetTransientRetryState();
55
+ deps.resetSessionTimeoutState();
52
56
 
53
57
  await deps.startAuto(
54
58
  ctx as ExtensionCommandContext,
@@ -16,6 +16,13 @@ import { registerHooks } from "./register-hooks.js";
16
16
  import { registerShortcuts } from "./register-shortcuts.js";
17
17
  import { writeCrashLog } from "./crash-log.js";
18
18
  import { logWarning } from "../workflow-logger.js";
19
+ // Static import so cmux event listeners are registered synchronously during
20
+ // extension bootstrap. Prior implementation used `void import().then()` which
21
+ // queued listener registration as a microtask — any CMUX_CHANNELS emit fired
22
+ // in the same event loop turn as registration (e.g. from a provider-error
23
+ // session hook calling startAuto) would be silently dropped because Node's
24
+ // EventEmitter does not buffer events for late subscribers.
25
+ import { initCmuxEventListeners } from "../../cmux/index.js";
19
26
 
20
27
  export { writeCrashLog } from "./crash-log.js";
21
28
 
@@ -103,6 +110,10 @@ export function registerGsdExtension(pi: ExtensionAPI): void {
103
110
  ["memory-tools", () => registerMemoryTools(pi)],
104
111
  ["exec-tools", () => registerExecTools(pi)],
105
112
  ["shortcuts", () => registerShortcuts(pi)],
113
+ // cmux is a library (no pi), so gsd sets up the event listeners on its
114
+ // behalf using the shared event channel contract. Registration is
115
+ // synchronous — see the import comment above for the rationale.
116
+ ["cmux-events", () => initCmuxEventListeners(pi.events)],
106
117
  ["hooks", () => registerHooks(pi, ecosystemHandlers)],
107
118
  ["ecosystem", () => {
108
119
  void loadEcosystemExtensions(pi, ecosystemHandlers).catch((err) => {
@@ -18,12 +18,13 @@ import { loadToolApiKeys } from "../commands-config.js";
18
18
  import { loadFile, saveFile, formatContinue } from "../files.js";
19
19
  import { deriveState } from "../state.js";
20
20
  import { getAutoDashboardData, isAutoActive, isAutoPaused, markToolEnd, markToolStart, recordToolInvocationError } from "../auto.js";
21
- import { hideFooter } from "../auto-dashboard.js";
21
+
22
22
  import { isParallelActive, shutdownParallel } from "../parallel-orchestrator.js";
23
23
  import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
24
24
  import { saveActivityLog } from "../activity-log.js";
25
25
  import { resetAskUserQuestionsCache } from "../../ask-user-questions.js";
26
- import { recordToolCall as safetyRecordToolCall, recordToolResult as safetyRecordToolResult } from "../safety/evidence-collector.js";
26
+ import { recordToolCall as safetyRecordToolCall, recordToolResult as safetyRecordToolResult, saveEvidenceToDisk } from "../safety/evidence-collector.js";
27
+ import { parseUnitId } from "../unit-id.js";
27
28
  import { classifyCommand } from "../safety/destructive-guard.js";
28
29
  import { logWarning as safetyLogWarning } from "../workflow-logger.js";
29
30
  import { installNotifyInterceptor } from "./notify-interceptor.js";
@@ -48,7 +49,9 @@ export function registerHooks(
48
49
  initNotificationStore(process.cwd());
49
50
  installNotifyInterceptor(ctx);
50
51
  initNotificationWidget(ctx);
51
- initHealthWidget(ctx);
52
+ if (!isAutoActive()) {
53
+ initHealthWidget(ctx);
54
+ }
52
55
  resetWriteGateState();
53
56
  resetToolCallLoopGuard();
54
57
  resetAskUserQuestionsCache();
@@ -90,7 +93,7 @@ export function registerHooks(
90
93
  }
91
94
  loadToolApiKeys();
92
95
  if (isAutoActive()) {
93
- ctx.ui.setFooter(hideFooter);
96
+ ctx.ui.setWidget("gsd-health", undefined);
94
97
  }
95
98
  });
96
99
 
@@ -113,7 +116,7 @@ export function registerHooks(
113
116
  }
114
117
  loadToolApiKeys();
115
118
  if (isAutoActive()) {
116
- ctx.ui.setFooter(hideFooter);
119
+ ctx.ui.setWidget("gsd-health", undefined);
117
120
  }
118
121
  });
119
122
 
@@ -481,7 +484,7 @@ export function registerHooks(
481
484
 
482
485
  pi.on("tool_execution_start", async (event) => {
483
486
  if (!isAutoActive()) return;
484
- markToolStart(event.toolCallId);
487
+ markToolStart(event.toolCallId, event.toolName);
485
488
  });
486
489
 
487
490
  pi.on("tool_execution_end", async (event) => {
@@ -497,6 +500,15 @@ export function registerHooks(
497
500
  // Safety harness: record tool execution results for evidence cross-referencing
498
501
  if (isAutoActive()) {
499
502
  safetyRecordToolResult(event.toolCallId, event.toolName, event.result, event.isError);
503
+ // Persist evidence to disk after each tool result so it survives a session
504
+ // restart mid-unit (Bug #4385 — non-persisted evidence false positives).
505
+ const dash = getAutoDashboardData();
506
+ if (dash.basePath && dash.currentUnit?.type === "execute-task") {
507
+ const { milestone: pMid, slice: pSid, task: pTid } = parseUnitId(dash.currentUnit.id);
508
+ if (pMid && pSid && pTid) {
509
+ saveEvidenceToDisk(dash.basePath, pMid, pSid, pTid);
510
+ }
511
+ }
500
512
  }
501
513
  });
502
514
 
@@ -19,7 +19,6 @@ import { getActiveWorktreeName, getWorktreeOriginalCwd } from "../worktree-comma
19
19
  import { deriveState } from "../state.js";
20
20
  import { formatOverridesSection, formatShortcut, loadActiveOverrides, loadFile, parseContinue, parseSummary } from "../files.js";
21
21
  import { toPosixPath } from "../../shared/mod.js";
22
- import { markCmuxPromptShown, shouldPromptToEnableCmux } from "../../cmux/index.js";
23
22
  import { autoEnableCmuxPreferences } from "../commands-cmux.js";
24
23
 
25
24
  const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
@@ -99,15 +98,20 @@ export async function buildBeforeAgentStartResult(
99
98
  shortcutShell: formatShortcut("Ctrl+Alt+B"),
100
99
  });
101
100
  let loadedPreferences = loadEffectiveGSDPreferences();
102
- if (shouldPromptToEnableCmux(loadedPreferences?.preferences)) {
103
- markCmuxPromptShown();
104
- if (autoEnableCmuxPreferences()) {
105
- loadedPreferences = loadEffectiveGSDPreferences();
106
- ctx.ui.notify(
107
- "cmux detected — auto-enabled. Run /gsd cmux off to disable.",
108
- "info",
109
- );
101
+ try {
102
+ const { markCmuxPromptShown, shouldPromptToEnableCmux } = await import("../../cmux/index.js");
103
+ if (shouldPromptToEnableCmux(loadedPreferences?.preferences)) {
104
+ markCmuxPromptShown();
105
+ if (autoEnableCmuxPreferences()) {
106
+ loadedPreferences = loadEffectiveGSDPreferences();
107
+ ctx.ui.notify(
108
+ "cmux detected — auto-enabled. Run /gsd cmux off to disable.",
109
+ "info",
110
+ );
111
+ }
110
112
  }
113
+ } catch (e) {
114
+ logWarning("bootstrap", `cmux prompt setup skipped: ${(e as Error).message}`);
111
115
  }
112
116
 
113
117
  let preferenceBlock = "";
@@ -28,8 +28,29 @@ const QUEUE_SAFE_TOOLS = new Set([
28
28
  /**
29
29
  * Bash commands that are read-only / investigative — safe during queue mode.
30
30
  * Matches the leading command in a bash invocation.
31
+ *
32
+ * Extension policy: add commands here when they are read-only / diagnostic.
33
+ * Never add commands that mutate project state (write files, run builds that
34
+ * emit artifacts, install packages, etc.).
35
+ *
36
+ * Current read-only additions (Bug #4385):
37
+ * npm run <diagnostic> — read-only diagnostic scripts: test, lint, typecheck, etc.
38
+ * NOT: build, install, compile, generate, deploy (artifact-producing)
39
+ * npm ls/list/info — inspect installed packages (read-only)
40
+ * npm outdated/audit — security/update checks (read-only)
41
+ * npx <pkg> — run a package binary without installing globally
42
+ * tsx — TypeScript runner used for dry-run / inspection scripts
43
+ * node --print — evaluate and print an expression, no side effects
44
+ * python / python3 — script inspection, version checks
45
+ * pip / pip3 show — show installed package info (read-only)
46
+ * jq — read-only JSON query
47
+ * yq — read-only YAML query
48
+ * curl -s / curl --silent — fetch for inspection (no -o / no output redirect)
49
+ * openssl version — version / certificate inspection
50
+ * env / printenv — print environment variables
51
+ * true / false — shell no-ops / test exit codes
31
52
  */
32
- const BASH_READ_ONLY_RE = /^\s*(cat|head|tail|less|more|wc|file|stat|du|df|which|type|echo|printf|ls|find|grep|rg|awk|sed\b(?!.*-i)|sort|uniq|diff|comm|tr|cut|tee\s+-a\s+\/dev\/null|git\s+(log|show|diff|status|branch|tag|remote|rev-parse|ls-files|blame|shortlog|describe|stash\s+list|config\s+--get|cat-file)|gh\s+(issue|pr|api|repo|release)\s+(view|list|diff|status|checks)|mkdir\s+-p\s+\.gsd|rtk\s)/;
53
+ const BASH_READ_ONLY_RE = /^\s*(cat|head|tail|less|more|wc|file|stat|du|df|which|type|echo|printf|ls|find|grep|rg|awk|sed\b(?!.*-i)|sort|uniq|diff|comm|tr|cut|tee\s+-a\s+\/dev\/null|git\s+(log|show|diff|status|branch|tag|remote|rev-parse|ls-files|blame|shortlog|describe|stash\s+list|config\s+--get|cat-file)|gh\s+(issue|pr|api|repo|release)\s+(view|list|diff|status|checks)|mkdir\s+-p\s+\.gsd|rtk\s|npm\s+run\s+(test|test:\w+|lint|lint:\w+|typecheck|type-check|type-check:\w+|check|verify|audit|outdated|format:check|ci|validate)\b|npm\s+(ls|list|info|view|show|outdated|audit|explain|doctor|ping|--version|-v)\b|npx\s|tsx\s|node\s+(--print|--version|-v\b)|python[23]?\s+(-c\s+'[^']*'|--version|-V\b|-m\s+(pip\s+show|pip\s+list|site))|pip[23]?\s+(show|list|freeze|check|index\s+versions)\b|jq\s|yq\s|curl\s+(-s\b|--silent\b)(?!\s+[^|>]*\s-[oO]\b)(?!\s+[^|>]*\s--output\b)[^|>]*$|openssl\s+(version|x509|s_client)|env\b|printenv\b|true\b|false\b)/;
33
54
 
34
55
  const verifiedDepthMilestones = new Set<string>();
35
56
  let activeQueuePhase = false;
@@ -117,9 +138,21 @@ function normalizeWriteGateSnapshot(value: unknown): WriteGateSnapshot {
117
138
  };
118
139
  }
119
140
 
141
+ const EMPTY_SNAPSHOT: WriteGateSnapshot = {
142
+ verifiedDepthMilestones: [],
143
+ activeQueuePhase: false,
144
+ pendingGateId: null,
145
+ };
146
+
120
147
  export function loadWriteGateSnapshot(basePath: string = process.cwd()): WriteGateSnapshot {
121
148
  const path = writeGateSnapshotPath(basePath);
122
- if (!existsSync(path)) return currentWriteGateSnapshot();
149
+ if (!existsSync(path)) {
150
+ // When persist mode is active and the file has been deleted, treat it as a
151
+ // full state reset so deleting the file clears the HARD BLOCK gate.
152
+ // In non-persist mode the file is never written, so fall back to in-memory.
153
+ if (shouldPersistWriteGateSnapshot()) return EMPTY_SNAPSHOT;
154
+ return currentWriteGateSnapshot();
155
+ }
123
156
  try {
124
157
  return normalizeWriteGateSnapshot(JSON.parse(readFileSync(path, "utf-8")));
125
158
  } catch {