gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0-dev.aeeb2ca00

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 (545) hide show
  1. package/README.md +53 -17
  2. package/dist/claude-cli-check.js +46 -10
  3. package/dist/headless.js +49 -4
  4. package/dist/resource-loader.d.ts +40 -0
  5. package/dist/resource-loader.js +32 -13
  6. package/dist/resources/extensions/browser-tools/capture.js +9 -0
  7. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  8. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  9. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  10. package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
  11. package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
  12. package/dist/resources/extensions/claude-code-cli/readiness.js +72 -16
  13. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
  14. package/dist/resources/extensions/github-sync/templates.js +103 -0
  15. package/dist/resources/extensions/google-search/index.js +3 -2
  16. package/dist/resources/extensions/gsd/auto/loop.js +124 -2
  17. package/dist/resources/extensions/gsd/auto/phases.js +57 -39
  18. package/dist/resources/extensions/gsd/auto/session.js +6 -2
  19. package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
  20. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  21. package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
  22. package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
  23. package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
  24. package/dist/resources/extensions/gsd/auto-start.js +107 -29
  25. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  26. package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
  27. package/dist/resources/extensions/gsd/auto.js +76 -21
  28. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  30. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
  31. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  32. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  33. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  34. package/dist/resources/extensions/gsd/component-types.js +69 -0
  35. package/dist/resources/extensions/gsd/context-store.js +23 -7
  36. package/dist/resources/extensions/gsd/detection.js +49 -1
  37. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
  38. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  39. package/dist/resources/extensions/gsd/forensics.js +106 -0
  40. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  41. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  42. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  43. package/dist/resources/extensions/gsd/git-service.js +126 -2
  44. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  45. package/dist/resources/extensions/gsd/guided-flow.js +39 -13
  46. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  47. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  48. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  49. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  50. package/dist/resources/extensions/gsd/model-router.js +6 -0
  51. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  52. package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
  53. package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
  54. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  55. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  56. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  57. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  58. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  59. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  60. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  61. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  62. package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
  63. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  64. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  65. package/dist/resources/extensions/gsd/state.js +69 -58
  66. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  67. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
  68. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  69. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  70. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  71. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  72. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  73. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  74. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  75. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  76. package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
  77. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  78. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  79. package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
  80. package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
  81. package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
  82. package/dist/resources/extensions/mcp-client/index.js +3 -1
  83. package/dist/resources/extensions/ollama/index.js +5 -1
  84. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  85. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  86. package/dist/web/standalone/.next/BUILD_ID +1 -1
  87. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  88. package/dist/web/standalone/.next/build-manifest.json +2 -2
  89. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/index.html +1 -1
  108. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  115. package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
  116. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  117. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  119. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  120. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  121. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  122. package/package.json +2 -3
  123. package/packages/daemon/package.json +2 -2
  124. package/packages/daemon/src/logger.ts +4 -3
  125. package/packages/mcp-server/dist/server.d.ts +24 -0
  126. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  127. package/packages/mcp-server/dist/server.js +88 -87
  128. package/packages/mcp-server/dist/server.js.map +1 -1
  129. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  130. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  131. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  132. package/packages/mcp-server/package.json +2 -2
  133. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  134. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  135. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  136. package/packages/mcp-server/src/server.ts +131 -105
  137. package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
  138. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  139. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  140. package/packages/native/package.json +2 -2
  141. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  142. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  143. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  144. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  145. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  146. package/packages/pi-agent-core/package.json +1 -1
  147. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  148. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  149. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  150. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  151. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  152. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  153. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  154. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  155. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  156. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  157. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  158. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  159. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  160. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  161. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  162. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  163. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  164. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  165. package/packages/pi-ai/dist/models.test.js +36 -11
  166. package/packages/pi-ai/dist/models.test.js.map +1 -1
  167. package/packages/pi-ai/package.json +1 -1
  168. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  169. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  170. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  171. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  172. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  173. package/packages/pi-ai/src/models.test.ts +48 -11
  174. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  175. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  176. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  178. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  180. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  182. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  184. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  186. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  188. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  190. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  193. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  195. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  197. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  198. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  199. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  201. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  203. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  205. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  206. package/packages/pi-coding-agent/dist/index.js +1 -0
  207. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
  209. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  217. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  218. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  219. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  220. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  221. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  224. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  225. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  226. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  227. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  228. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  229. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  230. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  231. package/packages/pi-coding-agent/package.json +1 -1
  232. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  233. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  234. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  235. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  236. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  237. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  238. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  239. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  240. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  241. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  242. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  243. package/packages/pi-coding-agent/src/index.ts +1 -0
  244. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
  245. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  246. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
  247. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  248. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  249. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  250. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  251. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  252. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  253. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  254. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  255. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  256. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  257. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +37 -11
  258. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  259. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  260. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  261. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  262. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  263. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  264. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  265. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  266. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  267. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  268. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  269. package/packages/pi-tui/dist/components/editor.js +19 -0
  270. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  271. package/packages/pi-tui/dist/components/image.test.js +6 -5
  272. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  273. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  274. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  275. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  276. package/packages/pi-tui/package.json +1 -1
  277. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  278. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  279. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +42 -11
  280. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  281. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  282. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  283. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  284. package/packages/pi-tui/src/components/editor.ts +22 -0
  285. package/packages/pi-tui/src/components/image.test.ts +10 -5
  286. package/packages/pi-tui/src/editor-component.ts +3 -0
  287. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  288. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  289. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  290. package/packages/rpc-client/package.json +1 -1
  291. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  292. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  293. package/pkg/package.json +1 -1
  294. package/scripts/install.js +15 -1
  295. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  296. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  297. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  298. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  299. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  300. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  301. package/src/resources/extensions/claude-code-cli/readiness.ts +75 -16
  302. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
  303. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
  304. package/src/resources/extensions/github-sync/templates.ts +151 -0
  305. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  306. package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
  307. package/src/resources/extensions/google-search/index.ts +3 -2
  308. package/src/resources/extensions/gsd/auto/loop.ts +142 -2
  309. package/src/resources/extensions/gsd/auto/phases.ts +62 -38
  310. package/src/resources/extensions/gsd/auto/session.ts +7 -2
  311. package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
  312. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  313. package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
  314. package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
  315. package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
  316. package/src/resources/extensions/gsd/auto-start.ts +127 -9
  317. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  318. package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
  319. package/src/resources/extensions/gsd/auto.ts +90 -23
  320. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
  321. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  322. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
  323. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  324. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  325. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  326. package/src/resources/extensions/gsd/component-types.ts +362 -0
  327. package/src/resources/extensions/gsd/context-store.ts +25 -8
  328. package/src/resources/extensions/gsd/detection.ts +58 -1
  329. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
  330. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  331. package/src/resources/extensions/gsd/forensics.ts +118 -1
  332. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  333. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  334. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  335. package/src/resources/extensions/gsd/git-service.ts +149 -2
  336. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  337. package/src/resources/extensions/gsd/guided-flow.ts +57 -14
  338. package/src/resources/extensions/gsd/journal.ts +11 -1
  339. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  340. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  341. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  342. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  343. package/src/resources/extensions/gsd/model-router.ts +6 -0
  344. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  345. package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
  346. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
  347. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  348. package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  349. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  350. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  351. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  352. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  353. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  354. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  355. package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
  356. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  357. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  358. package/src/resources/extensions/gsd/state.ts +76 -66
  359. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  360. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  361. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
  362. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  363. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  364. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +133 -292
  365. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  366. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  367. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  368. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  369. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
  370. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
  371. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
  372. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
  373. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  374. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
  375. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
  376. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
  377. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
  378. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  379. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  380. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  381. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  382. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  383. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
  384. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  385. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  386. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  387. package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
  388. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
  389. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  390. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
  391. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  392. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  393. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  394. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  395. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
  396. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
  397. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
  398. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
  399. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  400. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  401. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  402. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
  403. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
  404. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  405. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  406. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
  407. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  408. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  409. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
  410. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  411. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  412. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
  413. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  414. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  415. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  416. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  417. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  418. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  419. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
  420. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  421. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
  422. package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
  423. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
  424. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  425. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
  426. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  427. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  428. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  429. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  430. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
  431. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  432. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
  433. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
  434. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  435. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  436. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
  437. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
  438. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
  439. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
  440. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
  441. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
  442. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
  443. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  444. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  445. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  446. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  447. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  448. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
  449. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  450. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  451. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  452. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
  453. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  454. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  455. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  456. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  457. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
  458. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
  459. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  460. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
  461. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  462. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
  463. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  464. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
  465. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  466. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
  467. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  468. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  469. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
  470. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  471. package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
  472. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  473. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  474. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  475. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  476. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  477. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  478. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  479. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  480. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  481. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  482. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  483. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
  484. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  485. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
  486. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
  487. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  488. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  489. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  490. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  491. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  492. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  493. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  494. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  495. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
  496. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  497. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  498. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  499. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  500. package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
  501. package/src/resources/extensions/gsd/types.ts +3 -3
  502. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  503. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  504. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  505. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  506. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  507. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  508. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  509. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  510. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  511. package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
  512. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  513. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  514. package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
  515. package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
  516. package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
  517. package/src/resources/extensions/mcp-client/index.ts +3 -1
  518. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  519. package/src/resources/extensions/ollama/index.ts +5 -1
  520. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  521. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  522. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  523. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  524. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  525. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  526. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  527. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  528. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  529. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  530. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  531. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
  532. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  533. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  534. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  535. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  536. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  537. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  538. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
  539. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  540. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  541. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  542. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
  543. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
  544. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_buildManifest.js +0 -0
  545. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_ssgManifest.js +0 -0
@@ -462,6 +462,9 @@ export function registerDbTools(pi) {
462
462
  definitionOfDone: Type.Optional(Type.Array(Type.String(), { description: "Definition of done bullets" })),
463
463
  requirementCoverage: Type.Optional(Type.String({ description: "Requirement coverage text" })),
464
464
  boundaryMapMarkdown: Type.Optional(Type.String({ description: "Boundary map markdown block" })),
465
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
466
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
467
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'plan-phase complete')" })),
465
468
  }),
466
469
  execute: planMilestoneExecute,
467
470
  };
@@ -503,6 +506,9 @@ export function registerDbTools(pi) {
503
506
  proofLevel: Type.Optional(Type.String({ description: "Slice proof level" })),
504
507
  integrationClosure: Type.Optional(Type.String({ description: "Slice integration closure" })),
505
508
  observabilityImpact: Type.Optional(Type.String({ description: "Slice observability impact" })),
509
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
510
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
511
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'plan-phase complete')" })),
506
512
  }),
507
513
  execute: planSliceExecute,
508
514
  };
@@ -569,6 +575,9 @@ export function registerDbTools(pi) {
569
575
  inputs: Type.Array(Type.String(), { description: "Input files or references" }),
570
576
  expectedOutput: Type.Array(Type.String(), { description: "Expected output files or artifacts" }),
571
577
  observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
578
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
579
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
580
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'plan-phase complete')" })),
572
581
  }),
573
582
  execute: planTaskExecute,
574
583
  };
@@ -628,6 +637,9 @@ export function registerDbTools(pi) {
628
637
  }),
629
638
  Type.String({ description: "Fallback: verification summary string" }),
630
639
  ]), { description: "Array of verification evidence entries" })),
640
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
641
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
642
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'task verified after retry')" })),
631
643
  }),
632
644
  execute: taskCompleteExecute,
633
645
  };
@@ -705,6 +717,9 @@ export function registerDbTools(pi) {
705
717
  }),
706
718
  Type.String({ description: "Fallback: slice ID string" }),
707
719
  ]), { description: "Upstream slice dependencies consumed" })),
720
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
721
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
722
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'all tasks verified')" })),
708
723
  }),
709
724
  execute: sliceCompleteExecute,
710
725
  };
@@ -826,6 +841,9 @@ export function registerDbTools(pi) {
826
841
  lessonsLearned: Type.Optional(Type.Array(Type.String(), { description: "Lessons learned during the milestone" })),
827
842
  followUps: Type.Optional(Type.String({ description: "Follow-up items for future milestones" })),
828
843
  deviations: Type.Optional(Type.String({ description: "Deviations from the original plan" })),
844
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
845
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
846
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'milestone validation passed')" })),
829
847
  }),
830
848
  execute: milestoneCompleteExecute,
831
849
  };
@@ -897,6 +915,9 @@ export function registerDbTools(pi) {
897
915
  expectedOutput: Type.Array(Type.String(), { description: "Expected output files or artifacts" }),
898
916
  }), { description: "Tasks to upsert (update existing or insert new)" }),
899
917
  removedTaskIds: Type.Array(Type.String(), { description: "Task IDs to remove from the slice" }),
918
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
919
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
920
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'blocker discovered during execution')" })),
900
921
  }),
901
922
  execute: replanSliceExecute,
902
923
  };
@@ -941,11 +962,199 @@ export function registerDbTools(pi) {
941
962
  }), { description: "New slices to add" }),
942
963
  removed: Type.Array(Type.String(), { description: "Slice IDs to remove" }),
943
964
  }, { description: "Slice changes to apply" }),
965
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
966
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
967
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'slice S01 completed, reassessing remaining roadmap')" })),
944
968
  }),
945
969
  execute: reassessRoadmapExecute,
946
970
  };
947
971
  pi.registerTool(reassessRoadmapTool);
948
972
  registerAlias(pi, reassessRoadmapTool, "gsd_roadmap_reassess", "gsd_reassess_roadmap");
973
+ // ─── gsd_task_reopen (gsd_reopen_task alias) ───────────────────────────
974
+ // Single-writer v3, Stream 3: reversibility tools for closed units.
975
+ const reopenTaskExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
976
+ const dbAvailable = await ensureDbOpen();
977
+ if (!dbAvailable) {
978
+ return {
979
+ content: [{ type: "text", text: "Error: GSD database is not available. Cannot reopen task." }],
980
+ details: { operation: "reopen_task", error: "db_unavailable" },
981
+ };
982
+ }
983
+ try {
984
+ const { handleReopenTask } = await import("../tools/reopen-task.js");
985
+ const result = await handleReopenTask(params, process.cwd());
986
+ if ("error" in result) {
987
+ return {
988
+ content: [{ type: "text", text: `Error reopening task: ${result.error}` }],
989
+ details: { operation: "reopen_task", error: result.error },
990
+ };
991
+ }
992
+ return {
993
+ content: [{ type: "text", text: `Reopened task ${result.taskId} (${result.sliceId}/${result.milestoneId})` }],
994
+ details: {
995
+ operation: "reopen_task",
996
+ milestoneId: result.milestoneId,
997
+ sliceId: result.sliceId,
998
+ taskId: result.taskId,
999
+ },
1000
+ };
1001
+ }
1002
+ catch (err) {
1003
+ const msg = err instanceof Error ? err.message : String(err);
1004
+ logError("tool", `reopen_task tool failed: ${msg}`, { tool: "gsd_task_reopen", error: String(err) });
1005
+ return {
1006
+ content: [{ type: "text", text: `Error reopening task: ${msg}` }],
1007
+ details: { operation: "reopen_task", error: msg },
1008
+ };
1009
+ }
1010
+ };
1011
+ const reopenTaskTool = {
1012
+ name: "gsd_task_reopen",
1013
+ label: "Reopen Task",
1014
+ description: "Reset a completed task back to 'pending' so it can be re-done. Cleans up SUMMARY.md so the DB-filesystem reconciler does not auto-correct the task back to complete. " +
1015
+ "Both the parent slice and milestone must still be open — use gsd_slice_reopen first if the slice has been closed.",
1016
+ promptSnippet: "Reopen a completed GSD task (resets status to pending, removes SUMMARY.md)",
1017
+ promptGuidelines: [
1018
+ "Use gsd_task_reopen when a completed task needs to be re-done (e.g. verification missed a regression, requirements changed).",
1019
+ "Will fail if the parent slice or milestone is already closed — reopen those first.",
1020
+ "Will fail if the task is not currently 'complete' — there is nothing to reopen.",
1021
+ "Use the canonical name gsd_task_reopen; gsd_reopen_task is only an alias.",
1022
+ ],
1023
+ parameters: Type.Object({
1024
+ milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
1025
+ sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
1026
+ taskId: Type.String({ description: "Task ID (e.g. T01)" }),
1027
+ reason: Type.Optional(Type.String({ description: "Why the task is being reopened (recorded in the audit trail)" })),
1028
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
1029
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
1030
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'regression discovered post-completion')" })),
1031
+ }),
1032
+ execute: reopenTaskExecute,
1033
+ };
1034
+ pi.registerTool(reopenTaskTool);
1035
+ registerAlias(pi, reopenTaskTool, "gsd_reopen_task", "gsd_task_reopen");
1036
+ // ─── gsd_slice_reopen (gsd_reopen_slice alias) ─────────────────────────
1037
+ const reopenSliceExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
1038
+ const dbAvailable = await ensureDbOpen();
1039
+ if (!dbAvailable) {
1040
+ return {
1041
+ content: [{ type: "text", text: "Error: GSD database is not available. Cannot reopen slice." }],
1042
+ details: { operation: "reopen_slice", error: "db_unavailable" },
1043
+ };
1044
+ }
1045
+ try {
1046
+ const { handleReopenSlice } = await import("../tools/reopen-slice.js");
1047
+ const result = await handleReopenSlice(params, process.cwd());
1048
+ if ("error" in result) {
1049
+ return {
1050
+ content: [{ type: "text", text: `Error reopening slice: ${result.error}` }],
1051
+ details: { operation: "reopen_slice", error: result.error },
1052
+ };
1053
+ }
1054
+ return {
1055
+ content: [{ type: "text", text: `Reopened slice ${result.sliceId} (${result.milestoneId}); reset ${result.tasksReset} task(s) to pending.` }],
1056
+ details: {
1057
+ operation: "reopen_slice",
1058
+ milestoneId: result.milestoneId,
1059
+ sliceId: result.sliceId,
1060
+ tasksReset: result.tasksReset,
1061
+ },
1062
+ };
1063
+ }
1064
+ catch (err) {
1065
+ const msg = err instanceof Error ? err.message : String(err);
1066
+ logError("tool", `reopen_slice tool failed: ${msg}`, { tool: "gsd_slice_reopen", error: String(err) });
1067
+ return {
1068
+ content: [{ type: "text", text: `Error reopening slice: ${msg}` }],
1069
+ details: { operation: "reopen_slice", error: msg },
1070
+ };
1071
+ }
1072
+ };
1073
+ const reopenSliceTool = {
1074
+ name: "gsd_slice_reopen",
1075
+ label: "Reopen Slice",
1076
+ description: "Reset a completed slice back to 'in_progress' and reset ALL of its tasks back to 'pending'. Cleans up SUMMARY.md / UAT.md and per-task summaries. " +
1077
+ "Reopening a slice means re-doing the work — partial resets create ambiguous state, so all tasks are reset.",
1078
+ promptSnippet: "Reopen a completed GSD slice (resets all tasks to pending, removes summaries)",
1079
+ promptGuidelines: [
1080
+ "Use gsd_slice_reopen when a completed slice needs to be re-done (e.g. integration issue surfaced, requirements changed).",
1081
+ "All tasks within the slice are reset to 'pending' — there is no partial-reopen.",
1082
+ "Will fail if the parent milestone is already closed — reopen the milestone first.",
1083
+ "Will fail if the slice is not currently 'complete' — there is nothing to reopen.",
1084
+ "Use the canonical name gsd_slice_reopen; gsd_reopen_slice is only an alias.",
1085
+ ],
1086
+ parameters: Type.Object({
1087
+ milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
1088
+ sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
1089
+ reason: Type.Optional(Type.String({ description: "Why the slice is being reopened (recorded in the audit trail)" })),
1090
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
1091
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
1092
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'cross-slice regression discovered')" })),
1093
+ }),
1094
+ execute: reopenSliceExecute,
1095
+ };
1096
+ pi.registerTool(reopenSliceTool);
1097
+ registerAlias(pi, reopenSliceTool, "gsd_reopen_slice", "gsd_slice_reopen");
1098
+ // ─── gsd_milestone_reopen (gsd_reopen_milestone alias) ─────────────────
1099
+ const reopenMilestoneExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
1100
+ const dbAvailable = await ensureDbOpen();
1101
+ if (!dbAvailable) {
1102
+ return {
1103
+ content: [{ type: "text", text: "Error: GSD database is not available. Cannot reopen milestone." }],
1104
+ details: { operation: "reopen_milestone", error: "db_unavailable" },
1105
+ };
1106
+ }
1107
+ try {
1108
+ const { handleReopenMilestone } = await import("../tools/reopen-milestone.js");
1109
+ const result = await handleReopenMilestone(params, process.cwd());
1110
+ if ("error" in result) {
1111
+ return {
1112
+ content: [{ type: "text", text: `Error reopening milestone: ${result.error}` }],
1113
+ details: { operation: "reopen_milestone", error: result.error },
1114
+ };
1115
+ }
1116
+ return {
1117
+ content: [{ type: "text", text: `Reopened milestone ${result.milestoneId}; reset ${result.slicesReset} slice(s) and ${result.tasksReset} task(s).` }],
1118
+ details: {
1119
+ operation: "reopen_milestone",
1120
+ milestoneId: result.milestoneId,
1121
+ slicesReset: result.slicesReset,
1122
+ tasksReset: result.tasksReset,
1123
+ },
1124
+ };
1125
+ }
1126
+ catch (err) {
1127
+ const msg = err instanceof Error ? err.message : String(err);
1128
+ logError("tool", `reopen_milestone tool failed: ${msg}`, { tool: "gsd_milestone_reopen", error: String(err) });
1129
+ return {
1130
+ content: [{ type: "text", text: `Error reopening milestone: ${msg}` }],
1131
+ details: { operation: "reopen_milestone", error: msg },
1132
+ };
1133
+ }
1134
+ };
1135
+ const reopenMilestoneTool = {
1136
+ name: "gsd_milestone_reopen",
1137
+ label: "Reopen Milestone",
1138
+ description: "Reset a closed milestone back to 'active', all of its slices to 'in_progress', and all tasks to 'pending'. " +
1139
+ "Cleans up MILESTONE-SUMMARY.md, slice summaries, and task summaries so the DB-filesystem reconciler does not auto-correct status back to complete.",
1140
+ promptSnippet: "Reopen a closed GSD milestone (resets slices and tasks, removes summaries)",
1141
+ promptGuidelines: [
1142
+ "Use gsd_milestone_reopen when a closed milestone needs to be re-done (e.g. validation failure surfaced after closure).",
1143
+ "All slices reset to 'in_progress' and all tasks reset to 'pending' — no partial reopen.",
1144
+ "Will fail if the milestone is not currently closed — there is nothing to reopen.",
1145
+ "Use the canonical name gsd_milestone_reopen; gsd_reopen_milestone is only an alias.",
1146
+ ],
1147
+ parameters: Type.Object({
1148
+ milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
1149
+ reason: Type.Optional(Type.String({ description: "Why the milestone is being reopened (recorded in the audit trail)" })),
1150
+ // Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
1151
+ actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
1152
+ triggerReason: Type.Optional(Type.String({ description: "Caller-provided reason this action was triggered (e.g. 'post-closure validation failure')" })),
1153
+ }),
1154
+ execute: reopenMilestoneExecute,
1155
+ };
1156
+ pi.registerTool(reopenMilestoneTool);
1157
+ registerAlias(pi, reopenMilestoneTool, "gsd_reopen_milestone", "gsd_milestone_reopen");
949
1158
  // ─── gsd_save_gate_result ──────────────────────────────────────────────
950
1159
  const saveGateResultExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
951
1160
  return executeSaveGateResult(params, process.cwd());
@@ -1,10 +1,8 @@
1
1
  import { getAutoDashboardData, startAuto } from "../auto.js";
2
2
  import { resetTransientRetryState } from "./agent-end-recovery.js";
3
- import { resetSessionTimeoutState } from "../auto/phases.js";
4
3
  const defaultDeps = {
5
4
  getSnapshot: () => getAutoDashboardData(),
6
5
  resetTransientRetryState,
7
- resetSessionTimeoutState,
8
6
  startAuto,
9
7
  };
10
8
  export async function resumeAutoAfterProviderDelay(pi, ctx, deps = defaultDeps) {
@@ -17,11 +15,10 @@ export async function resumeAutoAfterProviderDelay(pi, ctx, deps = defaultDeps)
17
15
  ctx.ui.notify("Provider error recovery delay elapsed, but no paused auto-mode base path was available. Leaving auto-mode paused.", "warning");
18
16
  return "missing-base";
19
17
  }
20
- // Reset retry counters before restarting — without this, counters
21
- // accumulate across pause/resume cycles and permanently lock out
22
- // auto-resume after their respective MAX thresholds.
18
+ // Reset provider-error retry state before restarting. Session-creation
19
+ // timeout state intentionally survives delayed resumes so the bounded
20
+ // auto-resume limit cannot be reset into an infinite pause/resume loop.
23
21
  deps.resetTransientRetryState();
24
- deps.resetSessionTimeoutState();
25
22
  await deps.startAuto(ctx, pi, snapshot.basePath, false, { step: snapshot.stepMode });
26
23
  return "resumed";
27
24
  }
@@ -353,7 +353,7 @@ export function registerHooks(pi, ecosystemHandlers) {
353
353
  if (isAutoActive() && typeof event.toolCallId === "string") {
354
354
  markToolEnd(event.toolCallId);
355
355
  }
356
- if (isAutoActive() && event.isError && event.toolName.startsWith("gsd_")) {
356
+ if (isAutoActive() && event.isError) {
357
357
  const resultPayload = ("result" in event ? event.result : undefined);
358
358
  const errorText = typeof resultPayload === "string"
359
359
  ? resultPayload
@@ -362,6 +362,8 @@ export function registerHooks(pi, ecosystemHandlers) {
362
362
  : (typeof event.content === "string"
363
363
  ? event.content
364
364
  : String(resultPayload ?? "")));
365
+ // Let recordToolInvocationError classify the failure so non-gsd_ harness
366
+ // errors and deterministic policy rejections are handled consistently.
365
367
  recordToolInvocationError(event.toolName, errorText);
366
368
  }
367
369
  if (event.toolName !== "ask_user_questions")
@@ -447,12 +449,14 @@ export function registerHooks(pi, ecosystemHandlers) {
447
449
  });
448
450
  pi.on("tool_execution_end", async (event) => {
449
451
  markToolEnd(event.toolCallId);
450
- // #2883: Capture tool invocation errors (malformed/truncated JSON arguments)
452
+ // #2883/#4974: Capture deterministic invocation/policy errors
451
453
  // so postUnitPreVerification can break the retry loop instead of re-dispatching.
452
- if (event.isError && event.toolName.startsWith("gsd_")) {
454
+ if (event.isError) {
453
455
  const errorText = typeof event.result === "string"
454
456
  ? event.result
455
457
  : (typeof event.result?.content?.[0]?.text === "string" ? event.result.content[0].text : String(event.result));
458
+ // Let recordToolInvocationError classify the failure so non-gsd_ harness
459
+ // errors and deterministic policy rejections are handled consistently.
456
460
  recordToolInvocationError(event.toolName, errorText);
457
461
  }
458
462
  // Safety harness: record tool execution results for evidence cross-referencing
@@ -1,6 +1,13 @@
1
- import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- const MILESTONE_CONTEXT_RE = /M\d+(?:-[a-z0-9]{6})?-CONTEXT\.md$/;
1
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { isAbsolute, join, relative, resolve, sep } from "node:path";
3
+ import { minimatch } from "minimatch";
4
+ /**
5
+ * Regex matching milestone CONTEXT.md file names in both legacy M001
6
+ * and unique M001-abc123 formats. Exported so regex-hardening tests
7
+ * can exercise the real pattern rather than a drift-prone inline
8
+ * re-implementation (see #4835).
9
+ */
10
+ export const MILESTONE_CONTEXT_RE = /M\d+(?:-[a-z0-9]{6})?-CONTEXT\.md$/;
4
11
  const CONTEXT_MILESTONE_RE = /(?:^|[/\\])(M\d+(?:-[a-z0-9]{6})?)-CONTEXT\.md$/i;
5
12
  const DEPTH_VERIFICATION_MILESTONE_RE = /depth_verification[_-](M\d+(?:-[a-z0-9]{6})?)/i;
6
13
  /**
@@ -76,8 +83,15 @@ const GATE_SAFE_TOOLS = new Set([
76
83
  "search-the-web", "resolve_library", "get_library_docs", "fetch_page",
77
84
  "search_and_read",
78
85
  ]);
86
+ /**
87
+ * Persistence is ON by default (opt-out).
88
+ * Set GSD_PERSIST_WRITE_GATE_STATE="0" or GSD_PERSIST_WRITE_GATE_STATE="false"
89
+ * to disable. All other values — including unset — persist the snapshot.
90
+ * (Inverted from the original opt-in guard; see #4950.)
91
+ */
79
92
  function shouldPersistWriteGateSnapshot(env = process.env) {
80
- return env.GSD_PERSIST_WRITE_GATE_STATE === "1";
93
+ const v = env.GSD_PERSIST_WRITE_GATE_STATE;
94
+ return v !== "0" && v !== "false";
81
95
  }
82
96
  function writeGateSnapshotPath(basePath = process.cwd()) {
83
97
  return join(basePath, ".gsd", "runtime", "write-gate-state.json");
@@ -94,9 +108,22 @@ function persistWriteGateSnapshot(basePath = process.cwd()) {
94
108
  return;
95
109
  const path = writeGateSnapshotPath(basePath);
96
110
  mkdirSync(join(basePath, ".gsd", "runtime"), { recursive: true });
97
- const tempPath = `${path}.tmp`;
111
+ const tempPath = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
98
112
  writeFileSync(tempPath, JSON.stringify(currentWriteGateSnapshot(), null, 2), "utf-8");
99
- renameSync(tempPath, path);
113
+ try {
114
+ renameSync(tempPath, path);
115
+ }
116
+ catch (err) {
117
+ // EXDEV: cross-device rename (temp and dest on different mounts). Fall back
118
+ // to copy-then-delete so the snapshot is still written atomically enough.
119
+ if (err instanceof Error && err.code === "EXDEV") {
120
+ copyFileSync(tempPath, path);
121
+ unlinkSync(tempPath);
122
+ }
123
+ else {
124
+ throw err;
125
+ }
126
+ }
100
127
  }
101
128
  function clearPersistedWriteGateSnapshot(basePath = process.cwd()) {
102
129
  if (!shouldPersistWriteGateSnapshot())
@@ -295,9 +322,9 @@ export function isDepthConfirmationAnswer(selected, options) {
295
322
  const confirmLabel = options[0]?.label;
296
323
  return typeof confirmLabel === "string" && value === confirmLabel;
297
324
  }
298
- // Fallback when options aren't available (e.g., older call sites):
299
- // accept only if it contains "(Recommended)" the prompt convention suffix.
300
- return value.includes("(Recommended)");
325
+ // Fail-closed: no options means we cannot structurally validate the answer.
326
+ // Returning false prevents any free-form string from unlocking the gate.
327
+ return false;
301
328
  }
302
329
  export function shouldBlockContextWrite(toolName, inputPath, milestoneId, _queuePhaseActive) {
303
330
  if (toolName !== "write")
@@ -413,3 +440,94 @@ export function shouldBlockQueueExecutionInSnapshot(snapshot, toolName, input, q
413
440
  reason: `Blocked: /gsd queue is a planning tool — it creates milestones, not executes work. Unknown tools are not permitted during queue mode.`,
414
441
  };
415
442
  }
443
+ // ─── Planning-unit tools-policy enforcement (#4934) ───────────────────────
444
+ const PLANNING_WRITE_TOOLS = new Set(["write", "edit", "multi_edit", "notebook_edit"]);
445
+ const PLANNING_SUBAGENT_TOOLS = new Set(["subagent", "task"]);
446
+ const PLANNING_SAFE_TOOLS = new Set([
447
+ "read", "grep", "find", "ls", "glob",
448
+ "ask_user_questions",
449
+ "search-the-web", "resolve_library", "get_library_docs", "fetch_page",
450
+ "search_and_read",
451
+ ]);
452
+ function isPathUnderGsd(absPath, basePath) {
453
+ const gsdRoot = resolve(basePath, ".gsd");
454
+ const rel = relative(gsdRoot, absPath);
455
+ return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
456
+ }
457
+ function matchesAllowedGlob(absPath, basePath, globs) {
458
+ const rel = relative(basePath, absPath);
459
+ if (rel.startsWith("..") || isAbsolute(rel))
460
+ return false;
461
+ const posix = rel.split(sep).join("/");
462
+ return globs.some(g => minimatch(posix, g, { dot: false, nocase: false }));
463
+ }
464
+ function blockReason(unitType, mode, what) {
465
+ return [
466
+ `HARD BLOCK: unit "${unitType}" runs under tools-policy "${mode}" — ${what}.`,
467
+ `This is a mechanical gate enforced by manifest.tools (#4934). You MUST NOT proceed,`,
468
+ `retry the same call, or rationalize past this block. If you need to write user source,`,
469
+ `the work belongs in execute-task, not in a planning unit.`,
470
+ ].join(" ");
471
+ }
472
+ /**
473
+ * Planning-unit tool-policy enforcement. Returns { block } per the policy
474
+ * resolved from the active unit's manifest:
475
+ *
476
+ * - "all" → never blocks.
477
+ * - "read-only" → blocks all writes, bash, and subagent dispatch.
478
+ * - "planning" → blocks writes to paths outside <basePath>/.gsd/,
479
+ * bash that isn't read-only, and subagent dispatch.
480
+ * - "docs" → like "planning" but also allows writes to paths
481
+ * matching `allowedPathGlobs` relative to basePath.
482
+ *
483
+ * `policy` of null means "no manifest resolved" — pass-through.
484
+ */
485
+ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitType, policy) {
486
+ if (!policy)
487
+ return { block: false };
488
+ if (policy.mode === "all")
489
+ return { block: false };
490
+ const tool = toolName;
491
+ if (policy.mode === "read-only") {
492
+ if (PLANNING_SAFE_TOOLS.has(tool))
493
+ return { block: false };
494
+ if (tool.startsWith("gsd_"))
495
+ return { block: false };
496
+ if (PLANNING_WRITE_TOOLS.has(tool) || tool === "bash" || PLANNING_SUBAGENT_TOOLS.has(tool)) {
497
+ return { block: true, reason: blockReason(unitType, policy.mode, `${tool} is not permitted (read-only)`) };
498
+ }
499
+ return { block: true, reason: blockReason(unitType, policy.mode, `tool "${tool}" is not on the read-only allowlist`) };
500
+ }
501
+ // planning / docs modes
502
+ if (PLANNING_SAFE_TOOLS.has(tool))
503
+ return { block: false };
504
+ if (tool.startsWith("gsd_"))
505
+ return { block: false };
506
+ if (PLANNING_SUBAGENT_TOOLS.has(tool)) {
507
+ return { block: true, reason: blockReason(unitType, policy.mode, `subagent dispatch is not permitted in planning units`) };
508
+ }
509
+ if (tool === "bash") {
510
+ if (BASH_READ_ONLY_RE.test(pathOrCommand))
511
+ return { block: false };
512
+ return {
513
+ block: true,
514
+ reason: blockReason(unitType, policy.mode, `bash is restricted to read-only commands (cat/grep/git log/etc); cannot run "${pathOrCommand.slice(0, 80)}${pathOrCommand.length > 80 ? "…" : ""}"`),
515
+ };
516
+ }
517
+ if (PLANNING_WRITE_TOOLS.has(tool)) {
518
+ if (!pathOrCommand) {
519
+ return { block: true, reason: blockReason(unitType, policy.mode, `${tool} called with empty path`) };
520
+ }
521
+ const absPath = isAbsolute(pathOrCommand) ? pathOrCommand : resolve(basePath, pathOrCommand);
522
+ if (isPathUnderGsd(absPath, basePath))
523
+ return { block: false };
524
+ if (policy.mode === "docs" && matchesAllowedGlob(absPath, basePath, policy.allowedPathGlobs)) {
525
+ return { block: false };
526
+ }
527
+ return {
528
+ block: true,
529
+ reason: blockReason(unitType, policy.mode, `cannot ${tool} "${pathOrCommand}" — writes are restricted to .gsd/${policy.mode === "docs" ? " and " + policy.allowedPathGlobs.join(", ") : ""}`),
530
+ };
531
+ }
532
+ return { block: false };
533
+ }