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
@@ -107,7 +107,8 @@ describe("auditOrphanedMilestoneBranches", () => {
107
107
  assert.ok(branches.includes("milestone/M001"), "unmerged branch must be preserved");
108
108
  });
109
109
 
110
- test("skips active (non-complete) milestone branches", () => {
110
+ test("skips active milestone branch with no commits ahead of main (nothing to recover)", () => {
111
+ // Branch created from main with zero divergence — no live work, nothing to warn about.
111
112
  run("git branch milestone/M001", dir);
112
113
  insertMilestone({ id: "M001", title: "Test", status: "active" });
113
114
 
@@ -116,11 +117,67 @@ describe("auditOrphanedMilestoneBranches", () => {
116
117
  assert.deepStrictEqual(result.recovered, []);
117
118
  assert.deepStrictEqual(result.warnings, []);
118
119
 
119
- // Branch should still exist
120
+ // Branch should still exist (data safety — user may intend to use it)
120
121
  const branches = run("git branch --list milestone/M001", dir);
121
122
  assert.ok(branches.includes("milestone/M001"), "active milestone branch should be preserved");
122
123
  });
123
124
 
125
+ test("#4762 — warns about in-progress milestone with unmerged commits ahead of main", () => {
126
+ // Simulates the primary #4761 scenario: auto-mode was interrupted mid-milestone.
127
+ // DB status = active/in_progress, branch has real work, main is behind.
128
+ run("git checkout -b milestone/M001", dir);
129
+ writeFileSync(join(dir, "feature.txt"), "in-progress work\n");
130
+ run("git add feature.txt", dir);
131
+ run("git commit -m \"in-progress work on M001\"", dir);
132
+ run("git checkout main", dir);
133
+
134
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
135
+
136
+ const result = auditOrphanedMilestoneBranches(dir, "worktree");
137
+
138
+ // Must NOT recover/delete (data safety — work is live)
139
+ assert.deepStrictEqual(result.recovered, [], "must not delete a branch with live in-progress work");
140
+
141
+ // Must surface a warning so the user knows the worktree holds uncollapsed work
142
+ assert.ok(result.warnings.length > 0, "should warn about in-progress orphan");
143
+ assert.ok(
144
+ result.warnings.some(w => w.includes("milestone/M001") && w.includes("in-progress")),
145
+ `warning should mention milestone/M001 and in-progress state; got: ${JSON.stringify(result.warnings)}`,
146
+ );
147
+
148
+ // Branch must still exist
149
+ const branches = run("git branch --list milestone/M001", dir);
150
+ assert.ok(branches.includes("milestone/M001"), "in-progress branch must be preserved");
151
+ });
152
+
153
+ test("#4762 — also surfaces worktree directory for in-progress orphan when present", () => {
154
+ // In-progress + unmerged + physical worktree directory — the full primary scenario.
155
+ run("git checkout -b milestone/M001", dir);
156
+ writeFileSync(join(dir, "feature.txt"), "in-progress work\n");
157
+ run("git add feature.txt", dir);
158
+ run("git commit -m \"in-progress work on M001\"", dir);
159
+ run("git checkout main", dir);
160
+
161
+ // Simulate a leftover worktree directory
162
+ const wtDir = join(dir, ".gsd", "worktrees", "M001");
163
+ mkdirSync(wtDir, { recursive: true });
164
+ writeFileSync(join(wtDir, ".git"), `gitdir: ${join(dir, ".git", "worktrees", "M001")}\n`);
165
+
166
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
167
+
168
+ const result = auditOrphanedMilestoneBranches(dir, "worktree");
169
+
170
+ // Must preserve everything for data safety
171
+ assert.deepStrictEqual(result.recovered, [], "must not touch worktree or branch with live work");
172
+ assert.ok(existsSync(wtDir), "worktree directory must be preserved");
173
+
174
+ // Warning should mention the worktree path so the user can find the work
175
+ assert.ok(
176
+ result.warnings.some(w => w.includes(".gsd/worktrees/M001") || w.includes("worktree")),
177
+ `warning should reference the worktree location; got: ${JSON.stringify(result.warnings)}`,
178
+ );
179
+ });
180
+
124
181
  test("cleans up orphaned worktree directory for merged milestone", () => {
125
182
  // Create milestone branch (merged — same as main)
126
183
  run("git branch milestone/M001", dir);
@@ -1,165 +1,308 @@
1
1
  /**
2
- * Parallel research slices dispatch — structural tests.
2
+ * parallel-research-dispatch.test.tsbehaviour tests for the
3
+ * "planning (multiple slices need research) → parallel-research-slices"
4
+ * dispatch rule and its prompt builder.
3
5
  *
4
- * Verifies the dispatch rule and prompt builder exist with correct structure.
6
+ * These tests invoke the real functions (resolveDispatch,
7
+ * buildParallelResearchSlicesPrompt) against on-disk fixtures. They do
8
+ * not read source files and string-match identifiers.
9
+ *
10
+ * See #4784 for why the previous source-grep version of this file was
11
+ * replaced.
5
12
  */
6
13
 
7
- import test, { afterEach } from "node:test";
14
+ import { describe, test, beforeEach, afterEach, after } from "node:test";
8
15
  import assert from "node:assert/strict";
9
- import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
10
- import { join, dirname } from "node:path";
16
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
17
+ import { join } from "node:path";
11
18
  import { tmpdir } from "node:os";
12
- import { fileURLToPath } from "node:url";
13
19
 
14
- import { resolveDispatch } from "../auto-dispatch.ts";
20
+ // Point GSD_HOME at a throwaway directory *before* the prompt-loader
21
+ // module is imported (via the dynamic imports below) so templates
22
+ // resolve from the in-tree prompts/ directory instead of a developer's
23
+ // ~/.gsd/ copy (which may be a stale cached version from a prior
24
+ // install — see #4784 fallout). Static imports above are hoisted, so
25
+ // `tmpdir` and `join` are already available at this point; the dynamic
26
+ // imports below observe the value we set here. The previous value is
27
+ // captured and restored in an after() hook to avoid leaking module-scope
28
+ // env mutation into other suites if the runner ever moves to a shared
29
+ // process model.
30
+ const previousGsdHome = process.env.GSD_HOME;
31
+ process.env.GSD_HOME = process.env.GSD_HOME_TEST_OVERRIDE
32
+ ?? join(tmpdir(), `gsd-test-home-${process.pid}-${Date.now()}`);
15
33
 
16
- const __dirname = dirname(fileURLToPath(import.meta.url));
34
+ after(() => {
35
+ if (previousGsdHome === undefined) {
36
+ delete process.env.GSD_HOME;
37
+ } else {
38
+ process.env.GSD_HOME = previousGsdHome;
39
+ }
40
+ });
17
41
 
18
- const dispatchSrc = readFileSync(join(__dirname, "..", "auto-dispatch.ts"), "utf-8");
19
- const promptsSrc = readFileSync(join(__dirname, "..", "auto-prompts.ts"), "utf-8");
20
- const templatePath = join(__dirname, "..", "prompts", "parallel-research-slices.md");
21
- const templateSrc = readFileSync(templatePath, "utf-8");
42
+ const { resolveDispatch } = await import("../auto-dispatch.ts");
43
+ const { buildParallelResearchSlicesPrompt } = await import("../auto-prompts.ts");
22
44
 
23
- const tmpDirs: string[] = [];
45
+ type DispatchState = Parameters<typeof resolveDispatch>[0]["state"];
24
46
 
25
- function makeTmpProject(): string {
26
- const base = mkdtempSync(join(tmpdir(), "parallel-research-"));
27
- tmpDirs.push(base);
28
- const milestoneDir = join(base, ".gsd", "milestones", "M001");
47
+ function writeRoadmap(
48
+ base: string,
49
+ mid: string,
50
+ slices: Array<{ id: string; title: string; done?: boolean; depends?: string[] }>,
51
+ ): void {
52
+ const milestoneDir = join(base, ".gsd", "milestones", mid);
29
53
  mkdirSync(milestoneDir, { recursive: true });
54
+ const lines = [
55
+ `# ${mid}: Parallel Research Milestone`,
56
+ "",
57
+ "**Vision:** Research-ready slices.",
58
+ "",
59
+ "**Success Criteria:**",
60
+ "- Research all slices",
61
+ "",
62
+ "## Slices",
63
+ "",
64
+ ];
65
+ for (const s of slices) {
66
+ const box = s.done ? "x" : " ";
67
+ const deps = s.depends ? `depends:[${s.depends.join(",")}]` : "depends:[]";
68
+ lines.push(`- [${box}] **${s.id}: ${s.title}** \`risk:low\` \`${deps}\``);
69
+ }
70
+ lines.push("", "## Boundary Map", "");
30
71
  writeFileSync(
31
- join(milestoneDir, "M001-ROADMAP.md"),
32
- [
33
- "# M001: Parallel Research Milestone",
34
- "",
35
- "**Vision:** Research-ready slices.",
36
- "",
37
- "**Success Criteria:**",
38
- "- Research both slices",
39
- "",
40
- "## Slices",
41
- "",
42
- "- [ ] **S01: Alpha** `risk:low` `depends:[]`",
43
- "- [ ] **S02: Beta** `risk:low` `depends:[]`",
44
- "",
45
- "## Boundary Map",
46
- "",
47
- ].join("\n"),
72
+ join(milestoneDir, `${mid}-ROADMAP.md`),
73
+ lines.join("\n"),
48
74
  "utf-8",
49
75
  );
50
- return base;
51
76
  }
52
77
 
53
- afterEach(() => {
54
- for (const dir of tmpDirs) {
55
- try {
56
- rmSync(dir, { recursive: true, force: true });
57
- } catch {
58
- // Best-effort cleanup only.
59
- }
78
+ function assertNotParallelResearchDispatch(
79
+ action: Awaited<ReturnType<typeof resolveDispatch>>,
80
+ mid = "M001",
81
+ ): void {
82
+ if (action.action === "dispatch") {
83
+ assert.notEqual(action.unitId, `${mid}/parallel-research`);
60
84
  }
61
- tmpDirs.length = 0;
62
- });
85
+ }
63
86
 
64
- // ─── Dispatch rule ────────────────────────────────────────────────────────
87
+ function baseState(activeSliceId = "S01", activeSliceTitle = "Alpha"): DispatchState {
88
+ return {
89
+ phase: "planning",
90
+ activeMilestone: { id: "M001", title: "Parallel Research Milestone", status: "active" },
91
+ activeSlice: { id: activeSliceId, title: activeSliceTitle },
92
+ activeTask: null,
93
+ registry: [],
94
+ blockers: [],
95
+ } as unknown as DispatchState;
96
+ }
65
97
 
66
- test("dispatch: parallel-research-slices rule exists", () => {
67
- assert.ok(
68
- dispatchSrc.includes("parallel-research-slices"),
69
- "dispatch table should have parallel-research-slices rule",
70
- );
71
- });
98
+ describe("parallel-research-slices dispatch rule", () => {
99
+ let base: string;
72
100
 
73
- test("dispatch: parallel-research-slices requires 2+ slices", () => {
74
- assert.ok(
75
- dispatchSrc.includes("researchReadySlices.length < 2"),
76
- "rule should require at least 2 slices for parallel dispatch",
77
- );
78
- });
101
+ beforeEach(() => {
102
+ base = mkdtempSync(join(tmpdir(), "parallel-research-"));
103
+ });
79
104
 
80
- test("dispatch: parallel-research-slices respects skip_research", () => {
81
- const ruleIdx = dispatchSrc.indexOf("parallel-research-slices");
82
- const ruleBlock = dispatchSrc.slice(ruleIdx, ruleIdx + 500);
83
- assert.ok(
84
- ruleBlock.includes("skip_research") || dispatchSrc.slice(ruleIdx - 300, ruleIdx).includes("skip_research"),
85
- "rule should check skip_research preference",
86
- );
87
- });
105
+ afterEach(() => {
106
+ rmSync(base, { recursive: true, force: true });
107
+ });
88
108
 
89
- // ─── Prompt builder ───────────────────────────────────────────────────────
109
+ test("dispatches parallel research when 2+ slices need research", async () => {
110
+ writeRoadmap(base, "M001", [
111
+ { id: "S01", title: "Alpha" },
112
+ { id: "S02", title: "Beta" },
113
+ ]);
90
114
 
91
- test("prompt: buildParallelResearchSlicesPrompt exported", () => {
92
- assert.ok(
93
- promptsSrc.includes("export async function buildParallelResearchSlicesPrompt"),
94
- "buildParallelResearchSlicesPrompt should be exported",
95
- );
96
- });
115
+ const action = await resolveDispatch({
116
+ basePath: base,
117
+ mid: "M001",
118
+ midTitle: "Parallel Research Milestone",
119
+ state: baseState(),
120
+ prefs: undefined,
121
+ });
97
122
 
98
- test("prompt: builds per-slice subagent prompts", () => {
99
- assert.ok(
100
- promptsSrc.includes("buildResearchSlicePrompt"),
101
- "parallel prompt builder should delegate to per-slice research prompts",
102
- );
103
- });
123
+ assert.equal(action.action, "dispatch");
124
+ if (action.action === "dispatch") {
125
+ assert.equal(action.unitType, "research-slice");
126
+ assert.equal(action.unitId, "M001/parallel-research");
127
+ }
128
+ });
104
129
 
105
- // ─── Template ─────────────────────────────────────────────────────────────
130
+ test("does not dispatch parallel research with only one ready slice", async () => {
131
+ writeRoadmap(base, "M001", [{ id: "S01", title: "Alpha" }]);
106
132
 
107
- test("template: parallel-research-slices.md has required variables", () => {
108
- assert.ok(templateSrc.includes("{{sliceCount}}"), "template should use sliceCount");
109
- assert.ok(templateSrc.includes("{{mid}}"), "template should use mid");
110
- assert.ok(templateSrc.includes("{{subagentPrompts}}"), "template should use subagentPrompts");
111
- });
133
+ const action = await resolveDispatch({
134
+ basePath: base,
135
+ mid: "M001",
136
+ midTitle: "Parallel Research Milestone",
137
+ state: baseState(),
138
+ prefs: undefined,
139
+ });
112
140
 
113
- test("#4068: template: parallel-research-slices retry cap prevents infinite subagent loop", () => {
114
- // The template must cap retries at 1 ("retry it once") and instruct the
115
- // agent to write a BLOCKER note on the second failure rather than looping.
116
- // Without this, a timing-out subagent causes the orchestrating agent to
117
- // retry indefinitely (issue #4068 / #4355).
118
- assert.ok(
119
- templateSrc.includes("once") || templateSrc.includes("one retry") || templateSrc.match(/retry.{0,20}once/),
120
- "template should cap subagent retries at one",
121
- );
122
- assert.ok(
123
- templateSrc.toLowerCase().includes("blocker"),
124
- "template should instruct writing a BLOCKER note instead of infinite retries",
125
- );
126
- assert.ok(
127
- !templateSrc.match(/re-run it individually\s*\n/),
128
- "template must not have unbounded re-run instruction without a retry cap",
129
- );
130
- });
141
+ assertNotParallelResearchDispatch(action);
142
+ });
131
143
 
132
- // ─── Validate milestone prompt ────────────────────────────────────────────
144
+ test("does not dispatch parallel research when skip_research is set", async () => {
145
+ writeRoadmap(base, "M001", [
146
+ { id: "S01", title: "Alpha" },
147
+ { id: "S02", title: "Beta" },
148
+ ]);
133
149
 
134
- test("template: validate-milestone uses parallel reviewers", () => {
135
- const validateSrc = readFileSync(join(__dirname, "..", "prompts", "validate-milestone.md"), "utf-8");
136
- assert.ok(
137
- validateSrc.includes("Reviewer A") && validateSrc.includes("Reviewer B") && validateSrc.includes("Reviewer C"),
138
- "validate-milestone should dispatch 3 parallel reviewers",
139
- );
150
+ const action = await resolveDispatch({
151
+ basePath: base,
152
+ mid: "M001",
153
+ midTitle: "Parallel Research Milestone",
154
+ state: baseState(),
155
+ prefs: { phases: { skip_research: true } } as Parameters<typeof resolveDispatch>[0]["prefs"],
156
+ });
157
+
158
+ assertNotParallelResearchDispatch(action);
159
+ });
160
+
161
+ test("does not dispatch parallel research when skip_slice_research is set", async () => {
162
+ writeRoadmap(base, "M001", [
163
+ { id: "S01", title: "Alpha" },
164
+ { id: "S02", title: "Beta" },
165
+ ]);
166
+
167
+ const action = await resolveDispatch({
168
+ basePath: base,
169
+ mid: "M001",
170
+ midTitle: "Parallel Research Milestone",
171
+ state: baseState(),
172
+ prefs: { phases: { skip_slice_research: true } } as Parameters<typeof resolveDispatch>[0]["prefs"],
173
+ });
174
+
175
+ assertNotParallelResearchDispatch(action);
176
+ });
177
+
178
+ test("does not dispatch when a PARALLEL-BLOCKER placeholder exists (#4414)", async () => {
179
+ writeRoadmap(base, "M001", [
180
+ { id: "S01", title: "Alpha" },
181
+ { id: "S02", title: "Beta" },
182
+ ]);
183
+ const milestoneDir = join(base, ".gsd", "milestones", "M001");
184
+ writeFileSync(
185
+ join(milestoneDir, "M001-PARALLEL-BLOCKER.md"),
186
+ "# Parallel research escalated\nPrevious dispatch failed; need per-slice fallback.\n",
187
+ "utf-8",
188
+ );
189
+
190
+ const action = await resolveDispatch({
191
+ basePath: base,
192
+ mid: "M001",
193
+ midTitle: "Parallel Research Milestone",
194
+ state: baseState(),
195
+ prefs: undefined,
196
+ });
197
+
198
+ assertNotParallelResearchDispatch(action);
199
+ });
200
+
201
+ test("excludes slices that already have a RESEARCH file (falls back to <2)", async () => {
202
+ writeRoadmap(base, "M001", [
203
+ { id: "S01", title: "Alpha" },
204
+ { id: "S02", title: "Beta" },
205
+ ]);
206
+ // S01 already has research → only S02 remains → <2 ready → no parallel dispatch
207
+ const s01Dir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
208
+ mkdirSync(s01Dir, { recursive: true });
209
+ writeFileSync(
210
+ join(s01Dir, "S01-RESEARCH.md"),
211
+ "# Research\n",
212
+ "utf-8",
213
+ );
214
+
215
+ const action = await resolveDispatch({
216
+ basePath: base,
217
+ mid: "M001",
218
+ midTitle: "Parallel Research Milestone",
219
+ state: baseState(),
220
+ prefs: undefined,
221
+ });
222
+
223
+ assertNotParallelResearchDispatch(action);
224
+ });
140
225
  });
141
226
 
142
- test("resolveDispatch prefers parallel research when multiple slices are ready", async () => {
143
- const base = makeTmpProject();
144
-
145
- const action = await resolveDispatch({
146
- basePath: base,
147
- mid: "M001",
148
- midTitle: "Parallel Research Milestone",
149
- state: {
150
- phase: "planning",
151
- activeMilestone: { id: "M001", title: "Parallel Research Milestone", status: "active" },
152
- activeSlice: { id: "S01", title: "Alpha" },
153
- activeTask: null,
154
- registry: [],
155
- blockers: [],
156
- } as any,
157
- prefs: undefined,
227
+ describe("buildParallelResearchSlicesPrompt", () => {
228
+ let base: string;
229
+
230
+ beforeEach(() => {
231
+ base = mkdtempSync(join(tmpdir(), "parallel-research-prompt-"));
232
+ mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
158
233
  });
159
234
 
160
- assert.equal(action.action, "dispatch");
161
- if (action.action === "dispatch") {
162
- assert.equal(action.unitType, "research-slice");
163
- assert.equal(action.unitId, "M001/parallel-research");
164
- }
235
+ afterEach(() => {
236
+ rmSync(base, { recursive: true, force: true });
237
+ });
238
+
239
+ test("renders slice count and every slice title into the prompt", async () => {
240
+ const prompt = await buildParallelResearchSlicesPrompt(
241
+ "M001",
242
+ "Parallel Research Milestone",
243
+ [
244
+ { id: "S01", title: "Alpha slice title" },
245
+ { id: "S02", title: "Beta slice title" },
246
+ { id: "S03", title: "Gamma slice title" },
247
+ ],
248
+ base,
249
+ );
250
+
251
+ assert.match(
252
+ prompt,
253
+ /\b3\b[^.\n]{0,40}\bslices?\b/i,
254
+ "prompt should include slice count 3 in slice context",
255
+ );
256
+ assert.match(prompt, /Alpha slice title/);
257
+ assert.match(prompt, /Beta slice title/);
258
+ assert.match(prompt, /Gamma slice title/);
259
+ });
260
+
261
+ test("#4068: prompt caps subagent retries at one and instructs writing a BLOCKER on second failure", async () => {
262
+ // Regression for infinite-retry loop (#4068 / #4355 / #4570). A correct
263
+ // fix must both cap retries AND instruct the agent to escalate to a
264
+ // BLOCKER note on the second failure.
265
+ const prompt = await buildParallelResearchSlicesPrompt(
266
+ "M001",
267
+ "Parallel Research Milestone",
268
+ [
269
+ { id: "S01", title: "Alpha" },
270
+ { id: "S02", title: "Beta" },
271
+ ],
272
+ base,
273
+ );
274
+
275
+ // Cap: the rendered prompt must bound retries. "once" alone is too
276
+ // permissive — the word appears for unrelated reasons across a ~10KB
277
+ // rendered prompt — so the pattern must require retry-context
278
+ // pairing: either "retry ... once" within 30 chars, or the phrase
279
+ // "one retry", or "retry it once".
280
+ assert.match(
281
+ prompt,
282
+ /\bone retry\b|retry[^.?!]{0,30}\bonce\b|retry it \*{0,2}once/i,
283
+ "rendered prompt should cap retries to one",
284
+ );
285
+
286
+ // Escalation: on second failure the agent must write a BLOCKER
287
+ // rather than loop. Bare /blocker/i is too permissive — require
288
+ // retry/failure context within the same sentence so a stray
289
+ // "blocker" elsewhere in the ~10KB prompt cannot satisfy the
290
+ // assertion.
291
+ assert.match(
292
+ prompt,
293
+ /blocker[^.?!]{0,100}(second|retry|fail)|(second|retry|fail)[^.?!]{0,100}blocker/i,
294
+ "rendered prompt should instruct writing a BLOCKER on repeated failure",
295
+ );
296
+
297
+ // Anti-pattern: the unbounded "re-run it individually" instruction
298
+ // that caused the original infinite loop must not appear on its own.
299
+ // The negative lookahead is bounded to the surrounding 100
300
+ // characters so a later unrelated "once" elsewhere in the prompt
301
+ // cannot falsely satisfy the "paired with a retry bound" exception.
302
+ assert.doesNotMatch(
303
+ prompt,
304
+ /re-run it individually(?![\s\S]{0,100}\bonce\b)/i,
305
+ "rendered prompt must not contain the unbounded re-run instruction",
306
+ );
307
+ });
165
308
  });