gsd-pi 2.77.0-dev.c9c8932c6 → 2.77.0-dev.cfd69e714

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 (708) hide show
  1. package/README.md +1 -1
  2. package/dist/claude-cli-check.js +5 -1
  3. package/dist/cli-web-branch.d.ts +1 -0
  4. package/dist/cli-web-branch.js +3 -0
  5. package/dist/cli.js +24 -2
  6. package/dist/headless.js +49 -4
  7. package/dist/provider-migrations.d.ts +18 -0
  8. package/dist/provider-migrations.js +14 -0
  9. package/dist/resource-loader.d.ts +40 -0
  10. package/dist/resource-loader.js +32 -13
  11. package/dist/resources/extensions/browser-tools/capture.js +9 -0
  12. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  13. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  14. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  15. package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
  16. package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
  17. package/dist/resources/extensions/claude-code-cli/readiness.js +5 -1
  18. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +495 -27
  19. package/dist/resources/extensions/github-sync/templates.js +103 -0
  20. package/dist/resources/extensions/google-search/index.js +3 -2
  21. package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
  22. package/dist/resources/extensions/gsd/auto/loop.js +124 -2
  23. package/dist/resources/extensions/gsd/auto/phases.js +57 -39
  24. package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
  25. package/dist/resources/extensions/gsd/auto/run-unit.js +10 -2
  26. package/dist/resources/extensions/gsd/auto/session.js +6 -2
  27. package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
  28. package/dist/resources/extensions/gsd/auto-dispatch.js +166 -29
  29. package/dist/resources/extensions/gsd/auto-loop.js +1 -1
  30. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  31. package/dist/resources/extensions/gsd/auto-post-unit.js +181 -64
  32. package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
  33. package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
  34. package/dist/resources/extensions/gsd/auto-start.js +107 -29
  35. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
  36. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  37. package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
  38. package/dist/resources/extensions/gsd/auto-worktree.js +180 -34
  39. package/dist/resources/extensions/gsd/auto.js +80 -21
  40. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
  41. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  42. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +5 -6
  43. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  44. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  45. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
  46. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  47. package/dist/resources/extensions/gsd/component-types.js +69 -0
  48. package/dist/resources/extensions/gsd/context-store.js +23 -7
  49. package/dist/resources/extensions/gsd/detection.js +49 -1
  50. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
  51. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  52. package/dist/resources/extensions/gsd/file-lock.js +49 -9
  53. package/dist/resources/extensions/gsd/forensics.js +106 -0
  54. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  55. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  56. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  57. package/dist/resources/extensions/gsd/git-service.js +127 -2
  58. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  59. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  60. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
  61. package/dist/resources/extensions/gsd/guided-flow.js +39 -13
  62. package/dist/resources/extensions/gsd/journal.js +17 -2
  63. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  64. package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
  65. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  66. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  67. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  68. package/dist/resources/extensions/gsd/model-router.js +6 -0
  69. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  70. package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
  71. package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
  72. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  73. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  74. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  75. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  76. package/dist/resources/extensions/gsd/reports.js +5 -4
  77. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  78. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  79. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  80. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  81. package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
  82. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  83. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  84. package/dist/resources/extensions/gsd/state.js +69 -58
  85. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  86. package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
  87. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
  88. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
  89. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  90. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  91. package/dist/resources/extensions/gsd/uok/audit.js +18 -2
  92. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  93. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  94. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  95. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  96. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  97. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  98. package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
  99. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  100. package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
  101. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  102. package/dist/resources/extensions/gsd/worktree-manager.js +86 -8
  103. package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
  104. package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
  105. package/dist/resources/extensions/mcp-client/auth.js +10 -1
  106. package/dist/resources/extensions/mcp-client/index.js +121 -10
  107. package/dist/resources/extensions/ollama/index.js +5 -1
  108. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  109. package/dist/resources/skills/create-skill/SKILL.md +2 -2
  110. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  111. package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  112. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  113. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  114. package/dist/web/standalone/.next/BUILD_ID +1 -1
  115. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  116. package/dist/web/standalone/.next/build-manifest.json +3 -3
  117. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  118. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  195. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  197. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  207. package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
  208. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  209. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  211. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  213. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  214. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  215. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  216. package/dist/web/standalone/.next/static/chunks/{webpack-1832629448831fdc.js → webpack-2e68521d7c82f7c2.js} +1 -1
  217. package/package.json +4 -5
  218. package/packages/daemon/src/logger.ts +4 -3
  219. package/packages/mcp-server/README.md +3 -3
  220. package/packages/mcp-server/dist/env-writer.d.ts +1 -0
  221. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
  222. package/packages/mcp-server/dist/env-writer.js +74 -6
  223. package/packages/mcp-server/dist/env-writer.js.map +1 -1
  224. package/packages/mcp-server/dist/server.d.ts +24 -0
  225. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  226. package/packages/mcp-server/dist/server.js +111 -87
  227. package/packages/mcp-server/dist/server.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/src/env-writer.test.ts +79 -1
  232. package/packages/mcp-server/src/env-writer.ts +76 -6
  233. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  234. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  235. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  236. package/packages/mcp-server/src/server.ts +158 -105
  237. package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
  238. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  239. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  240. package/packages/native/package.json +1 -1
  241. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  242. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  243. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  244. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  245. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  246. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  247. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  248. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  249. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  250. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  251. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  252. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  253. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  254. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  255. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  256. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  257. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  258. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  259. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  260. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  261. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  262. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  263. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  264. package/packages/pi-ai/dist/models.test.js +36 -11
  265. package/packages/pi-ai/dist/models.test.js.map +1 -1
  266. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  267. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  268. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  269. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  270. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  271. package/packages/pi-ai/src/models.test.ts +48 -11
  272. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  273. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  274. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  276. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  278. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
  280. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +21 -16
  282. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
  284. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
  285. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
  286. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
  287. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  288. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  290. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  292. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  294. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  296. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  299. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  301. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  303. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  304. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  305. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  306. package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
  307. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
  309. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
  311. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  313. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  315. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  317. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  318. package/packages/pi-coding-agent/dist/index.js +1 -0
  319. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
  321. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
  323. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  325. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  326. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
  328. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
  330. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
  332. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  333. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  334. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
  335. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  336. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  337. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  338. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  339. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  340. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  341. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  342. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  343. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  344. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  345. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  346. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  347. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  349. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  350. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  351. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  352. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  353. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  354. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  355. package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
  356. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +24 -17
  357. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  358. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  359. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  360. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  361. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  362. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  363. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  364. package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
  365. package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
  366. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  367. package/packages/pi-coding-agent/src/index.ts +1 -0
  368. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
  369. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
  370. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  371. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
  372. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
  373. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
  374. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  375. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  376. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  377. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  378. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  379. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  380. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  381. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  382. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  383. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  384. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +51 -6
  385. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  386. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  387. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  388. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  389. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  390. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  391. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  392. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  393. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  394. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  395. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  396. package/packages/pi-tui/dist/components/editor.js +19 -0
  397. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  398. package/packages/pi-tui/dist/components/image.test.js +6 -5
  399. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  400. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  401. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  402. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  403. package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
  404. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  405. package/packages/pi-tui/dist/stdin-buffer.js +20 -0
  406. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  407. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  408. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  409. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +62 -6
  410. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  411. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  412. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  413. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  414. package/packages/pi-tui/src/components/editor.ts +22 -0
  415. package/packages/pi-tui/src/components/image.test.ts +10 -5
  416. package/packages/pi-tui/src/editor-component.ts +3 -0
  417. package/packages/pi-tui/src/stdin-buffer.ts +26 -0
  418. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  419. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  420. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  421. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  422. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  423. package/scripts/install.js +15 -1
  424. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  425. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  426. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  427. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  428. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  429. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  430. package/src/resources/extensions/claude-code-cli/readiness.ts +5 -1
  431. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +532 -29
  432. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +941 -91
  433. package/src/resources/extensions/github-sync/templates.ts +151 -0
  434. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  435. package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
  436. package/src/resources/extensions/google-search/index.ts +3 -2
  437. package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
  438. package/src/resources/extensions/gsd/auto/loop.ts +142 -2
  439. package/src/resources/extensions/gsd/auto/phases.ts +62 -38
  440. package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
  441. package/src/resources/extensions/gsd/auto/run-unit.ts +16 -2
  442. package/src/resources/extensions/gsd/auto/session.ts +7 -2
  443. package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
  444. package/src/resources/extensions/gsd/auto-dispatch.ts +176 -29
  445. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  446. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  447. package/src/resources/extensions/gsd/auto-post-unit.ts +193 -73
  448. package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
  449. package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
  450. package/src/resources/extensions/gsd/auto-start.ts +127 -9
  451. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
  452. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  453. package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
  454. package/src/resources/extensions/gsd/auto-worktree.ts +190 -31
  455. package/src/resources/extensions/gsd/auto.ts +95 -23
  456. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
  457. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  458. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -6
  459. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  460. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  461. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
  462. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  463. package/src/resources/extensions/gsd/component-types.ts +362 -0
  464. package/src/resources/extensions/gsd/context-store.ts +25 -8
  465. package/src/resources/extensions/gsd/detection.ts +58 -1
  466. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
  467. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  468. package/src/resources/extensions/gsd/file-lock.ts +84 -11
  469. package/src/resources/extensions/gsd/forensics.ts +118 -1
  470. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  471. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  472. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  473. package/src/resources/extensions/gsd/git-service.ts +150 -2
  474. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  475. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  476. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
  477. package/src/resources/extensions/gsd/guided-flow.ts +57 -14
  478. package/src/resources/extensions/gsd/journal.ts +38 -3
  479. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  480. package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
  481. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  482. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  483. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  484. package/src/resources/extensions/gsd/model-router.ts +6 -0
  485. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  486. package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
  487. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
  488. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  489. package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  490. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  491. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  492. package/src/resources/extensions/gsd/reports.ts +5 -4
  493. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  494. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  495. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  496. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  497. package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
  498. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  499. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  500. package/src/resources/extensions/gsd/state.ts +76 -66
  501. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  502. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  503. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
  504. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  505. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  506. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +135 -285
  507. package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
  508. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  509. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  510. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  511. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  512. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
  513. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
  514. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
  515. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
  516. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  517. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
  518. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
  519. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
  520. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
  521. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  522. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  523. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  524. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  525. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  526. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
  527. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  528. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  529. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  530. package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
  531. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
  532. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  533. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
  534. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  535. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  536. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  537. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  538. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
  539. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
  540. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
  541. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
  542. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  543. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  544. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  545. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
  546. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
  547. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  548. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  549. package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
  550. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
  551. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  552. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  553. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
  554. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  555. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  556. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
  557. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  558. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
  559. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  560. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  561. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  562. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  563. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  564. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  565. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
  566. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  567. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
  568. package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
  569. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +47 -0
  570. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  571. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
  572. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  573. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  574. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  575. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  576. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
  577. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  578. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
  579. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
  580. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  581. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  582. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
  583. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
  584. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
  585. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +54 -41
  586. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +213 -0
  587. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
  588. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
  589. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
  590. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  591. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  592. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  593. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  594. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
  595. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  596. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
  597. package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
  598. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  599. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  600. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  601. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
  602. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  603. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  604. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  605. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  606. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
  607. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
  608. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  609. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
  610. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  611. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
  612. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  613. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
  614. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  615. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
  616. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
  617. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  618. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  619. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
  620. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  621. package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
  622. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  623. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  624. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  625. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
  626. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
  627. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  628. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  629. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  630. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  631. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  632. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  633. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  634. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  635. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
  636. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  637. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
  638. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
  639. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  640. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  641. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  642. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  643. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  644. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  645. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  646. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  647. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
  648. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  649. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  650. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  651. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  652. package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
  653. package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
  654. package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
  655. package/src/resources/extensions/gsd/types.ts +3 -3
  656. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  657. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  658. package/src/resources/extensions/gsd/uok/audit.ts +20 -2
  659. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  660. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  661. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  662. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  663. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  664. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  665. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  666. package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
  667. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  668. package/src/resources/extensions/gsd/workflow-logger.ts +22 -3
  669. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  670. package/src/resources/extensions/gsd/worktree-manager.ts +109 -7
  671. package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
  672. package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
  673. package/src/resources/extensions/mcp-client/auth.ts +12 -1
  674. package/src/resources/extensions/mcp-client/index.ts +132 -11
  675. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  676. package/src/resources/extensions/ollama/index.ts +5 -1
  677. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  678. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  679. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  680. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  681. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  682. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  683. package/src/resources/skills/create-skill/SKILL.md +2 -2
  684. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  685. package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  686. package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  687. package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
  688. package/dist/web/standalone/.next/static/chunks/2826.d445fb428ef41fa1.js +0 -9
  689. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  690. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  691. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  692. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  693. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  694. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
  695. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  696. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  697. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  698. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  699. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  700. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  701. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
  702. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  703. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  704. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  705. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
  706. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
  707. /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → SvCJDZPQW104bR1KnBQg1}/_buildManifest.js +0 -0
  708. /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → SvCJDZPQW104bR1KnBQg1}/_ssgManifest.js +0 -0
@@ -77,20 +77,21 @@ export function clearInFlightTools() {
77
77
  }
78
78
  // ─── Tool invocation error classification (#2883) ────────────────────────
79
79
  /**
80
- * Patterns that indicate a tool invocation failed due to malformed or truncated
81
- * JSON arguments — as opposed to a normal business-logic error from the tool
82
- * handler. When these errors occur, retrying the same unit will produce the same
83
- * failure, so the retry loop must be broken.
80
+ * Patterns that indicate a tool invocation failed deterministically before
81
+ * useful work could be completed — as opposed to a normal business-logic error
82
+ * from the tool handler. When these errors occur, retrying the same unit will
83
+ * produce the same failure, so the retry loop must be broken.
84
84
  */
85
85
  const TOOL_INVOCATION_ERROR_RE = /Validation failed for tool|Expected ',' or '\}'(?: after property value)?(?: in JSON)?|Unexpected end of JSON|Unexpected token.*in JSON/i;
86
+ const DETERMINISTIC_POLICY_ERROR_RE = /(?:^|\b)(?:HARD BLOCK:|Blocked: \/gsd queue is a planning tool|Direct writes to \.gsd\/STATE\.md and \.gsd\/gsd\.db are blocked|This is a mechanical gate)/i;
86
87
  /**
87
- * Returns true if the error message indicates a tool invocation failure due to
88
- * malformed/truncated arguments (as opposed to a normal tool execution error).
88
+ * Returns true if the error message indicates a deterministic invocation or
89
+ * policy failure (as opposed to a normal tool execution error).
89
90
  */
90
91
  export function isToolInvocationError(errorMsg) {
91
92
  if (!errorMsg)
92
93
  return false;
93
- return TOOL_INVOCATION_ERROR_RE.test(errorMsg);
94
+ return TOOL_INVOCATION_ERROR_RE.test(errorMsg) || isDeterministicPolicyError(errorMsg);
94
95
  }
95
96
  /**
96
97
  * Returns true if the error message indicates the tool was skipped because
@@ -102,3 +103,42 @@ export function isQueuedUserMessageSkip(errorMsg) {
102
103
  return false;
103
104
  return /^Skipped due to queued user message\.?$/i.test(errorMsg.trim());
104
105
  }
106
+ // ─── Deterministic policy error classification (#4973, #4974) ──────────────
107
+ /**
108
+ * Known deterministic policy error substrings. Each entry is a stable string
109
+ * that will appear in the tool error text content when the corresponding
110
+ * policy gate fires. Retrying these errors will always produce the same outcome.
111
+ *
112
+ * Add new entries here as new deterministic gates are introduced. Do NOT use
113
+ * regex — explicit substrings keep the list auditable.
114
+ */
115
+ export const DETERMINISTIC_POLICY_ERROR_STRINGS = [
116
+ // gsd_summary_save write-gate: CONTEXT artifact blocked pending depth verification (#4973).
117
+ // Matches the fallback text in workflow-tool-executors.ts and the verbose reason
118
+ // from shouldBlockContextArtifactSaveInSnapshot at write-gate.ts:432-442.
119
+ "context write blocked",
120
+ "CONTEXT without depth verification",
121
+ // Raw write tool gate (#4973): shouldBlockContextWrite at write-gate.ts:390-399 emits
122
+ // "Cannot write to milestone CONTEXT.md without depth verification." for direct
123
+ // write tool calls to *-CONTEXT.md paths (different code path than gsd_summary_save).
124
+ "CONTEXT.md without depth verification",
125
+ ];
126
+ /**
127
+ * Returns true if the error message indicates a deterministic policy gate
128
+ * blocked the tool call before execution. Retrying the same unit without
129
+ * changing behavior will hit the same gate, so auto-mode should pause instead
130
+ * of re-dispatching.
131
+ *
132
+ * Combines the regex-based gate set from #4974 (HARD BLOCK / queue planning /
133
+ * STATE.md / mechanical gate) and the substring-based set from #4973 (context
134
+ * write block / CONTEXT depth verification). Both branches landed on main
135
+ * independently and their parallel `isDeterministicPolicyError` declarations
136
+ * were not deduplicated at merge — this consolidated form preserves both
137
+ * matchers under a single export.
138
+ */
139
+ export function isDeterministicPolicyError(errorMsg) {
140
+ if (!errorMsg)
141
+ return false;
142
+ return (DETERMINISTIC_POLICY_ERROR_RE.test(errorMsg) ||
143
+ DETERMINISTIC_POLICY_ERROR_STRINGS.some(s => errorMsg.includes(s)));
144
+ }
@@ -20,9 +20,18 @@ export async function closeoutUnit(ctx, basePath, unitType, unitId, startedAt, o
20
20
  const { buildMemoryLLMCall, extractMemoriesFromUnit } = await import('./memory-extractor.js');
21
21
  const llmCallFn = buildMemoryLLMCall(ctx);
22
22
  if (llmCallFn) {
23
- extractMemoriesFromUnit(activityFile, unitType, unitId, llmCallFn).catch((err) => {
23
+ // Awaited: a fire-and-forget here lets memory-extractor writes land in
24
+ // .gsd/ after closeoutUnit returns but before the milestone merge
25
+ // runs, which made the working tree appear dirty to `git merge
26
+ // --squash` (root cause class of #4704). Completion latency is now
27
+ // bounded by the extractor's LLM call, which is the acceptable price
28
+ // for not racing the merge boundary.
29
+ try {
30
+ await extractMemoriesFromUnit(activityFile, unitType, unitId, llmCallFn);
31
+ }
32
+ catch (err) {
24
33
  logWarning("engine", `memory extraction failed for ${unitType}/${unitId}: ${err.message}`);
25
- });
34
+ }
26
35
  }
27
36
  }
28
37
  catch (err) { /* non-fatal */
@@ -9,7 +9,7 @@ import { existsSync, cpSync, readFileSync, readdirSync, mkdirSync, realpathSync,
9
9
  import { isAbsolute, join, sep as pathSep } from "node:path";
10
10
  import { homedir } from "node:os";
11
11
  import { GSDError, GSD_IO_ERROR, GSD_GIT_ERROR } from "./errors.js";
12
- import { reconcileWorktreeDb, isDbAvailable, getMilestone, getMilestoneSlices, } from "./gsd-db.js";
12
+ import { reconcileWorktreeDb, isDbAvailable, getMilestone, getMilestoneSlices, closeDatabase, openDatabase, getDbPath, } from "./gsd-db.js";
13
13
  import { atomicWriteSync } from "./atomic-write.js";
14
14
  import { execFileSync } from "node:child_process";
15
15
  import { safeCopy, safeCopyRecursive } from "./safe-fs.js";
@@ -45,6 +45,67 @@ const ROOT_STATE_FILES = [
45
45
  // Back-sync (worktree → main) must NEVER overwrite the project root's copy
46
46
  // because the project root is authoritative for preferences (#2684).
47
47
  ];
48
+ /**
49
+ * Pop a stash entry by tracking the unique marker embedded in its message so
50
+ * concurrent stash operations against the same project root cannot cause us to
51
+ * pop the wrong entry.
52
+ *
53
+ * If `stashMarker` is null or no longer present in the stash list (e.g. a
54
+ * concurrent process popped/dropped it), leaves the stash list untouched and
55
+ * returns null.
56
+ *
57
+ * Throws on pop failure so callers can handle conflict cases the same way
58
+ * they would with the prior `git stash pop` form. When throwing after a
59
+ * targeted pop attempt, the error is annotated with the targeted stash ref.
60
+ *
61
+ * (Issue #4980 HIGH-6)
62
+ */
63
+ function popStashByRef(basePath, stashMarker) {
64
+ let popArg = null;
65
+ if (stashMarker) {
66
+ try {
67
+ const list = execFileSync("git", ["stash", "list", "--format=%gd%x00%s"], {
68
+ cwd: basePath,
69
+ stdio: ["ignore", "pipe", "pipe"],
70
+ encoding: "utf-8",
71
+ }).trim().split("\n").filter(Boolean);
72
+ for (const entry of list) {
73
+ const [ref, subject] = entry.split("\0");
74
+ if (ref && subject?.includes(stashMarker)) {
75
+ popArg = ref;
76
+ break;
77
+ }
78
+ }
79
+ }
80
+ catch (err) {
81
+ logWarning("worktree", `stash list lookup failed; leaving stash untouched: ${err instanceof Error ? err.message : String(err)}`);
82
+ }
83
+ }
84
+ if (!popArg) {
85
+ logWarning("worktree", "recorded stash entry could not be resolved; skipping automatic pop");
86
+ return null;
87
+ }
88
+ try {
89
+ execFileSync("git", ["stash", "pop", popArg], {
90
+ cwd: basePath,
91
+ stdio: ["ignore", "pipe", "pipe"],
92
+ encoding: "utf-8",
93
+ });
94
+ }
95
+ catch (err) {
96
+ if (err && typeof err === "object") {
97
+ err.stashRef = popArg;
98
+ }
99
+ throw err;
100
+ }
101
+ return popArg;
102
+ }
103
+ function stashRefFromError(err) {
104
+ if (!err || typeof err !== "object")
105
+ return null;
106
+ const stashRef = err.stashRef;
107
+ return typeof stashRef === "string" && stashRef.length > 0 ? stashRef : null;
108
+ }
48
109
  /**
49
110
  * Check if two filesystem paths resolve to the same real location.
50
111
  * Returns false if either path cannot be resolved (e.g. doesn't exist).
@@ -828,6 +889,27 @@ export function enterBranchModeForMilestone(basePath, milestoneId) {
828
889
  const startPoint = integrationBranch ??
829
890
  validatedPrefBranch ??
830
891
  nativeDetectMainBranch(basePath);
892
+ // TOCTOU ancestry guard (Issue #4980 HIGH-3).
893
+ //
894
+ // The outer `branchExists` check at line 1012 is racy: a concurrent
895
+ // process (parallel-orchestrator worker, side-by-side `gsd` instance,
896
+ // or manual `git branch` invocation) may have created the branch with
897
+ // real commits between that check and this point. `nativeBranchForceReset`
898
+ // does `git branch -f`, which silently overwrites the branch ref —
899
+ // orphaning any commits not reachable from `startPoint`. Re-check
900
+ // immediately before the destructive call and refuse if the branch
901
+ // suddenly exists with non-ancestor commits.
902
+ //
903
+ // Note: under single-threaded execution this is rarely reached, but it
904
+ // is NOT dead code — it is the only barrier against a TOCTOU-induced
905
+ // commit loss in this code path.
906
+ const concurrentlyCreated = nativeBranchExists(basePath, branch);
907
+ if (concurrentlyCreated &&
908
+ !nativeIsAncestor(basePath, branch, startPoint)) {
909
+ throw new GSDError(GSD_GIT_ERROR, `Branch "${branch}" was created concurrently with commits not reachable from "${startPoint}". ` +
910
+ `Refusing to force-reset — would orphan prior work. ` +
911
+ `Resume the existing milestone or run \`git branch -D ${branch}\` to discard.`);
912
+ }
831
913
  // nativeBranchForceReset creates (or resets) branch at startPoint,
832
914
  // then checkout switches HEAD to it.
833
915
  nativeBranchForceReset(basePath, branch, startPoint);
@@ -1345,7 +1427,17 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1345
1427
  clearProjectRootStateFiles(originalBasePath_, milestoneId);
1346
1428
  // 5. Checkout integration branch (skip if already current — avoids git error
1347
1429
  // when main is already checked out in the project-root worktree, #757)
1430
+ //
1431
+ // Refuse to proceed if the project root is in detached HEAD state. Silently
1432
+ // running `nativeCheckoutBranch(mainBranch)` on a detached HEAD would
1433
+ // abandon the user's deliberately-checked-out commit (mid-bisect, reviewing
1434
+ // a tag, CI checkout-sha) without warning. (Issue #4980 HIGH-10)
1348
1435
  const currentBranchAtBase = nativeGetCurrentBranch(originalBasePath_);
1436
+ if (!currentBranchAtBase || currentBranchAtBase.length === 0) {
1437
+ process.chdir(previousCwd);
1438
+ throw new GSDError(GSD_GIT_ERROR, `Project root is in detached HEAD state — cannot perform milestone merge. ` +
1439
+ `Checkout an integration branch (e.g. \`git checkout ${mainBranch}\`) before resuming.`);
1440
+ }
1349
1441
  if (currentBranchAtBase !== mainBranch) {
1350
1442
  nativeCheckoutBranch(originalBasePath_, mainBranch);
1351
1443
  }
@@ -1433,26 +1525,53 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1433
1525
  const milestonesDir = join(gsdRoot(originalBasePath_), "milestones");
1434
1526
  const shelterDir = join(gsdRoot(originalBasePath_), ".milestone-shelter");
1435
1527
  const shelteredDirs = [];
1528
+ let shelterRestored = false;
1436
1529
  // Helper: restore sheltered milestone directories (#2505).
1437
1530
  // Called on both success and error paths to ensure queued CONTEXT files
1438
- // are never permanently lost.
1531
+ // are never permanently lost. Idempotent — the error path may fire after
1532
+ // the success path has already restored and removed the shelter dir; a
1533
+ // second call is a no-op instead of logging a misleading "shelter restore
1534
+ // failed: ENOENT" error for shelter sources that were cleaned up legitimately.
1439
1535
  const restoreShelter = () => {
1536
+ if (shelterRestored)
1537
+ return;
1538
+ shelterRestored = true;
1440
1539
  if (shelteredDirs.length === 0)
1441
1540
  return;
1541
+ let restoreFailed = false;
1442
1542
  for (const dirName of shelteredDirs) {
1543
+ const src = join(shelterDir, dirName);
1544
+ // If the shelter source is missing the restore cannot proceed for this
1545
+ // entry. Distinguish "legitimately missing" (shelter dir removed by a
1546
+ // prior successful restore or never copied) from a surprising ENOENT
1547
+ // inside an otherwise-populated shelter.
1548
+ if (!existsSync(src)) {
1549
+ logWarning("worktree", `shelter source missing for ${dirName}; skipping restore (shelter already cleaned or entry never staged)`);
1550
+ continue;
1551
+ }
1443
1552
  try {
1444
1553
  mkdirSync(milestonesDir, { recursive: true });
1445
- cpSync(join(shelterDir, dirName), join(milestonesDir, dirName), { recursive: true, force: true });
1554
+ cpSync(src, join(milestonesDir, dirName), { recursive: true, force: true });
1446
1555
  }
1447
1556
  catch (err) { /* best-effort */
1448
- logError("worktree", `shelter restore failed: ${err instanceof Error ? err.message : String(err)}`);
1557
+ restoreFailed = true;
1558
+ logError("worktree", `shelter restore failed (${dirName}): ${err instanceof Error ? err.message : String(err)}`);
1449
1559
  }
1450
1560
  }
1451
- try {
1452
- rmSync(shelterDir, { recursive: true, force: true });
1561
+ // Preserve the shelter if any per-entry restore failed — it is the only
1562
+ // surviving copy of the queued milestone dirs (sources were deleted during
1563
+ // shelter). Deleting it here would permanently lose those files (#2505).
1564
+ if (restoreFailed) {
1565
+ logWarning("worktree", `shelter retained at ${shelterDir} — manual recovery required for unrestored entries`);
1566
+ return;
1453
1567
  }
1454
- catch (err) { /* best-effort */
1455
- logWarning("worktree", `shelter cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
1568
+ if (existsSync(shelterDir)) {
1569
+ try {
1570
+ rmSync(shelterDir, { recursive: true, force: true });
1571
+ }
1572
+ catch (err) { /* best-effort */
1573
+ logWarning("worktree", `shelter cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
1574
+ }
1456
1575
  }
1457
1576
  };
1458
1577
  try {
@@ -1491,7 +1610,27 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1491
1610
  // entries (e.g. a gitignored `.gsd` symlink under ADR-002) (#4573).
1492
1611
  // Queued CONTEXT files under `.gsd/milestones/*` are already sheltered
1493
1612
  // in step 7 above, so they won't be swept into the stash.
1613
+ // On Windows, SQLite holds mandatory file locks on the gsd.db WAL/SHM
1614
+ // sidecars while the connection is open. `git stash --include-untracked`
1615
+ // walks those files and fails with EBUSY (#4704). Close the DB before
1616
+ // stashing so Windows releases the handles; reopen after. No-op on
1617
+ // POSIX, where advisory locks don't block git.
1618
+ const needsDbCycle = process.platform === "win32" && isDbAvailable();
1619
+ const dbPathToReopen = needsDbCycle ? getDbPath() : null;
1620
+ if (needsDbCycle) {
1621
+ try {
1622
+ closeDatabase();
1623
+ }
1624
+ catch (err) {
1625
+ logWarning("worktree", `pre-stash db close failed: ${err instanceof Error ? err.message : String(err)}`);
1626
+ }
1627
+ }
1494
1628
  let stashed = false;
1629
+ // Embed a unique marker in the stash message so subsequent pop/drop targets
1630
+ // the entry we created, not whatever happens to be at stash@{0} (concurrent
1631
+ // milestone merges share the project-root stash list and can shift positions).
1632
+ // (Issue #4980 HIGH-6)
1633
+ let stashMarker = null;
1495
1634
  try {
1496
1635
  const status = execFileSync("git", ["status", "--porcelain"], {
1497
1636
  cwd: originalBasePath_,
@@ -1499,7 +1638,8 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1499
1638
  encoding: "utf-8",
1500
1639
  }).trim();
1501
1640
  if (status) {
1502
- execFileSync("git", ["stash", "push", "--include-untracked", "-m", `gsd: pre-merge stash for ${milestoneId}`], { cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
1641
+ stashMarker = `gsd-pre-merge:${milestoneId}:${process.pid}:${Date.now()}:${process.hrtime.bigint().toString(36)}`;
1642
+ execFileSync("git", ["stash", "push", "--include-untracked", "-m", `gsd: pre-merge stash for ${milestoneId} [${stashMarker}]`], { cwd: originalBasePath_, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
1503
1643
  stashed = true;
1504
1644
  }
1505
1645
  }
@@ -1508,6 +1648,14 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1508
1648
  // report the dirty tree if it fails.
1509
1649
  logWarning("worktree", `git stash failed: ${err instanceof Error ? err.message : String(err)}`);
1510
1650
  }
1651
+ if (needsDbCycle && dbPathToReopen) {
1652
+ try {
1653
+ openDatabase(dbPathToReopen);
1654
+ }
1655
+ catch (err) {
1656
+ logWarning("worktree", `post-stash db reopen failed: ${err instanceof Error ? err.message : String(err)}`);
1657
+ }
1658
+ }
1511
1659
  // 7b. Clean up stale merge state before attempting squash merge (#2912).
1512
1660
  // A leftover MERGE_HEAD (from a previous failed merge, libgit2 native path,
1513
1661
  // or interrupted operation) causes `git merge --squash` to refuse with
@@ -1547,11 +1695,7 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1547
1695
  // Pop stash before throwing so local work is not lost.
1548
1696
  if (stashed) {
1549
1697
  try {
1550
- execFileSync("git", ["stash", "pop"], {
1551
- cwd: originalBasePath_,
1552
- stdio: ["ignore", "pipe", "pipe"],
1553
- encoding: "utf-8",
1554
- });
1698
+ popStashByRef(originalBasePath_, stashMarker);
1555
1699
  }
1556
1700
  catch (err) { /* stash pop conflict is non-fatal */
1557
1701
  logWarning("worktree", `git stash pop failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -1619,11 +1763,7 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1619
1763
  // Pop stash before throwing so local work is not lost (#2151).
1620
1764
  if (stashed) {
1621
1765
  try {
1622
- execFileSync("git", ["stash", "pop"], {
1623
- cwd: originalBasePath_,
1624
- stdio: ["ignore", "pipe", "pipe"],
1625
- encoding: "utf-8",
1626
- });
1766
+ popStashByRef(originalBasePath_, stashMarker);
1627
1767
  }
1628
1768
  catch (err) { /* stash pop conflict is non-fatal */
1629
1769
  logWarning("worktree", `git stash pop failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -1666,14 +1806,12 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1666
1806
  // or the commit content. Conflict on pop is non-fatal — the stash entry is
1667
1807
  // preserved and the user can resolve manually with `git stash pop`.
1668
1808
  if (stashed) {
1809
+ let stashRefForDrop = null;
1669
1810
  try {
1670
- execFileSync("git", ["stash", "pop"], {
1671
- cwd: originalBasePath_,
1672
- stdio: ["ignore", "pipe", "pipe"],
1673
- encoding: "utf-8",
1674
- });
1811
+ stashRefForDrop = popStashByRef(originalBasePath_, stashMarker);
1675
1812
  }
1676
1813
  catch (e) {
1814
+ stashRefForDrop = stashRefFromError(e);
1677
1815
  logWarning("worktree", `git stash pop failed, attempting conflict resolution: ${e.message}`);
1678
1816
  // Stash pop after squash merge can conflict on .gsd/ state files that
1679
1817
  // diverged between branches. Left unresolved, these UU entries block
@@ -1701,25 +1839,33 @@ export function mergeMilestoneToMain(originalBasePath_, milestoneId, roadmapCont
1701
1839
  }
1702
1840
  }
1703
1841
  }
1704
- if (nonGsdUU.length === 0) {
1842
+ if (gsdUU.length > 0 && nonGsdUU.length === 0) {
1705
1843
  // All conflicts were .gsd/ files — safe to drop the stash
1706
- try {
1707
- execFileSync("git", ["stash", "drop"], {
1708
- cwd: originalBasePath_,
1709
- stdio: ["ignore", "pipe", "pipe"],
1710
- encoding: "utf-8",
1711
- });
1844
+ if (stashRefForDrop) {
1845
+ try {
1846
+ execFileSync("git", ["stash", "drop", stashRefForDrop], {
1847
+ cwd: originalBasePath_,
1848
+ stdio: ["ignore", "pipe", "pipe"],
1849
+ encoding: "utf-8",
1850
+ });
1851
+ }
1852
+ catch (err) { /* stash may already be consumed */
1853
+ logWarning("worktree", `git stash drop failed: ${err instanceof Error ? err.message : String(err)}`);
1854
+ }
1712
1855
  }
1713
- catch (err) { /* stash may already be consumed */
1714
- logWarning("worktree", `git stash drop failed: ${err instanceof Error ? err.message : String(err)}`);
1856
+ else {
1857
+ logWarning("worktree", "recorded stash entry could not be resolved; skipping automatic drop");
1715
1858
  }
1716
1859
  }
1717
- else {
1860
+ else if (nonGsdUU.length > 0) {
1718
1861
  // Non-.gsd conflicts remain — leave stash for manual resolution
1719
1862
  logWarning("reconcile", "Stash pop conflict on non-.gsd files after merge", {
1720
1863
  files: nonGsdUU.join(", "),
1721
1864
  });
1722
1865
  }
1866
+ else {
1867
+ logWarning("worktree", "git stash pop failed without resolvable conflict files; leaving stash for manual recovery");
1868
+ }
1723
1869
  }
1724
1870
  }
1725
1871
  // 9a-iii. Restore sheltered queued milestone directories (#2505).
@@ -24,9 +24,9 @@ import { acquireSessionLock, getSessionLockStatus, releaseSessionLock, updateSes
24
24
  import { resolveAutoSupervisorConfig, loadEffectiveGSDPreferences, getIsolationMode, } from "./preferences.js";
25
25
  import { sendDesktopNotification } from "./notifications.js";
26
26
  import { getBudgetAlertLevel, getNewBudgetAlertLevel, getBudgetEnforcementAction, } from "./auto-budget.js";
27
- import { markToolStart as _markToolStart, markToolEnd as _markToolEnd, getOldestInFlightToolAgeMs as _getOldestInFlightToolAgeMs, clearInFlightTools, isToolInvocationError, isQueuedUserMessageSkip, } from "./auto-tool-tracking.js";
27
+ import { markToolStart as _markToolStart, markToolEnd as _markToolEnd, getOldestInFlightToolAgeMs as _getOldestInFlightToolAgeMs, clearInFlightTools, isToolInvocationError, isQueuedUserMessageSkip, isDeterministicPolicyError, } from "./auto-tool-tracking.js";
28
28
  import { closeoutUnit } from "./auto-unit-closeout.js";
29
- import { selectAndApplyModel, resolveModelId } from "./auto-model-selection.js";
29
+ import { selectAndApplyModel, resolveModelId, clearToolBaseline } from "./auto-model-selection.js";
30
30
  import { resetRoutingHistory, recordOutcome } from "./routing-history.js";
31
31
  import { resetHookState, runPreDispatchHooks, restoreHookState, clearPersistedHookState, } from "./post-unit-hooks.js";
32
32
  import { runGSDDoctor, rebuildState } from "./doctor.js";
@@ -51,6 +51,7 @@ import { pruneQueueOrder } from "./queue-order.js";
51
51
  import { startCommandPolling as _startCommandPolling, isRemoteConfigured } from "../remote-questions/manager.js";
52
52
  import { debugLog, isDebugEnabled, writeDebugSummary } from "./debug-logger.js";
53
53
  import { reconcileMergeState, } from "./auto-recovery.js";
54
+ import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
54
55
  import { resolveDispatch, DISPATCH_RULES } from "./auto-dispatch.js";
55
56
  import { getErrorMessage } from "./error-utils.js";
56
57
  import { recoverFailedMigration } from "./migrate-external.js";
@@ -81,7 +82,7 @@ import { WorktreeResolver, } from "./worktree-resolver.js";
81
82
  import { reorderForCaching } from "./prompt-ordering.js";
82
83
  // ─── Session State ─────────────────────────────────────────────────────────
83
84
  import { AutoSession, } from "./auto/session.js";
84
- export { MAX_UNIT_DISPATCHES, STUB_RECOVERY_THRESHOLD, MAX_LIFETIME_DISPATCHES, NEW_SESSION_TIMEOUT_MS, } from "./auto/session.js";
85
+ export { STUB_RECOVERY_THRESHOLD, NEW_SESSION_TIMEOUT_MS, } from "./auto/session.js";
85
86
  // ── ENCAPSULATION INVARIANT ─────────────────────────────────────────────────
86
87
  // ALL mutable auto-mode state lives in the AutoSession class (auto/session.ts).
87
88
  // This file must NOT declare module-level `let` or `var` variables for state.
@@ -162,6 +163,13 @@ function normalizeSessionFilePath(raw) {
162
163
  return null;
163
164
  return candidate;
164
165
  }
166
+ function synthesizePausedSessionRecovery(basePath, unitType, unitId, sessionFile) {
167
+ const activityDir = join(gsdRoot(basePath), "activity");
168
+ return synthesizeCrashRecovery(basePath, unitType, unitId, sessionFile, activityDir);
169
+ }
170
+ export function _synthesizePausedSessionRecoveryForTest(basePath, unitType, unitId, sessionFile) {
171
+ return synthesizePausedSessionRecovery(basePath, unitType, unitId, sessionFile);
172
+ }
165
173
  export function startAutoDetached(ctx, pi, base, verboseMode, options) {
166
174
  void startAuto(ctx, pi, base, verboseMode, options).catch((err) => {
167
175
  const message = getErrorMessage(err);
@@ -274,6 +282,10 @@ export function getAutoDashboardData() {
274
282
  export function isAutoActive() {
275
283
  return s.active;
276
284
  }
285
+ /** Test-only seam for validating auto-mode guards (#4704). Do not use in production code. */
286
+ export function _setAutoActiveForTest(active) {
287
+ s.active = active;
288
+ }
277
289
  export function isAutoPaused() {
278
290
  return s.paused;
279
291
  }
@@ -315,13 +327,15 @@ export function markToolEnd(toolCallId) {
315
327
  /**
316
328
  * Record a tool invocation error on the current session (#2883).
317
329
  * Called from tool_execution_end when a GSD tool fails with isError.
318
- * Only stores the error if it matches the tool-invocation-error pattern
319
- * (malformed/truncated JSON), not normal business-logic errors.
330
+ * Stores the error if it matches:
331
+ * - tool-invocation-error pattern (malformed/truncated JSON)
332
+ * - queued-user-message skip pattern
333
+ * - deterministic policy rejection (#4973, e.g. context_write_blocked)
320
334
  */
321
335
  export function recordToolInvocationError(toolName, errorMsg) {
322
336
  if (!s.active)
323
337
  return;
324
- if (isToolInvocationError(errorMsg) || isQueuedUserMessageSkip(errorMsg)) {
338
+ if (isToolInvocationError(errorMsg) || isQueuedUserMessageSkip(errorMsg) || isDeterministicPolicyError(errorMsg)) {
325
339
  s.lastToolInvocationError = `${toolName}: ${errorMsg}`;
326
340
  }
327
341
  }
@@ -523,6 +537,40 @@ export async function stopAuto(ctx, pi, reason) {
523
537
  return;
524
538
  const loadedPreferences = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences;
525
539
  const reasonSuffix = reason ? ` — ${reason}` : "";
540
+ // #4764 — telemetry: record the exit reason and whether the current milestone
541
+ // was merged before we entered stopAuto. This is the producer-side signal for
542
+ // the #4761 orphan class: milestoneMerged=false + currentMilestoneId present
543
+ // is exactly the pattern that strands work.
544
+ try {
545
+ const { emitAutoExit } = await import("./worktree-telemetry.js");
546
+ // Normalize the free-form reason to a closed set so the telemetry
547
+ // aggregator buckets stably. Raw detail is preserved in the phases.ts
548
+ // notification and the notify'd error string.
549
+ const rawReason = reason ?? "stop";
550
+ const normalizedReason = rawReason.startsWith("Blocked:")
551
+ ? "blocked"
552
+ : rawReason.startsWith("Merge conflict")
553
+ ? "merge-conflict"
554
+ : rawReason.startsWith("Merge error") || rawReason.startsWith("Merge failed")
555
+ ? "merge-failed"
556
+ : rawReason.startsWith("slice-merge-conflict")
557
+ ? "slice-merge-conflict"
558
+ : rawReason === "All milestones complete"
559
+ ? "all-complete"
560
+ : rawReason === "No active milestone"
561
+ ? "no-active-milestone"
562
+ : rawReason === "stop" || rawReason === "pause"
563
+ ? rawReason
564
+ : "other";
565
+ emitAutoExit(s.originalBasePath || s.basePath, {
566
+ reason: normalizedReason,
567
+ milestoneId: s.currentMilestoneId ?? undefined,
568
+ milestoneMerged: s.milestoneMergedInPhases === true,
569
+ });
570
+ }
571
+ catch (err) {
572
+ logWarning("engine", `auto-exit telemetry failed: ${err instanceof Error ? err.message : String(err)}`);
573
+ }
526
574
  try {
527
575
  // ── Step 1: Timers and locks ──
528
576
  try {
@@ -774,6 +822,12 @@ export async function stopAuto(ctx, pi, reason) {
774
822
  initHealthWidget(ctx);
775
823
  restoreProjectRootEnv();
776
824
  restoreMilestoneLockEnv();
825
+ // Drop the active-tool baseline so a subsequent /gsd auto run on the
826
+ // same `pi` instance recaptures from the live tool set rather than
827
+ // restoring this session's snapshot and silently undoing any tool
828
+ // changes the user made between sessions (#4959 / CodeRabbit).
829
+ if (pi)
830
+ clearToolBaseline(pi);
777
831
  // Reset all session state in one call
778
832
  s.reset();
779
833
  }
@@ -1021,6 +1075,15 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1021
1075
  debugLog("startAuto", { phase: "already-active", skipping: true });
1022
1076
  return;
1023
1077
  }
1078
+ // On a *fresh* start, drop any stale active-tool baseline left by a prior
1079
+ // auto session that didn't run stopAuto cleanly. Skip on resume: pauseAuto
1080
+ // leaves the last provider-trimmed active tools in place, so clearing here
1081
+ // would let the next selectAndApplyModel recapture that already-narrowed
1082
+ // set as the new baseline — exactly the cross-unit poisoning this PR is
1083
+ // fixing (#4959 / CodeRabbit Major). The pre-pause baseline survives in
1084
+ // the WeakMap keyed by `pi`.
1085
+ if (!s.paused)
1086
+ clearToolBaseline(pi);
1024
1087
  const requestedStepMode = options?.step ?? false;
1025
1088
  const interruptedAssessment = options?.interrupted ?? null;
1026
1089
  if (options?.milestoneLock !== undefined) {
@@ -1080,7 +1143,16 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1080
1143
  // Validate the milestone still exists and isn't already complete (#1664).
1081
1144
  const mDir = resolveMilestonePath(base, meta.milestoneId);
1082
1145
  const summaryFile = resolveMilestoneFile(base, meta.milestoneId, "SUMMARY");
1083
- if (!mDir || summaryFile) {
1146
+ let summaryIsTerminal = false;
1147
+ if (summaryFile) {
1148
+ try {
1149
+ summaryIsTerminal = classifyMilestoneSummaryContent(readFileSync(summaryFile, "utf-8")) !== "failure";
1150
+ }
1151
+ catch {
1152
+ summaryIsTerminal = false;
1153
+ }
1154
+ }
1155
+ if (!mDir || summaryIsTerminal) {
1084
1156
  try {
1085
1157
  unlinkSync(pausedPath);
1086
1158
  }
@@ -1169,18 +1241,6 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1169
1241
  ctx.ui.notify(`Cannot resume: ${resumeLock.reason}`, "error");
1170
1242
  return;
1171
1243
  }
1172
- // Lock acquired — now safe to delete the pause file
1173
- if (s.pausedSessionFile) {
1174
- try {
1175
- unlinkSync(s.pausedSessionFile);
1176
- }
1177
- catch (err) {
1178
- if (err.code !== "ENOENT") {
1179
- logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
1180
- }
1181
- }
1182
- s.pausedSessionFile = null;
1183
- }
1184
1244
  s.paused = false;
1185
1245
  s.active = true;
1186
1246
  s.verbose = verboseMode;
@@ -1269,8 +1329,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
1269
1329
  }
1270
1330
  invalidateAllCaches();
1271
1331
  if (s.pausedSessionFile) {
1272
- const activityDir = join(gsdRoot(s.basePath), "activity");
1273
- const recovery = synthesizeCrashRecovery(s.basePath, s.currentUnit?.type ?? s.pausedUnitType ?? "unknown", s.currentUnit?.id ?? s.pausedUnitId ?? "unknown", s.pausedSessionFile ?? undefined, activityDir);
1332
+ const recovery = synthesizePausedSessionRecovery(s.basePath, s.currentUnit?.type ?? s.pausedUnitType ?? "unknown", s.currentUnit?.id ?? s.pausedUnitId ?? "unknown", s.pausedSessionFile);
1274
1333
  if (recovery && recovery.trace.toolCallCount > 0) {
1275
1334
  s.pendingCrashRecovery = recovery.prompt;
1276
1335
  ctx.ui.notify(`Recovered ${recovery.trace.toolCallCount} tool calls from paused session. Resuming with context.`, "info");
@@ -1,5 +1,6 @@
1
1
  import { logWarning } from "../workflow-logger.js";
2
2
  import { checkAutoStartAfterDiscuss, maybeHandleReadyPhraseWithoutFiles, maybeHandleEmptyIntentTurn, resetEmptyTurnCounter, } from "../guided-flow.js";
3
+ import { clearPathCache } from "../paths.js";
3
4
  import { getAutoDashboardData, getAutoModeStartModel, isAutoActive, pauseAuto, setCurrentDispatchedModelId } from "../auto.js";
4
5
  import { getNextFallbackModel, resolveModelWithFallbacksForUnit } from "../preferences.js";
5
6
  import { pauseAutoForProviderError } from "../provider-error-pause.js";
@@ -11,7 +12,15 @@ import { classifyError, createRetryState, resetRetryState, isTransient, } from "
11
12
  import { blockModel, isModelBlocked } from "../blocked-models.js";
12
13
  const retryState = createRetryState();
13
14
  const MAX_NETWORK_RETRIES = 2;
14
- const MAX_TRANSIENT_AUTO_RESUMES = 8;
15
+ /**
16
+ * Cap on auto-resume attempts for sustained transient-provider errors.
17
+ *
18
+ * Exported so tests assert against the shared constant instead of
19
+ * regex-scraping the source literal (see #4837). Raising this value to
20
+ * handle longer provider overloads should update the single constant; the
21
+ * test in provider-errors.test.ts consumes it directly.
22
+ */
23
+ export const MAX_TRANSIENT_AUTO_RESUMES = 8;
15
24
  /**
16
25
  * Reset the module-level retry state so a resumed auto-session starts fresh.
17
26
  * Called by provider-error-resume.ts before startAuto() — without this, the
@@ -49,6 +58,15 @@ async function pauseTransientWithBackoff(cls, pi, ctx, errorDetail, isRateLimit)
49
58
  });
50
59
  }
51
60
  export async function handleAgentEnd(pi, event, ctx) {
61
+ // #4648 — Invalidate the directory-listing cache before any artifact-existence
62
+ // checks. The LLM may have written milestone files (CONTEXT.md, ROADMAP.md,
63
+ // PROJECT.md, REQUIREMENTS.md) via tool calls during the turn that just
64
+ // ended. `paths.ts` caches readdir() results without a TTL, so without this
65
+ // flush, `resolveMilestoneFile` returns the pre-write listing and the guards
66
+ // below (`checkAutoStartAfterDiscuss` and `maybeHandleReadyPhraseWithoutFiles`)
67
+ // falsely report files as missing — producing a spurious "ready signal
68
+ // rejected" loop even though the files are on disk.
69
+ clearPathCache();
52
70
  if (checkAutoStartAfterDiscuss()) {
53
71
  clearDiscussionFlowState();
54
72
  return;