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
@@ -13,13 +13,16 @@
13
13
  * - Conflict check: file overlap between slice plans (slice-parallel-conflict.ts)
14
14
  */
15
15
 
16
- import { spawn, type ChildProcess } from "node:child_process";
16
+ import { execFileSync, spawn, type ChildProcess } from "node:child_process";
17
+ import { randomUUID } from "node:crypto";
17
18
  import {
18
19
  appendFileSync,
19
20
  existsSync,
20
21
  writeFileSync,
21
22
  readFileSync,
22
23
  mkdirSync,
24
+ renameSync,
25
+ unlinkSync,
23
26
  } from "node:fs";
24
27
  import { join, dirname } from "node:path";
25
28
  import { fileURLToPath } from "node:url";
@@ -40,6 +43,8 @@ export interface SliceWorkerInfo {
40
43
  milestoneId: string;
41
44
  sliceId: string;
42
45
  pid: number;
46
+ workerToken: string;
47
+ processStartFingerprint: string | null;
43
48
  process: ChildProcess | null;
44
49
  worktreePath: string;
45
50
  startedAt: number;
@@ -69,13 +74,276 @@ export interface StartSliceParallelOpts {
69
74
 
70
75
  let sliceState: SliceOrchestratorState | null = null;
71
76
 
77
+ // ─── Persisted State (crash recovery) ──────────────────────────────────────
78
+ //
79
+ // Mirrors parallel-orchestrator.ts. Without persistence, a coordinator crash
80
+ // leaves orphaned worktrees on disk with no way to detect or clean them up
81
+ // on next session start. (Issue #4980 HIGH-8)
82
+
83
+ const SLICE_ORCHESTRATOR_STATE_FILE = "slice-orchestrator.json";
84
+ const TMP_SUFFIX = ".tmp";
85
+
86
+ interface PersistedSliceWorker {
87
+ milestoneId: string;
88
+ sliceId: string;
89
+ pid: number;
90
+ workerToken?: string;
91
+ processStartFingerprint?: string | null;
92
+ worktreePath: string;
93
+ startedAt: number;
94
+ state: "running" | "stopped" | "error";
95
+ completedUnits: number;
96
+ cost: number;
97
+ }
98
+
99
+ interface PersistedSliceState {
100
+ active: boolean;
101
+ workers: PersistedSliceWorker[];
102
+ totalCost: number;
103
+ budgetCeiling?: number;
104
+ maxWorkers: number;
105
+ startedAt: number;
106
+ basePath: string;
107
+ }
108
+
109
+ function sliceStateFilePath(basePath: string): string {
110
+ return join(gsdRoot(basePath), SLICE_ORCHESTRATOR_STATE_FILE);
111
+ }
112
+
113
+ function isPidAlive(pid: number): boolean {
114
+ if (!Number.isInteger(pid) || pid <= 0) return false;
115
+ try {
116
+ process.kill(pid, 0);
117
+ return true;
118
+ } catch (err) {
119
+ if ((err as NodeJS.ErrnoException).code === "EPERM") return true;
120
+ return false;
121
+ }
122
+ }
123
+
124
+ function readLinuxProcessStartFingerprint(pid: number): string | null {
125
+ try {
126
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf-8");
127
+ const afterCommand = stat.slice(stat.lastIndexOf(")") + 2).trim();
128
+ const fields = afterCommand.split(/\s+/);
129
+ const startTimeTicks = fields[19];
130
+ return startTimeTicks ? `linux-stat:${startTimeTicks}` : null;
131
+ } catch {
132
+ return null;
133
+ }
134
+ }
135
+
136
+ function readPsProcessStartFingerprint(pid: number): string | null {
137
+ try {
138
+ const raw = execFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
139
+ stdio: ["ignore", "pipe", "ignore"],
140
+ encoding: "utf-8",
141
+ }).trim().replace(/\s+/g, " ");
142
+ return raw ? `ps-lstart:${raw}` : null;
143
+ } catch {
144
+ return null;
145
+ }
146
+ }
147
+
148
+ function readProcessStartFingerprint(pid: number): string | null {
149
+ if (!Number.isInteger(pid) || pid <= 0) return null;
150
+ return readLinuxProcessStartFingerprint(pid) ?? readPsProcessStartFingerprint(pid);
151
+ }
152
+
153
+ function linuxProcessEnvContains(pid: number, key: string, value: string): boolean | null {
154
+ if (process.platform !== "linux") return null;
155
+ try {
156
+ const env = readFileSync(`/proc/${pid}/environ`, "utf-8");
157
+ return env.split("\0").includes(`${key}=${value}`);
158
+ } catch {
159
+ return null;
160
+ }
161
+ }
162
+
163
+ function createWorkerToken(milestoneId: string, sliceId: string): string {
164
+ return `slice:${milestoneId}:${sliceId}:${Date.now()}:${randomUUID()}`;
165
+ }
166
+
167
+ function isRecoveredSliceWorkerAlive(worker: {
168
+ pid: number;
169
+ workerToken?: string;
170
+ processStartFingerprint?: string | null;
171
+ }): boolean {
172
+ if (!isPidAlive(worker.pid)) return false;
173
+ if (!worker.processStartFingerprint) return false;
174
+
175
+ const currentFingerprint = readProcessStartFingerprint(worker.pid);
176
+ if (!currentFingerprint || currentFingerprint !== worker.processStartFingerprint) {
177
+ return false;
178
+ }
179
+
180
+ if (worker.workerToken) {
181
+ const envMatches = linuxProcessEnvContains(
182
+ worker.pid,
183
+ "GSD_SLICE_WORKER_TOKEN",
184
+ worker.workerToken,
185
+ );
186
+ if (envMatches === false) return false;
187
+ }
188
+
189
+ return true;
190
+ }
191
+
192
+ /**
193
+ * Persist current slice orchestrator state. Atomic write (tmp + rename) to
194
+ * prevent partial reads if the coordinator dies mid-write.
195
+ */
196
+ function persistSliceState(): void {
197
+ if (!sliceState) return;
198
+ try {
199
+ const dir = gsdRoot(sliceState.basePath);
200
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
201
+
202
+ const persisted: PersistedSliceState = {
203
+ active: sliceState.active,
204
+ workers: [...sliceState.workers.values()].map((w) => ({
205
+ milestoneId: w.milestoneId,
206
+ sliceId: w.sliceId,
207
+ pid: w.pid,
208
+ workerToken: w.workerToken,
209
+ processStartFingerprint: w.processStartFingerprint,
210
+ worktreePath: w.worktreePath,
211
+ startedAt: w.startedAt,
212
+ state: w.state,
213
+ completedUnits: w.completedUnits,
214
+ cost: w.cost,
215
+ })),
216
+ totalCost: sliceState.totalCost,
217
+ budgetCeiling: sliceState.budgetCeiling,
218
+ maxWorkers: sliceState.maxWorkers,
219
+ startedAt: sliceState.startedAt,
220
+ basePath: sliceState.basePath,
221
+ };
222
+
223
+ const dest = sliceStateFilePath(sliceState.basePath);
224
+ const tmp = dest + TMP_SUFFIX;
225
+ writeFileSync(tmp, JSON.stringify(persisted, null, 2), "utf-8");
226
+ renameSync(tmp, dest);
227
+ lastPersistTs = Date.now();
228
+ } catch {
229
+ /* non-fatal: persistence is best-effort */
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Throttled wrapper around `persistSliceState`. Skips if the last successful
235
+ * persist was less than `PERSIST_THROTTLE_MS` ago; otherwise persists
236
+ * immediately. Use this on hot paths (e.g. `message_end` events) where we
237
+ * receive many events per second per worker. Terminal events (worker exit,
238
+ * crash, stop) should call `persistSliceState()` directly to guarantee the
239
+ * final state hits disk regardless of timing.
240
+ */
241
+ const PERSIST_THROTTLE_MS = 1000;
242
+ let lastPersistTs = 0;
243
+
244
+ function persistSliceStateThrottled(): void {
245
+ if (Date.now() - lastPersistTs < PERSIST_THROTTLE_MS) return;
246
+ persistSliceState();
247
+ }
248
+
249
+ function removeSliceStateFile(basePath: string): void {
250
+ try {
251
+ const p = sliceStateFilePath(basePath);
252
+ if (existsSync(p)) unlinkSync(p);
253
+ } catch {
254
+ /* non-fatal */
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Restore slice orchestrator state from disk. Filters dead-PID workers and
260
+ * removes their orphaned worktrees so a clean restart is possible.
261
+ *
262
+ * Returns null if no state file exists or no workers survive.
263
+ */
264
+ export function restoreSliceState(basePath: string): PersistedSliceState | null {
265
+ try {
266
+ const p = sliceStateFilePath(basePath);
267
+ if (!existsSync(p)) return null;
268
+ const persisted = JSON.parse(readFileSync(p, "utf-8")) as PersistedSliceState;
269
+
270
+ const survivors: PersistedSliceWorker[] = [];
271
+ const dead: PersistedSliceWorker[] = [];
272
+ for (const w of persisted.workers) {
273
+ if (w.state === "running" && isRecoveredSliceWorkerAlive(w)) {
274
+ survivors.push(w);
275
+ } else if (w.state === "running") {
276
+ dead.push(w);
277
+ } else {
278
+ survivors.push(w);
279
+ }
280
+ }
281
+
282
+ // Best-effort cleanup of orphaned worktrees from dead workers.
283
+ for (const w of dead) {
284
+ const wtName = `${w.milestoneId}-${w.sliceId}`;
285
+ try {
286
+ removeWorktree(persisted.basePath, wtName, { deleteBranch: true, force: true });
287
+ } catch {
288
+ /* worktree may already be gone */
289
+ }
290
+ }
291
+
292
+ persisted.workers = survivors;
293
+
294
+ if (survivors.length === 0) {
295
+ removeSliceStateFile(basePath);
296
+ return null;
297
+ }
298
+
299
+ return persisted;
300
+ } catch {
301
+ return null;
302
+ }
303
+ }
304
+
72
305
  // ─── Public API ────────────────────────────────────────────────────────────
73
306
 
74
307
  /**
75
308
  * Check whether slice-level parallel is currently active.
309
+ *
310
+ * If in-memory state is unset but a persisted state file exists with at
311
+ * least one live-PID worker, treat as active and rehydrate so a coordinator
312
+ * crash followed by a fresh process is detectable. (Issue #4980 HIGH-8)
76
313
  */
77
- export function isSliceParallelActive(): boolean {
78
- return sliceState?.active === true;
314
+ export function isSliceParallelActive(basePath?: string): boolean {
315
+ if (sliceState?.active === true) return true;
316
+ if (!basePath) return false;
317
+ const restored = restoreSliceState(basePath);
318
+ if (!restored || restored.workers.length === 0) return false;
319
+
320
+ // Rehydrate in-memory state from disk; processes are detached so we have
321
+ // no ChildProcess handles, only PIDs.
322
+ sliceState = {
323
+ active: restored.active,
324
+ workers: new Map(),
325
+ totalCost: restored.totalCost,
326
+ budgetCeiling: restored.budgetCeiling,
327
+ maxWorkers: restored.maxWorkers,
328
+ startedAt: restored.startedAt,
329
+ basePath: restored.basePath,
330
+ };
331
+ for (const w of restored.workers) {
332
+ sliceState.workers.set(w.sliceId, {
333
+ milestoneId: w.milestoneId,
334
+ sliceId: w.sliceId,
335
+ pid: w.pid,
336
+ process: null,
337
+ worktreePath: w.worktreePath,
338
+ workerToken: w.workerToken ?? "",
339
+ processStartFingerprint: w.processStartFingerprint ?? null,
340
+ startedAt: w.startedAt,
341
+ state: w.state,
342
+ completedUnits: w.completedUnits,
343
+ cost: w.cost,
344
+ });
345
+ }
346
+ return true;
79
347
  }
80
348
 
81
349
  /**
@@ -146,6 +414,8 @@ export async function startSliceParallel(
146
414
  milestoneId,
147
415
  sliceId: slice.id,
148
416
  pid: 0,
417
+ workerToken: createWorkerToken(milestoneId, slice.id),
418
+ processStartFingerprint: null,
149
419
  process: null,
150
420
  worktreePath: wtPath,
151
421
  startedAt: Date.now(),
@@ -162,12 +432,16 @@ export async function startSliceParallel(
162
432
  started.push(slice.id);
163
433
  } else {
164
434
  errors.push({ sid: slice.id, error: "Failed to spawn worker process" });
165
- worker.state = "error";
435
+ sliceState.workers.delete(slice.id);
436
+ try {
437
+ removeWorktree(basePath, wtName, { deleteBranch: true, force: true });
438
+ } catch { /* ignore cleanup failures */ }
166
439
  }
167
440
  } catch (err) {
168
441
  errors.push({ sid: slice.id, error: getErrorMessage(err) });
169
442
  // Best-effort cleanup of partially created worktree
170
443
  const wtName = `${milestoneId}-${slice.id}`;
444
+ sliceState.workers.delete(slice.id);
171
445
  try {
172
446
  removeWorktree(basePath, wtName, { deleteBranch: true, force: true });
173
447
  } catch { /* ignore cleanup failures */ }
@@ -177,6 +451,10 @@ export async function startSliceParallel(
177
451
  // If nothing started, deactivate
178
452
  if (started.length === 0) {
179
453
  sliceState.active = false;
454
+ removeSliceStateFile(basePath);
455
+ } else {
456
+ // Persist state for crash recovery (Issue #4980 HIGH-8).
457
+ persistSliceState();
180
458
  }
181
459
 
182
460
  return { started, errors };
@@ -187,13 +465,16 @@ export async function startSliceParallel(
187
465
  */
188
466
  export function stopSliceParallel(): void {
189
467
  if (!sliceState) return;
468
+ const basePath = sliceState.basePath;
190
469
 
191
470
  for (const worker of sliceState.workers.values()) {
192
- if (worker.process) {
193
- try {
471
+ try {
472
+ if (worker.process) {
194
473
  worker.process.kill("SIGTERM");
195
- } catch { /* already dead */ }
196
- }
474
+ } else if (worker.state === "running" && isRecoveredSliceWorkerAlive(worker)) {
475
+ process.kill(worker.pid, "SIGTERM");
476
+ }
477
+ } catch { /* already dead */ }
197
478
  worker.cleanup?.();
198
479
  worker.cleanup = undefined;
199
480
  worker.process = null;
@@ -207,6 +488,9 @@ export function stopSliceParallel(): void {
207
488
  }
208
489
 
209
490
  sliceState.active = false;
491
+ // Clear persisted state — clean shutdown means no recovery on next start.
492
+ // (Issue #4980 HIGH-8)
493
+ removeSliceStateFile(basePath);
210
494
  }
211
495
 
212
496
  /**
@@ -239,6 +523,7 @@ export function resetSliceOrchestrator(): void {
239
523
  }
240
524
  }
241
525
  sliceState = null;
526
+ lastPersistTs = 0;
242
527
  }
243
528
 
244
529
  // ─── Internal: Conflict Filtering ──────────────────────────────────────────
@@ -339,6 +624,7 @@ function spawnSliceWorker(
339
624
  GSD_MILESTONE_LOCK: milestoneId,
340
625
  GSD_PROJECT_ROOT: basePath,
341
626
  GSD_PARALLEL_WORKER: "1",
627
+ GSD_SLICE_WORKER_TOKEN: worker.workerToken,
342
628
  },
343
629
  stdio: ["ignore", "pipe", "pipe"],
344
630
  detached: false,
@@ -357,9 +643,15 @@ function spawnSliceWorker(
357
643
 
358
644
  worker.process = child;
359
645
  worker.pid = child.pid ?? 0;
646
+ worker.processStartFingerprint = worker.pid > 0
647
+ ? readProcessStartFingerprint(worker.pid)
648
+ : null;
360
649
 
361
650
  if (!child.pid) {
362
651
  worker.process = null;
652
+ worker.pid = 0;
653
+ worker.processStartFingerprint = null;
654
+ try { child.kill("SIGTERM"); } catch { /* best-effort */ }
363
655
  return false;
364
656
  }
365
657
 
@@ -438,6 +730,10 @@ function spawnSliceWorker(
438
730
  startedAt: w.startedAt,
439
731
  worktreePath: w.worktreePath,
440
732
  });
733
+
734
+ // Persist worker terminal state for crash recovery.
735
+ // (Issue #4980 HIGH-8)
736
+ persistSliceState();
441
737
  });
442
738
 
443
739
  return true;
@@ -474,6 +770,11 @@ function processSliceWorkerLine(
474
770
  sliceState.totalCost += usage.cost;
475
771
  }
476
772
  worker.completedUnits++;
773
+ // Persist cost / progress updates so a crash mid-run preserves them.
774
+ // Throttled (~1/s per process) so high-frequency message_end traffic
775
+ // does not saturate disk I/O. Worker exit / start / stop paths persist
776
+ // unthrottled to guarantee the terminal state lands. (Issue #4980 HIGH-8)
777
+ persistSliceStateThrottled();
477
778
  }
478
779
  }
479
780
  }
@@ -0,0 +1,152 @@
1
+ import type { Phase } from "./types.js";
2
+
3
+ export type StateTransitionReasonCode =
4
+ | "state"
5
+ | "manual"
6
+ | "recovery"
7
+ | "dependency"
8
+ | "policy"
9
+ | "retry";
10
+
11
+ export interface StateTransitionEntry {
12
+ from: Phase | "*";
13
+ event: string;
14
+ guard: string;
15
+ to: Phase;
16
+ onFail: Phase | "manual-attention" | "blocked" | "no-transition";
17
+ reasonCode: StateTransitionReasonCode;
18
+ }
19
+
20
+ export const STATE_TRANSITION_MATRIX: readonly StateTransitionEntry[] = [
21
+ {
22
+ from: "needs-discussion",
23
+ event: "context-ready",
24
+ guard: "CONTEXT artifact exists or PRD/context express path produced context",
25
+ to: "researching",
26
+ onFail: "needs-discussion",
27
+ reasonCode: "state",
28
+ },
29
+ {
30
+ from: "researching",
31
+ event: "research-ready",
32
+ guard: "RESEARCH artifact exists or research is explicitly skipped",
33
+ to: "planning",
34
+ onFail: "researching",
35
+ reasonCode: "state",
36
+ },
37
+ {
38
+ from: "planning",
39
+ event: "plan-ready",
40
+ guard: "ROADMAP/PLAN artifacts exist and plan gate passes",
41
+ to: "executing",
42
+ onFail: "replanning-slice",
43
+ reasonCode: "state",
44
+ },
45
+ {
46
+ from: "executing",
47
+ event: "task-dispatched",
48
+ guard: "task inputs are ready and dependencies are closed",
49
+ to: "executing",
50
+ onFail: "blocked",
51
+ reasonCode: "dependency",
52
+ },
53
+ {
54
+ from: "executing",
55
+ event: "slice-complete",
56
+ guard: "all slice tasks are closed and verification gate passes",
57
+ to: "summarizing",
58
+ onFail: "validating-milestone",
59
+ reasonCode: "state",
60
+ },
61
+ {
62
+ from: "summarizing",
63
+ event: "summary-ready",
64
+ guard: "SUMMARY artifact exists for the completed work unit",
65
+ to: "validating-milestone",
66
+ onFail: "summarizing",
67
+ reasonCode: "state",
68
+ },
69
+ {
70
+ from: "validating-milestone",
71
+ event: "validation-pass",
72
+ guard: "validation verdict is terminal and not remediation-required",
73
+ to: "completing-milestone",
74
+ onFail: "blocked",
75
+ reasonCode: "state",
76
+ },
77
+ {
78
+ from: "blocked",
79
+ event: "recovery-plan-ready",
80
+ guard: "reassessment produced an executable next action",
81
+ to: "executing",
82
+ onFail: "blocked",
83
+ reasonCode: "recovery",
84
+ },
85
+ {
86
+ from: "replanning-slice",
87
+ event: "replan-ready",
88
+ guard: "replacement slice/task plan exists and plan gate passes",
89
+ to: "executing",
90
+ onFail: "blocked",
91
+ reasonCode: "recovery",
92
+ },
93
+ {
94
+ from: "completing-milestone",
95
+ event: "closeout-complete",
96
+ guard: "closeout gate passes and git transaction succeeds",
97
+ to: "complete",
98
+ onFail: "blocked",
99
+ reasonCode: "state",
100
+ },
101
+ {
102
+ from: "*",
103
+ event: "manual-block",
104
+ guard: "operator or hard gate requested manual attention",
105
+ to: "blocked",
106
+ onFail: "manual-attention",
107
+ reasonCode: "manual",
108
+ },
109
+ {
110
+ from: "*",
111
+ event: "retryable-failure",
112
+ guard: "retry budget remains for failure class",
113
+ to: "executing",
114
+ onFail: "blocked",
115
+ reasonCode: "retry",
116
+ },
117
+ ] as const;
118
+
119
+ export interface MatrixValidationResult {
120
+ ok: boolean;
121
+ missingEvents: string[];
122
+ duplicateKeys: string[];
123
+ }
124
+
125
+ export function findTransition(
126
+ from: Phase,
127
+ event: string,
128
+ ): StateTransitionEntry | undefined {
129
+ return STATE_TRANSITION_MATRIX.find((entry) =>
130
+ (entry.from === from || entry.from === "*") && entry.event === event,
131
+ );
132
+ }
133
+
134
+ export function validateTransitionMatrix(requiredEvents: readonly string[]): MatrixValidationResult {
135
+ const seen = new Set<string>();
136
+ const duplicateKeys: string[] = [];
137
+
138
+ for (const entry of STATE_TRANSITION_MATRIX) {
139
+ const key = `${entry.from}:${entry.event}`;
140
+ if (seen.has(key)) duplicateKeys.push(key);
141
+ seen.add(key);
142
+ }
143
+
144
+ const availableEvents = new Set(STATE_TRANSITION_MATRIX.map((entry) => entry.event));
145
+ const missingEvents = requiredEvents.filter((event) => !availableEvents.has(event));
146
+
147
+ return {
148
+ ok: missingEvents.length === 0 && duplicateKeys.length === 0,
149
+ missingEvents,
150
+ duplicateKeys,
151
+ };
152
+ }