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
@@ -32,11 +32,12 @@ import { isInfrastructureError, isTransientCooldownError, getCooldownRetryAfterM
32
32
  import { resolveEngine } from "../engine-resolver.js";
33
33
  import { logWarning } from "../workflow-logger.js";
34
34
  import { gsdRoot } from "../paths.js";
35
+ import { atomicWriteSync } from "../atomic-write.js";
35
36
  import { resolveUokFlags } from "../uok/flags.js";
36
37
  import { scheduleSidecarQueue } from "../uok/execution-graph.js";
37
38
  import { ExecutionGraphScheduler } from "../uok/execution-graph.js";
38
39
  import type { UokGraphNode } from "../uok/contracts.js";
39
- import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
40
+ import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs";
40
41
  import { join } from "node:path";
41
42
 
42
43
  // ── Stuck detection persistence (#3704) ──────────────────────────────────
@@ -50,6 +51,13 @@ function stuckStatePath(basePath: string): string {
50
51
  function loadStuckState(basePath: string): { recentUnits: Array<{ key: string }>; stuckRecoveryAttempts: number } {
51
52
  try {
52
53
  const data = JSON.parse(readFileSync(stuckStatePath(basePath), "utf-8"));
54
+ // Only load state written by a DIFFERENT process (real session restart).
55
+ // If the PID matches the current process, this state was written by an earlier
56
+ // autoLoop call in the same process (e.g., a test that completed before this
57
+ // one), not by a crashed session — skip it to prevent test state pollution.
58
+ if (data.pid === process.pid) {
59
+ return { recentUnits: [], stuckRecoveryAttempts: 0 };
60
+ }
53
61
  return {
54
62
  recentUnits: Array.isArray(data.recentUnits) ? data.recentUnits : [],
55
63
  stuckRecoveryAttempts: typeof data.stuckRecoveryAttempts === "number" ? data.stuckRecoveryAttempts : 0,
@@ -65,6 +73,7 @@ function saveStuckState(basePath: string, state: LoopState): void {
65
73
  const filePath = stuckStatePath(basePath);
66
74
  mkdirSync(join(gsdRoot(basePath), "runtime"), { recursive: true });
67
75
  writeFileSync(filePath, JSON.stringify({
76
+ pid: process.pid,
68
77
  recentUnits: state.recentUnits.slice(-20), // keep last 20 entries
69
78
  stuckRecoveryAttempts: state.stuckRecoveryAttempts,
70
79
  updatedAt: new Date().toISOString(),
@@ -74,12 +83,69 @@ function saveStuckState(basePath: string, state: LoopState): void {
74
83
  }
75
84
  }
76
85
 
86
+ // ── Custom workflow verification retry persistence ───────────────────────
87
+ // Custom workflows can request verification retries after a step runs. The
88
+ // retry budget must survive an auto-mode restart or a failing verifier can
89
+ // consume a fresh retry budget every session.
90
+ function customVerifyRetryStateDir(s: Pick<AutoSession, "activeRunDir" | "basePath">): string {
91
+ return s.activeRunDir ? join(s.activeRunDir, "runtime") : join(gsdRoot(s.basePath), "runtime");
92
+ }
93
+
94
+ function customVerifyRetryStatePath(s: Pick<AutoSession, "activeRunDir" | "basePath">): string {
95
+ return join(customVerifyRetryStateDir(s), "custom-verify-retries.json");
96
+ }
97
+
98
+ function hydrateCustomVerifyRetryCounts(s: AutoSession): Map<string, number> {
99
+ if (s.verificationRetryCount.size > 0) {
100
+ return s.verificationRetryCount;
101
+ }
102
+
103
+ try {
104
+ const raw = JSON.parse(readFileSync(customVerifyRetryStatePath(s), "utf-8"));
105
+ const counts = raw && typeof raw === "object" && raw.counts && typeof raw.counts === "object"
106
+ ? raw.counts as Record<string, unknown>
107
+ : {};
108
+ for (const [key, value] of Object.entries(counts)) {
109
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
110
+ s.verificationRetryCount.set(key, Math.floor(value));
111
+ }
112
+ }
113
+ } catch (err) {
114
+ debugLog("autoLoop", { phase: "load-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
115
+ }
116
+
117
+ return s.verificationRetryCount;
118
+ }
119
+
120
+ function saveCustomVerifyRetryCounts(s: AutoSession): void {
121
+ const retryCounts = s.verificationRetryCount;
122
+ const filePath = customVerifyRetryStatePath(s);
123
+
124
+ try {
125
+ if (!retryCounts || retryCounts.size === 0) {
126
+ unlinkSync(filePath);
127
+ return;
128
+ }
129
+ mkdirSync(customVerifyRetryStateDir(s), { recursive: true });
130
+ atomicWriteSync(filePath, JSON.stringify({
131
+ counts: Object.fromEntries(retryCounts),
132
+ updatedAt: new Date().toISOString(),
133
+ }) + "\n");
134
+ } catch (err) {
135
+ const code = err && typeof err === "object" && "code" in err ? (err as { code?: string }).code : undefined;
136
+ if (code !== "ENOENT") {
137
+ debugLog("autoLoop", { phase: "save-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
138
+ }
139
+ }
140
+ }
141
+
77
142
  // ── Memory pressure monitoring (#3331) ──────────────────────────────────
78
143
  // Check heap usage every N iterations and trigger graceful shutdown before
79
144
  // the OS OOM killer sends SIGKILL. The threshold is 90% of the V8 heap
80
145
  // limit (--max-old-space-size or default ~1.5-4GB depending on platform).
81
146
  const MEMORY_CHECK_INTERVAL = 5; // check every 5 iterations
82
147
  const MEMORY_PRESSURE_THRESHOLD = 0.85; // 85% of heap limit
148
+ const MAX_CUSTOM_ENGINE_VERIFY_RETRIES = 3;
83
149
 
84
150
  type DispatchContract = "legacy-direct" | "uok-scheduler";
85
151
 
@@ -429,16 +495,51 @@ export async function autoLoop(
429
495
  break;
430
496
  }
431
497
  if (verifyResult === "retry") {
432
- debugLog("autoLoop", { phase: "custom-engine-verify-retry", iteration, unitId: iterData.unitId });
498
+ const recoveryKey = `${iterData.unitType}/${iterData.unitId}`;
499
+ const retryCounts = hydrateCustomVerifyRetryCounts(s);
500
+ const attempts = (retryCounts.get(recoveryKey) ?? 0) + 1;
501
+ retryCounts.set(recoveryKey, attempts);
502
+ saveCustomVerifyRetryCounts(s);
503
+ debugLog("autoLoop", { phase: "custom-engine-verify-retry", iteration, unitId: iterData.unitId, attempts });
433
504
  deps.uokObserver?.onPhaseResult("custom-engine", "retry", {
434
505
  unitType: iterData.unitType,
435
506
  unitId: iterData.unitId,
507
+ attempts,
436
508
  });
509
+ if (attempts > MAX_CUSTOM_ENGINE_VERIFY_RETRIES) {
510
+ const recovery = await policy.recover(iterData.unitType, iterData.unitId, { basePath: s.basePath });
511
+ if (recovery.outcome === "pause") {
512
+ await deps.pauseAuto(ctx, pi);
513
+ finishTurn("paused", "manual-attention", recovery.reason ?? "custom-engine-verify-retry-exhausted");
514
+ break;
515
+ }
516
+ if (recovery.outcome === "skip") {
517
+ await deps.stopAuto(
518
+ ctx,
519
+ pi,
520
+ recovery.reason ??
521
+ `Custom workflow verification for ${iterData.unitId} requested skip after retry exhaustion, but the custom engine cannot reconcile skipped steps.`,
522
+ );
523
+ finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
524
+ break;
525
+ }
526
+ const exhaustedReason =
527
+ `Custom workflow verification for ${iterData.unitId} requested retry ${attempts} times without passing.`;
528
+ await deps.stopAuto(
529
+ ctx,
530
+ pi,
531
+ recovery.outcome === "stop" && recovery.reason ? recovery.reason : exhaustedReason,
532
+ );
533
+ finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
534
+ break;
535
+ }
437
536
  finishTurn("retry");
438
537
  continue;
439
538
  }
440
539
 
441
540
  // Verification passed — mark step complete
541
+ s.verificationRetryCount?.delete(`${iterData.unitType}/${iterData.unitId}`);
542
+ saveCustomVerifyRetryCounts(s);
442
543
  debugLog("autoLoop", { phase: "custom-engine-reconcile", iteration, unitId: iterData.unitId });
443
544
  const reconcileResult = await engine.reconcile(engineState, {
444
545
  unitType: iterData.unitType,
@@ -590,6 +691,7 @@ export async function autoLoop(
590
691
  consecutiveCooldowns = 0;
591
692
  recentErrorMessages.length = 0;
592
693
  deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
694
+ saveStuckState(s.basePath, loopState); // persist across session restarts (#4382)
593
695
  debugLog("autoLoop", { phase: "iteration-complete", iteration });
594
696
  finishTurn("completed");
595
697
  } catch (loopErr) {
@@ -51,10 +51,11 @@ import { getEligibleSlices } from "../slice-parallel-eligibility.js";
51
51
  import { startSliceParallel } from "../slice-parallel-orchestrator.js";
52
52
  import { isDbAvailable, getMilestoneSlices } from "../gsd-db.js";
53
53
  import type { MinimalModelRegistry } from "../context-budget.js";
54
- import { ensurePlanV2Graph } from "../uok/plan-v2.js";
54
+ import { ensurePlanV2Graph, isMissingFinalizedContextResult } from "../uok/plan-v2.js";
55
55
  import { resolveUokFlags } from "../uok/flags.js";
56
56
  import { UokGateRunner } from "../uok/gate-runner.js";
57
- import { resetEvidence } from "../safety/evidence-collector.js";
57
+ import { resetEvidence, loadEvidenceFromDisk } from "../safety/evidence-collector.js";
58
+ import { parseUnitId } from "../unit-id.js";
58
59
  import { createCheckpoint, cleanupCheckpoint, rollbackToCheckpoint } from "../safety/git-checkpoint.js";
59
60
  import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
60
61
  import {
@@ -80,7 +81,11 @@ export function resetSessionTimeoutState(): void {
80
81
  * Exported for testing as _resolveReportBasePath.
81
82
  */
82
83
  export function _resolveReportBasePath(s: Pick<AutoSession, "originalBasePath" | "basePath">): string {
83
- return s.originalBasePath || s.basePath;
84
+ // Strip /.gsd/worktrees/ suffix when basePath is itself a worktree path and
85
+ // originalBasePath is falsy — prevents reports landing in the worktree (#3729).
86
+ const resolved = s.originalBasePath || s.basePath;
87
+ const markerIdx = resolved.indexOf("/.gsd/worktrees/");
88
+ return markerIdx !== -1 ? resolved.slice(0, markerIdx) : resolved;
84
89
  }
85
90
 
86
91
  /**
@@ -91,7 +96,12 @@ export function _resolveReportBasePath(s: Pick<AutoSession, "originalBasePath" |
91
96
  export function _resolveDispatchGuardBasePath(
92
97
  s: Pick<AutoSession, "originalBasePath" | "basePath">,
93
98
  ): string {
94
- return s.originalBasePath || s.basePath;
99
+ // Strip /.gsd/worktrees/ suffix when basePath is itself a worktree path and
100
+ // originalBasePath is falsy — prevents guard checks running against the
101
+ // worktree instead of the project root (#3729).
102
+ const resolved = s.originalBasePath || s.basePath;
103
+ const markerIdx = resolved.indexOf("/.gsd/worktrees/");
104
+ return markerIdx !== -1 ? resolved.slice(0, markerIdx) : resolved;
95
105
  }
96
106
 
97
107
  const PLAN_V2_GATE_PHASES: ReadonlySet<Phase> = new Set([
@@ -410,27 +420,41 @@ export async function runPreDispatch(
410
420
  const compiled = ensurePlanV2Graph(s.basePath, state);
411
421
  if (!compiled.ok) {
412
422
  const reason = compiled.reason ?? "Plan v2 compilation failed";
423
+ if (isMissingFinalizedContextResult(compiled)) {
424
+ await runPreDispatchGate({
425
+ gateId: "plan-v2-gate",
426
+ gateType: "policy",
427
+ outcome: "pass",
428
+ failureClass: "none",
429
+ rationale: "plan v2 missing context recovery deferred to dispatch",
430
+ findings: reason,
431
+ milestoneId: state.activeMilestone?.id ?? undefined,
432
+ });
433
+ } else {
434
+ await runPreDispatchGate({
435
+ gateId: "plan-v2-gate",
436
+ gateType: "policy",
437
+ outcome: "manual-attention",
438
+ failureClass: "manual-attention",
439
+ rationale: "plan v2 compile gate failed",
440
+ findings: reason,
441
+ milestoneId: state.activeMilestone?.id ?? undefined,
442
+ });
443
+ ctx.ui.notify(`Plan gate failed-closed: ${reason}\n\nIf this keeps happening, try: /gsd doctor heal`, "error");
444
+ await deps.pauseAuto(ctx, pi);
445
+ return { action: "break", reason: "plan-v2-gate-failed" };
446
+ }
447
+ }
448
+ if (compiled.ok) {
413
449
  await runPreDispatchGate({
414
450
  gateId: "plan-v2-gate",
415
451
  gateType: "policy",
416
- outcome: "manual-attention",
417
- failureClass: "manual-attention",
418
- rationale: "plan v2 compile gate failed",
419
- findings: reason,
452
+ outcome: "pass",
453
+ failureClass: "none",
454
+ rationale: "plan v2 compile gate passed",
420
455
  milestoneId: state.activeMilestone?.id ?? undefined,
421
456
  });
422
- ctx.ui.notify(`Plan gate failed-closed: ${reason}`, "error");
423
- await deps.pauseAuto(ctx, pi);
424
- return { action: "break", reason: "plan-v2-gate-failed" };
425
457
  }
426
- await runPreDispatchGate({
427
- gateId: "plan-v2-gate",
428
- gateType: "policy",
429
- outcome: "pass",
430
- failureClass: "none",
431
- rationale: "plan v2 compile gate passed",
432
- milestoneId: state.activeMilestone?.id ?? undefined,
433
- });
434
458
  }
435
459
  deps.syncCmuxSidebar(prefs, state);
436
460
  let mid = state.activeMilestone?.id;
@@ -545,6 +569,12 @@ export async function runPreDispatch(
545
569
  loopState.stuckRecoveryAttempts = 0;
546
570
 
547
571
  // Worktree lifecycle on milestone transition — merge current, enter next
572
+ // #2909: preflight — warn + stash dirty working tree before merge
573
+ const preflightTransition = deps.preflightCleanRoot(
574
+ s.originalBasePath || s.basePath,
575
+ s.currentMilestoneId!,
576
+ ctx.ui.notify.bind(ctx.ui),
577
+ );
548
578
  try {
549
579
  deps.resolver.mergeAndExit(s.currentMilestoneId!, ctx.ui);
550
580
  } catch (mergeErr) {
@@ -566,6 +596,14 @@ export async function runPreDispatch(
566
596
  await deps.stopAuto(ctx, pi, `Merge error on milestone ${s.currentMilestoneId}: ${String(mergeErr)}`);
567
597
  return { action: "break", reason: "merge-failed" };
568
598
  }
599
+ // #2909: postflight — restore stashed changes after successful merge
600
+ if (preflightTransition.stashPushed) {
601
+ deps.postflightPopStash(
602
+ s.originalBasePath || s.basePath,
603
+ s.currentMilestoneId!,
604
+ ctx.ui.notify.bind(ctx.ui),
605
+ );
606
+ }
569
607
 
570
608
  // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
571
609
 
@@ -644,6 +682,12 @@ export async function runPreDispatch(
644
682
  if (incomplete.length === 0 && state.registry.length > 0) {
645
683
  // All milestones complete — merge milestone branch before stopping
646
684
  if (s.currentMilestoneId) {
685
+ // #2909: preflight — warn + stash dirty working tree before merge
686
+ const preflightAllComplete = deps.preflightCleanRoot(
687
+ s.originalBasePath || s.basePath,
688
+ s.currentMilestoneId,
689
+ ctx.ui.notify.bind(ctx.ui),
690
+ );
647
691
  try {
648
692
  deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
649
693
  // Prevent stopAuto from attempting the same merge (#2645)
@@ -665,6 +709,14 @@ export async function runPreDispatch(
665
709
  await deps.stopAuto(ctx, pi, `Merge error on milestone ${s.currentMilestoneId}: ${String(mergeErr)}`);
666
710
  return { action: "break", reason: "merge-failed" };
667
711
  }
712
+ // #2909: postflight — restore stashed changes after successful merge
713
+ if (preflightAllComplete.stashPushed) {
714
+ deps.postflightPopStash(
715
+ s.originalBasePath || s.basePath,
716
+ s.currentMilestoneId,
717
+ ctx.ui.notify.bind(ctx.ui),
718
+ );
719
+ }
668
720
 
669
721
  // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
670
722
  }
@@ -758,6 +810,12 @@ export async function runPreDispatch(
758
810
  if (state.phase === "complete") {
759
811
  // Milestone merge on complete (before closeout so branch state is clean)
760
812
  if (s.currentMilestoneId) {
813
+ // #2909: preflight — warn + stash dirty working tree before merge
814
+ const preflightComplete = deps.preflightCleanRoot(
815
+ s.originalBasePath || s.basePath,
816
+ s.currentMilestoneId,
817
+ ctx.ui.notify.bind(ctx.ui),
818
+ );
761
819
  try {
762
820
  deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
763
821
  // Prevent stopAuto from attempting the same merge (#2645)
@@ -779,6 +837,14 @@ export async function runPreDispatch(
779
837
  await deps.stopAuto(ctx, pi, `Merge error on milestone ${s.currentMilestoneId}: ${String(mergeErr)}`);
780
838
  return { action: "break", reason: "merge-failed" };
781
839
  }
840
+ // #2909: postflight — restore stashed changes after successful merge
841
+ if (preflightComplete.stashPushed) {
842
+ deps.postflightPopStash(
843
+ s.originalBasePath || s.basePath,
844
+ s.currentMilestoneId,
845
+ ctx.ui.notify.bind(ctx.ui),
846
+ );
847
+ }
782
848
 
783
849
  // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
784
850
  }
@@ -1385,6 +1451,14 @@ export async function runUnitPhase(
1385
1451
  );
1386
1452
  if (safetyConfig.enabled && safetyConfig.evidence_collection) {
1387
1453
  resetEvidence();
1454
+ // Restore persisted evidence so session-restart resumes don't produce
1455
+ // false-positive "no bash calls" warnings (Bug #4385).
1456
+ if (s.basePath && unitType === "execute-task") {
1457
+ const { milestone: eMid, slice: eSid, task: eTid } = parseUnitId(unitId);
1458
+ if (eMid && eSid && eTid) {
1459
+ loadEvidenceFromDisk(s.basePath, eMid, eSid, eTid);
1460
+ }
1461
+ }
1388
1462
  }
1389
1463
  // Only checkpoint code-executing units (not lifecycle/planning units)
1390
1464
  if (safetyConfig.enabled && safetyConfig.checkpoints && unitType === "execute-task") {
@@ -1620,9 +1694,23 @@ export async function runUnitPhase(
1620
1694
 
1621
1695
  if (unitResult.status === "cancelled") {
1622
1696
  const errorCategory = unitResult.errorContext?.category;
1623
- // Provider-error pause: pauseAuto already handled cleanup and scheduled
1624
- // recovery. Don't hard-stop just break out of the loop (#2762).
1697
+ // Provider-error pause: agent_end recovery normally pauses before this
1698
+ // branch. Provider readiness failures happen before dispatch, so pause here
1699
+ // if nothing upstream already did.
1625
1700
  if (errorCategory === "provider") {
1701
+ if (!s.paused) {
1702
+ const detail = unitResult.errorContext?.message ?? `Provider unavailable for ${unitType} ${unitId}`;
1703
+ await pauseAutoForProviderError(
1704
+ ctx.ui,
1705
+ detail,
1706
+ () => deps.pauseAuto(ctx, pi),
1707
+ {
1708
+ isRateLimit: false,
1709
+ isTransient: Boolean(unitResult.errorContext?.isTransient),
1710
+ retryAfterMs: unitResult.errorContext?.retryAfterMs,
1711
+ },
1712
+ );
1713
+ }
1626
1714
  await emitCancelledUnitEnd(ic, unitType, unitId, unitStartSeq, unitResult.errorContext);
1627
1715
  debugLog("autoLoop", { phase: "exit", reason: "provider-pause", isTransient: unitResult.errorContext?.isTransient });
1628
1716
  return { action: "break", reason: "provider-pause" };
@@ -1928,6 +2016,20 @@ export async function runFinalize(
1928
2016
  debugLog("autoLoop", { phase: "sidecar-artifact-retry-skipped", iteration: ic.iteration });
1929
2017
  } else {
1930
2018
  // s.pendingVerificationRetry was set by postUnitPreVerification.
2019
+ // Emit a dedicated journal event so forensics can distinguish bounded
2020
+ // verification retries from genuine stuck-loop dispatch repetitions (#4540).
2021
+ const retryInfo = s.pendingVerificationRetry;
2022
+ deps.emitJournalEvent({
2023
+ ts: new Date().toISOString(),
2024
+ flowId: ic.flowId,
2025
+ seq: ic.nextSeq(),
2026
+ eventType: "artifact-verification-retry",
2027
+ data: {
2028
+ unitType: preUnitSnapshot?.type,
2029
+ unitId: retryInfo?.unitId,
2030
+ attempt: retryInfo?.attempt,
2031
+ },
2032
+ });
1931
2033
  // Continue the loop — next iteration will inject the retry context into the prompt.
1932
2034
  debugLog("autoLoop", { phase: "artifact-verification-retry", iteration: ic.iteration });
1933
2035
  return { action: "continue" };
@@ -11,6 +11,7 @@
11
11
  import type { UnitResult, AgentEndEvent, ErrorContext } from "./types.js";
12
12
  import type { AutoSession } from "./session.js";
13
13
  import { debugLog } from "../debug-logger.js";
14
+ import { bumpTurnGeneration } from "./turn-epoch.js";
14
15
 
15
16
  // ─── Per-unit one-shot promise state ────────────────────────────────────────
16
17
  //
@@ -68,6 +69,24 @@ export function isSessionSwitchInFlight(): boolean {
68
69
  return _sessionSwitchInFlight;
69
70
  }
70
71
 
72
+ // ─── bumpAndResolveSynthetic ────────────────────────────────────────────────
73
+
74
+ /**
75
+ * Bump the turn epoch and synthetically resolve the pending unit promise —
76
+ * the exact sequence timeout recovery must perform when it advances past a
77
+ * timed-out unit. Using this helper enforces the invariant "bump iff we are
78
+ * actually superseding the turn" so a future caller cannot resolve without
79
+ * bumping (orphaned writes leak) or bump without resolving (next turn starts
80
+ * already stale).
81
+ *
82
+ * NOT to be used for steering retries that keep the same turn alive — those
83
+ * do not supersede the turn and must not bump.
84
+ */
85
+ export function bumpAndResolveSynthetic(reason: string): void {
86
+ bumpTurnGeneration(reason);
87
+ resolveAgentEnd({ messages: [], _synthetic: reason } as unknown as AgentEndEvent);
88
+ }
89
+
71
90
  // ─── resolveAgentEndCancelled ─────────────────────────────────────────────────
72
91
 
73
92
  /**
@@ -79,6 +98,12 @@ export function isSessionSwitchInFlight(): boolean {
79
98
  */
80
99
  export function resolveAgentEndCancelled(errorContext?: ErrorContext): void {
81
100
  if (_currentResolve) {
101
+ // Cancellation supersedes the in-flight turn the same way timeout
102
+ // recovery does — bump the turn epoch so any lingering writes from the
103
+ // cancelled turn drop themselves.
104
+ bumpTurnGeneration(
105
+ `cancelled:${errorContext?.category ?? "unknown"}`,
106
+ );
82
107
  debugLog("resolveAgentEndCancelled", { status: "resolving-cancelled" });
83
108
  const r = _currentResolve;
84
109
  _currentResolve = null;
@@ -97,6 +122,10 @@ export function _resetPendingResolve(): void {
97
122
  _sessionSwitchInFlight = false;
98
123
  }
99
124
 
125
+ export function _hasPendingResolveForTest(): boolean {
126
+ return _currentResolve !== null;
127
+ }
128
+
100
129
  /**
101
130
  * No-op for backward compatibility with tests that previously set the
102
131
  * active session. The module no longer holds a session reference.
@@ -9,7 +9,11 @@ import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
9
9
  import type { AutoSession } from "./session.js";
10
10
  import { NEW_SESSION_TIMEOUT_MS } from "./session.js";
11
11
  import type { UnitResult } from "./types.js";
12
- import { _setCurrentResolve, _setSessionSwitchInFlight } from "./resolve.js";
12
+ import { _clearCurrentResolve, _setCurrentResolve, _setSessionSwitchInFlight } from "./resolve.js";
13
+ import {
14
+ getCurrentTurnGeneration,
15
+ runWithTurnGeneration,
16
+ } from "./turn-epoch.js";
13
17
  import { debugLog } from "../debug-logger.js";
14
18
  import { logWarning, logError } from "../workflow-logger.js";
15
19
  import { resolveAutoSupervisorConfig } from "../preferences.js";
@@ -42,16 +46,25 @@ export async function runUnit(
42
46
  let sessionResult: { cancelled: boolean };
43
47
  let sessionTimeoutHandle: ReturnType<typeof setTimeout> | undefined;
44
48
  const mySessionSwitchGeneration = ++sessionSwitchGeneration;
49
+ // #3731: Cancellation controller for newSession(). When the session-creation
50
+ // timeout fires, we abort this controller so that the still-in-flight
51
+ // newSession() discards itself after await this.abort() completes, preventing
52
+ // it from capturing the (now-root) process.cwd() and rebuilding the tool
53
+ // runtime with the wrong cwd.
54
+ const sessionAbortController = new AbortController();
45
55
  _setSessionSwitchInFlight(true);
46
56
  try {
47
- const sessionPromise = s.cmdCtx!.newSession().finally(() => {
57
+ const sessionPromise = s.cmdCtx!.newSession({ abortSignal: sessionAbortController.signal }).finally(() => {
48
58
  if (sessionSwitchGeneration === mySessionSwitchGeneration) {
49
59
  _setSessionSwitchInFlight(false);
50
60
  }
51
61
  });
52
62
  const timeoutPromise = new Promise<{ cancelled: true }>((resolve) => {
53
63
  sessionTimeoutHandle = setTimeout(
54
- () => resolve({ cancelled: true }),
64
+ () => {
65
+ sessionAbortController.abort();
66
+ resolve({ cancelled: true });
67
+ },
55
68
  NEW_SESSION_TIMEOUT_MS,
56
69
  );
57
70
  });
@@ -118,6 +131,43 @@ export async function runUnit(
118
131
  logWarning("engine", "Failed to chdir to basePath before dispatch", { basePath: s.basePath, error: String(e) });
119
132
  }
120
133
 
134
+ // ── Provider request-readiness pre-check (#4555) ──
135
+ // Verify the provider can accept requests before dispatching. If the token
136
+ // has expired since bootstrap, return cancelled immediately so the unit is
137
+ // not wasted on a guaranteed 401.
138
+ {
139
+ const provider = s.currentUnitModel?.provider ?? ctx.model?.provider;
140
+ const registry = (ctx as any).modelRegistry;
141
+
142
+ if (provider && registry != null && typeof registry.isProviderRequestReady === "function") {
143
+ let ready = false;
144
+ try {
145
+ ready = registry.isProviderRequestReady(provider);
146
+ } catch {
147
+ ready = false;
148
+ }
149
+
150
+ if (!ready) {
151
+ _clearCurrentResolve();
152
+ return {
153
+ status: "cancelled",
154
+ errorContext: {
155
+ message: `Provider ${provider} is not request-ready (login/token expired)`,
156
+ category: "provider",
157
+ isTransient: false,
158
+ },
159
+ };
160
+ }
161
+ }
162
+ }
163
+
164
+ // ── Capture turn generation for stale-write detection ──
165
+ // Any write site reached via the sendMessage → tool-call → await chain
166
+ // below sees this generation via AsyncLocalStorage. If a timeout recovery
167
+ // or cancellation bumps the generation while this turn is in flight, those
168
+ // writes see themselves as stale and self-drop.
169
+ const capturedTurnGen = getCurrentTurnGeneration();
170
+
121
171
  // ── Send the prompt ──
122
172
  debugLog("runUnit", { phase: "send-message", unitType, unitId });
123
173
 
@@ -141,7 +191,9 @@ export async function runUnit(
141
191
  resolve({ status: "cancelled", errorContext: { message: "Unit hard timeout — supervision may have failed", category: "timeout", isTransient: true } });
142
192
  }, UNIT_HARD_TIMEOUT_MS);
143
193
  });
144
- const result = await Promise.race([unitPromise, timeoutResult]);
194
+ const result = await runWithTurnGeneration(capturedTurnGen, () =>
195
+ Promise.race([unitPromise, timeoutResult]),
196
+ );
145
197
  if (unitTimeoutHandle) clearTimeout(unitTimeoutHandle);
146
198
  debugLog("runUnit", {
147
199
  phase: "agent-end-received",
@@ -64,6 +64,15 @@ export interface SidecarItem {
64
64
  captureId?: string;
65
65
  }
66
66
 
67
+ export interface PreExecFailure {
68
+ /** Milestone/slice that failed (e.g. "M001/S02"). */
69
+ unitId: string;
70
+ /** Verbatim blocking check strings from the failed gate run. */
71
+ blockingFindings: string[];
72
+ /** Condensed gate verdict excerpt for context (status + rationale). */
73
+ verdictExcerpt: string;
74
+ }
75
+
67
76
  // ─── Constants ───────────────────────────────────────────────────────────────
68
77
 
69
78
  export const MAX_UNIT_DISPATCHES = 3;
@@ -139,6 +148,18 @@ export class AutoSession {
139
148
  // ── Sidecar queue ─────────────────────────────────────────────────────
140
149
  sidecarQueue: SidecarItem[] = [];
141
150
 
151
+ // ── Pre-exec gate failure context (#4551) ───────────────────────────
152
+ /**
153
+ * Persisted when a pre-execution gate fails on a plan-slice or refine-slice
154
+ * unit. The planning → plan-slice dispatch rule reads this field and injects
155
+ * the failure details into the next re-dispatch prompt so the LLM can fix the
156
+ * specific issues instead of producing an identical plan.
157
+ *
158
+ * Cleared after it has been consumed (injected into the prompt) to avoid
159
+ * stale context bleeding into unrelated slices.
160
+ */
161
+ lastPreExecFailure: PreExecFailure | null = null;
162
+
142
163
  // ── Tool invocation errors (#2883) ──────────────────────────────────
143
164
  /** Set when a GSD tool execution ends with isError due to malformed/truncated
144
165
  * JSON arguments. Checked by postUnitPreVerification to break retry loops. */
@@ -199,7 +220,12 @@ export class AutoSession {
199
220
  }
200
221
 
201
222
  get lockBasePath(): string {
202
- return this.originalBasePath || this.basePath;
223
+ // Prefer originalBasePath (project root); fall back to basePath.
224
+ // Strip /.gsd/worktrees/ suffix if basePath is itself a worktree path
225
+ // to avoid reading/writing the lock inside the worktree (#3729).
226
+ const resolved = this.originalBasePath || this.basePath;
227
+ const markerIdx = resolved.indexOf("/.gsd/worktrees/");
228
+ return markerIdx !== -1 ? resolved.slice(0, markerIdx) : resolved;
203
229
  }
204
230
 
205
231
  reset(): void {
@@ -267,6 +293,7 @@ export class AutoSession {
267
293
  this.sidecarQueue = [];
268
294
  this.rewriteAttemptCount = 0;
269
295
  this.consecutiveCompleteBootstraps = 0;
296
+ this.lastPreExecFailure = null;
270
297
  this.lastToolInvocationError = null;
271
298
  this.lastGitActionFailure = null;
272
299
  this.lastGitActionStatus = null;