gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0

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 (655) hide show
  1. package/README.md +1 -1
  2. package/dist/claude-cli-check.js +5 -1
  3. package/dist/headless.js +49 -4
  4. package/dist/loader.js +0 -0
  5. package/dist/resource-loader.d.ts +40 -0
  6. package/dist/resource-loader.js +32 -13
  7. package/dist/resources/extensions/browser-tools/capture.js +9 -0
  8. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  9. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  10. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  11. package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
  12. package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
  13. package/dist/resources/extensions/claude-code-cli/readiness.js +5 -1
  14. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
  15. package/dist/resources/extensions/github-sync/templates.js +103 -0
  16. package/dist/resources/extensions/google-search/index.js +3 -2
  17. package/dist/resources/extensions/gsd/auto/loop.js +124 -2
  18. package/dist/resources/extensions/gsd/auto/phases.js +57 -39
  19. package/dist/resources/extensions/gsd/auto/session.js +6 -2
  20. package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
  21. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  22. package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
  23. package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
  24. package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
  25. package/dist/resources/extensions/gsd/auto-start.js +107 -29
  26. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  27. package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
  28. package/dist/resources/extensions/gsd/auto.js +76 -21
  29. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
  30. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  31. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  34. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  35. package/dist/resources/extensions/gsd/component-types.js +69 -0
  36. package/dist/resources/extensions/gsd/context-store.js +23 -7
  37. package/dist/resources/extensions/gsd/detection.js +49 -1
  38. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  40. package/dist/resources/extensions/gsd/forensics.js +106 -0
  41. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  42. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  43. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  44. package/dist/resources/extensions/gsd/git-service.js +126 -2
  45. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  46. package/dist/resources/extensions/gsd/guided-flow.js +39 -13
  47. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  48. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  49. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  50. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  51. package/dist/resources/extensions/gsd/model-router.js +6 -0
  52. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  53. package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
  54. package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
  55. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  56. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  57. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  58. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  59. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  60. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  61. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  62. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  63. package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
  64. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  65. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  66. package/dist/resources/extensions/gsd/state.js +69 -58
  67. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  68. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
  69. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  70. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  71. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  72. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  73. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  74. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  75. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  76. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  77. package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
  78. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  79. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  80. package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
  81. package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
  82. package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
  83. package/dist/resources/extensions/mcp-client/index.js +3 -1
  84. package/dist/resources/extensions/ollama/index.js +5 -1
  85. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  86. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  87. package/dist/web/standalone/.next/BUILD_ID +1 -1
  88. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  89. package/dist/web/standalone/.next/build-manifest.json +3 -3
  90. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  91. package/dist/web/standalone/.next/required-server-files.json +3 -3
  92. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  93. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  103. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  119. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  131. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  151. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  161. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  167. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  181. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  183. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  185. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  187. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/index.html +1 -1
  197. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  198. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  199. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  200. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  201. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  202. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  203. package/dist/web/standalone/.next/server/app/page.js +2 -2
  204. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  206. package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
  207. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  208. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  209. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  211. package/dist/web/standalone/.next/server/middleware.js +2 -2
  212. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  214. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  215. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  216. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  217. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  218. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  219. package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +1 -0
  220. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  222. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  223. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  224. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  225. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  226. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  227. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  228. package/dist/web/standalone/server.js +1 -1
  229. package/package.json +2 -3
  230. package/packages/daemon/package.json +2 -2
  231. package/packages/daemon/src/logger.ts +4 -3
  232. package/packages/mcp-server/dist/server.d.ts +24 -0
  233. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  234. package/packages/mcp-server/dist/server.js +88 -87
  235. package/packages/mcp-server/dist/server.js.map +1 -1
  236. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  237. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  238. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  239. package/packages/mcp-server/package.json +2 -2
  240. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  241. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  242. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  243. package/packages/mcp-server/src/server.ts +131 -105
  244. package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
  245. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  246. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  247. package/packages/native/package.json +2 -2
  248. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  249. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  250. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  251. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  252. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  253. package/packages/pi-agent-core/package.json +1 -1
  254. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  255. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  256. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  257. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  258. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  259. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  260. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  261. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  262. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  263. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  264. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  265. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  266. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  267. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  268. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  269. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  270. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  271. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  272. package/packages/pi-ai/dist/models.test.js +36 -11
  273. package/packages/pi-ai/dist/models.test.js.map +1 -1
  274. package/packages/pi-ai/package.json +1 -1
  275. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  276. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  277. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  278. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  279. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  280. package/packages/pi-ai/src/models.test.ts +48 -11
  281. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  282. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  283. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  285. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  287. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  288. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  289. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  291. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  293. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  294. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  295. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  297. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  300. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  302. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  304. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  305. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  306. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  307. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  308. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  310. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  312. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  313. package/packages/pi-coding-agent/dist/index.js +1 -0
  314. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  315. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
  316. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  317. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  318. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  320. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
  321. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  323. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  324. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  325. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  326. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  328. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  330. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  331. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  333. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  335. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  336. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  337. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  338. package/packages/pi-coding-agent/package.json +1 -1
  339. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  340. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  341. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  342. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  343. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  344. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  345. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  346. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  347. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  348. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  349. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  350. package/packages/pi-coding-agent/src/index.ts +1 -0
  351. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
  352. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  353. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
  354. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  355. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  356. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  357. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  358. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  359. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  360. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  361. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  362. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  363. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  364. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +37 -11
  365. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  366. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  367. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  368. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  369. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  370. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  371. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  372. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  373. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  374. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  375. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  376. package/packages/pi-tui/dist/components/editor.js +19 -0
  377. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  378. package/packages/pi-tui/dist/components/image.test.js +6 -5
  379. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  380. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  381. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  382. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  383. package/packages/pi-tui/package.json +1 -1
  384. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  385. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  386. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +42 -11
  387. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  388. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  389. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  390. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  391. package/packages/pi-tui/src/components/editor.ts +22 -0
  392. package/packages/pi-tui/src/components/image.test.ts +10 -5
  393. package/packages/pi-tui/src/editor-component.ts +3 -0
  394. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  395. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  396. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  397. package/packages/rpc-client/package.json +1 -1
  398. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  399. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  400. package/pkg/package.json +1 -1
  401. package/scripts/install.js +15 -1
  402. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  403. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  404. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  405. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  406. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  407. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  408. package/src/resources/extensions/claude-code-cli/readiness.ts +5 -1
  409. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
  410. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
  411. package/src/resources/extensions/github-sync/templates.ts +151 -0
  412. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  413. package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
  414. package/src/resources/extensions/google-search/index.ts +3 -2
  415. package/src/resources/extensions/gsd/auto/loop.ts +142 -2
  416. package/src/resources/extensions/gsd/auto/phases.ts +62 -38
  417. package/src/resources/extensions/gsd/auto/session.ts +7 -2
  418. package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
  419. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  420. package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
  421. package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
  422. package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
  423. package/src/resources/extensions/gsd/auto-start.ts +127 -9
  424. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  425. package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
  426. package/src/resources/extensions/gsd/auto.ts +90 -23
  427. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
  428. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  429. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
  430. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  431. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  432. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  433. package/src/resources/extensions/gsd/component-types.ts +362 -0
  434. package/src/resources/extensions/gsd/context-store.ts +25 -8
  435. package/src/resources/extensions/gsd/detection.ts +58 -1
  436. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
  437. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  438. package/src/resources/extensions/gsd/forensics.ts +118 -1
  439. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  440. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  441. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  442. package/src/resources/extensions/gsd/git-service.ts +149 -2
  443. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  444. package/src/resources/extensions/gsd/guided-flow.ts +57 -14
  445. package/src/resources/extensions/gsd/journal.ts +11 -1
  446. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  447. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  448. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  449. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  450. package/src/resources/extensions/gsd/model-router.ts +6 -0
  451. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  452. package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
  453. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
  454. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  455. package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  456. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  457. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  458. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  459. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  460. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  461. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  462. package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
  463. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  464. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  465. package/src/resources/extensions/gsd/state.ts +76 -66
  466. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  467. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  468. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
  469. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  470. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  471. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +133 -292
  472. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  473. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  474. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  475. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  476. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
  477. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
  478. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
  479. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
  480. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  481. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
  482. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
  483. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
  484. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
  485. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  486. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  487. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  488. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  489. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  490. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
  491. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  492. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  493. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  494. package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
  495. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
  496. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  497. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
  498. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  499. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  500. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  501. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  502. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
  503. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
  504. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
  505. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
  506. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  507. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  508. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  509. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
  510. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
  511. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  512. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  513. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
  514. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  515. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  516. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
  517. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  518. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  519. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
  520. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  521. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  522. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  523. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  524. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  525. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  526. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
  527. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  528. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
  529. package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
  530. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
  531. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  532. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
  533. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  534. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  535. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  536. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  537. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
  538. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  539. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
  540. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
  541. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  542. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  543. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
  544. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
  545. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
  546. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
  547. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
  548. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
  549. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
  550. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  551. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  552. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  553. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  554. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  555. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
  556. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  557. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  558. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  559. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
  560. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  561. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  562. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  563. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  564. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
  565. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
  566. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  567. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
  568. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  569. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
  570. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  571. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
  572. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  573. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
  574. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  575. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  576. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
  577. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  578. package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
  579. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  580. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  581. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  582. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  583. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  584. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  585. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  586. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  587. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  588. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  589. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  590. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
  591. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  592. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
  593. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
  594. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  595. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  596. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  597. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  598. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  599. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  600. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  601. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  602. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
  603. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  604. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  605. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  606. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  607. package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
  608. package/src/resources/extensions/gsd/types.ts +3 -3
  609. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  610. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  611. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  612. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  613. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  614. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  615. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  616. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  617. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  618. package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
  619. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  620. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  621. package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
  622. package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
  623. package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
  624. package/src/resources/extensions/mcp-client/index.ts +3 -1
  625. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  626. package/src/resources/extensions/ollama/index.ts +5 -1
  627. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  628. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  629. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  630. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  631. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  632. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  633. package/dist/web/standalone/.next/static/chunks/app/page-5b113fd32bc2a1c3.js +0 -1
  634. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  635. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  636. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  637. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  638. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  639. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  640. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  641. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
  642. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  643. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  644. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  645. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  646. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  647. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  648. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
  649. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  650. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  651. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  652. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
  653. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
  654. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → C1zT2kEfoLhDdbWPWKrXd}/_buildManifest.js +0 -0
  655. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → C1zT2kEfoLhDdbWPWKrXd}/_ssgManifest.js +0 -0
@@ -35,11 +35,12 @@ import { getAutoWorktreePath } from "./auto-worktree.js";
35
35
  import { loadEffectiveGSDPreferences, loadGlobalGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
36
36
  import { showNextAction } from "../shared/tui.js";
37
37
  import { ensurePreferencesFile, serializePreferencesToFrontmatter } from "./commands-prefs-wizard.js";
38
+ import { summarizeWorktreeTelemetry, percentile, type WorktreeTelemetrySummary } from "./worktree-telemetry.js";
38
39
 
39
40
  // ─── Types ────────────────────────────────────────────────────────────────────
40
41
 
41
42
  export interface ForensicAnomaly {
42
- type: "stuck-loop" | "cost-spike" | "timeout" | "missing-artifact" | "crash" | "doctor-issue" | "error-trace" | "journal-stuck" | "journal-guard-block" | "journal-rapid-iterations" | "journal-worktree-failure";
43
+ type: "stuck-loop" | "cost-spike" | "timeout" | "missing-artifact" | "crash" | "doctor-issue" | "error-trace" | "journal-stuck" | "journal-guard-block" | "journal-rapid-iterations" | "journal-worktree-failure" | "worktree-orphan" | "worktree-unmerged-exit";
43
44
  severity: "info" | "warning" | "error";
44
45
  unitType?: string;
45
46
  unitId?: string;
@@ -113,6 +114,8 @@ interface ForensicReport {
113
114
  recentUnits: { type: string; id: string; cost: number; duration: number; model: string; finishedAt: number }[];
114
115
  journalSummary: JournalSummary | null;
115
116
  activityLogMeta: ActivityLogMeta | null;
117
+ /** #4764 — worktree lifespan / divergence telemetry aggregates. */
118
+ worktreeTelemetry: WorktreeTelemetrySummary | null;
116
119
  }
117
120
 
118
121
  // ─── Duplicate Detection ──────────────────────────────────────────────────────
@@ -337,6 +340,16 @@ export async function buildForensicReport(basePath: string): Promise<ForensicRep
337
340
  detectCrash(crashLock, anomalies);
338
341
  detectDoctorIssues(doctorIssues, anomalies);
339
342
  detectErrorTraces(unitTraces, anomalies);
343
+
344
+ // 11b. #4764 — worktree lifecycle telemetry
345
+ let worktreeTelemetry: WorktreeTelemetrySummary | null = null;
346
+ try {
347
+ worktreeTelemetry = summarizeWorktreeTelemetry(basePath);
348
+ detectWorktreeOrphans(worktreeTelemetry, anomalies);
349
+ } catch {
350
+ // Telemetry is best-effort — do not let an aggregator failure block the
351
+ // rest of the forensic report.
352
+ }
340
353
  detectJournalAnomalies(journalSummary, anomalies);
341
354
 
342
355
  return {
@@ -356,6 +369,7 @@ export async function buildForensicReport(basePath: string): Promise<ForensicRep
356
369
  recentUnits,
357
370
  journalSummary,
358
371
  activityLogMeta,
372
+ worktreeTelemetry,
359
373
  };
360
374
  }
361
375
 
@@ -783,6 +797,51 @@ function detectMissingArtifacts(completedKeys: string[], basePath: string, activ
783
797
  }
784
798
  }
785
799
 
800
+ /**
801
+ * #4764 — surface worktree lifecycle and orphan signals in the forensic report.
802
+ *
803
+ * Consumes only the aggregated summary (not raw journal events) to respect
804
+ * the forensics memory-bloat guard in forensics-journal.test.ts — per-event
805
+ * detail stays in the journal itself where the LLM can query it on demand.
806
+ */
807
+ function detectWorktreeOrphans(
808
+ summary: WorktreeTelemetrySummary,
809
+ anomalies: ForensicAnomaly[],
810
+ ): void {
811
+ // 1. Orphan aggregate — severity depends on reason. In-progress orphans are
812
+ // the #4761 consumer-side signal (live work sitting on an unmerged branch).
813
+ for (const [reason, count] of Object.entries(summary.orphansByReason)) {
814
+ if (count <= 0) continue;
815
+ const severity: ForensicAnomaly["severity"] =
816
+ reason === "in-progress-unmerged" ? "warning" : "info";
817
+ anomalies.push({
818
+ type: "worktree-orphan",
819
+ severity,
820
+ summary: `${count} worktree orphan(s) detected (${reason})`,
821
+ details:
822
+ reason === "in-progress-unmerged"
823
+ ? "Auto-mode exited without completing a milestone; live work sits on an unmerged milestone branch. Run `/gsd auto` to resume, or merge manually."
824
+ : reason === "complete-unmerged"
825
+ ? "A completed milestone's branch was never merged back to main. Run `/gsd health --fix` to resolve."
826
+ : `Reason: ${reason}.`,
827
+ });
828
+ }
829
+
830
+ // 2. Auto-exit producer signal — #4761's upstream cause.
831
+ if (summary.exitsWithUnmergedWork > 0) {
832
+ const reasonBreakdown = Object.entries(summary.exitsByReason)
833
+ .filter(([, n]) => n > 0)
834
+ .map(([r, n]) => `${r}=${n}`)
835
+ .join(", ");
836
+ anomalies.push({
837
+ type: "worktree-unmerged-exit",
838
+ severity: "warning",
839
+ summary: `${summary.exitsWithUnmergedWork} auto-exit(s) left milestone work unmerged`,
840
+ details: `Exit reasons: ${reasonBreakdown || "(none)"} · Producer-side signal for #4761-class orphans. Inspect .gsd/journal/*.jsonl with eventType:"auto-exit" for per-exit detail.`,
841
+ });
842
+ }
843
+ }
844
+
786
845
  function detectCrash(crashLock: LockData | null, anomalies: ForensicAnomaly[]): void {
787
846
  if (!crashLock) return;
788
847
  if (isLockProcessAlive(crashLock)) return; // Process still running, not a crash
@@ -972,6 +1031,40 @@ function saveForensicReport(basePath: string, report: ForensicReport, problemDes
972
1031
  sections.push(``);
973
1032
  }
974
1033
 
1034
+ // #4764 — Worktree telemetry summary
1035
+ if (report.worktreeTelemetry) {
1036
+ const t = report.worktreeTelemetry;
1037
+ const p50 = percentile(t.mergeDurationsMs, 0.5);
1038
+ const p95 = percentile(t.mergeDurationsMs, 0.95);
1039
+ sections.push(`## Worktree Telemetry`, ``);
1040
+ sections.push(`- Worktrees created: ${t.worktreesCreated}`);
1041
+ sections.push(`- Worktrees merged: ${t.worktreesMerged}`);
1042
+ sections.push(`- Orphans detected: ${t.orphansDetected}`);
1043
+ if (t.orphansDetected > 0) {
1044
+ const breakdown = Object.entries(t.orphansByReason)
1045
+ .map(([r, n]) => `${r}=${n}`).join(", ");
1046
+ sections.push(` - By reason: ${breakdown}`);
1047
+ }
1048
+ sections.push(`- Merge conflicts: ${t.mergeConflicts}`);
1049
+ if (t.mergeDurationsMs.length > 0) {
1050
+ sections.push(`- Merge duration p50 / p95: ${p50 ?? "-"} / ${p95 ?? "-"} ms (n=${t.mergeDurationsMs.length})`);
1051
+ }
1052
+ sections.push(`- Auto-exits leaving unmerged work: ${t.exitsWithUnmergedWork}`);
1053
+ if (Object.keys(t.exitsByReason).length > 0) {
1054
+ const breakdown = Object.entries(t.exitsByReason)
1055
+ .sort((a, b) => b[1] - a[1])
1056
+ .map(([r, n]) => `${r}=${n}`).join(", ");
1057
+ sections.push(` - Exit reasons: ${breakdown}`);
1058
+ }
1059
+ sections.push(`- Canonical-root redirects (#4761 fix fired): ${t.canonicalRedirects}`);
1060
+ // #4765 slice-cadence counters
1061
+ if (t.slicesMerged + t.sliceMergeConflicts + t.milestoneResquashes > 0) {
1062
+ sections.push(`- Slices merged: ${t.slicesMerged} · Slice merge conflicts: ${t.sliceMergeConflicts}`);
1063
+ sections.push(`- Milestone re-squashes: ${t.milestoneResquashes}`);
1064
+ }
1065
+ sections.push(``);
1066
+ }
1067
+
975
1068
  // Journal summary
976
1069
  if (report.journalSummary) {
977
1070
  const js = report.journalSummary;
@@ -1117,6 +1210,30 @@ function formatReportForPrompt(report: ForensicReport): string {
1117
1210
  sections.push("");
1118
1211
  }
1119
1212
 
1213
+ // #4764 — worktree telemetry (compact prompt form)
1214
+ if (report.worktreeTelemetry) {
1215
+ const t = report.worktreeTelemetry;
1216
+ const hasSignal =
1217
+ t.worktreesCreated + t.worktreesMerged + t.orphansDetected +
1218
+ t.exitsWithUnmergedWork + t.canonicalRedirects +
1219
+ t.slicesMerged + t.milestoneResquashes > 0;
1220
+ if (hasSignal) {
1221
+ sections.push("### Worktree Telemetry");
1222
+ sections.push(`- Created: ${t.worktreesCreated} · Merged: ${t.worktreesMerged} · Conflicts: ${t.mergeConflicts}`);
1223
+ sections.push(`- Orphans: ${t.orphansDetected} · Unmerged exits: ${t.exitsWithUnmergedWork} · Redirects (#4761): ${t.canonicalRedirects}`);
1224
+ if (t.orphansDetected > 0) {
1225
+ const breakdown = Object.entries(t.orphansByReason)
1226
+ .map(([r, n]) => `${r}=${n}`).join(", ");
1227
+ sections.push(`- Orphan reasons: ${breakdown}`);
1228
+ }
1229
+ // #4765 — slice-cadence counters (only shown when the feature was exercised)
1230
+ if (t.slicesMerged + t.sliceMergeConflicts + t.milestoneResquashes > 0) {
1231
+ sections.push(`- Slices merged: ${t.slicesMerged} · Slice conflicts: ${t.sliceMergeConflicts} · Re-squashes: ${t.milestoneResquashes}`);
1232
+ }
1233
+ sections.push("");
1234
+ }
1235
+ }
1236
+
1120
1237
  // Activity log metadata
1121
1238
  if (report.activityLogMeta) {
1122
1239
  const meta = report.activityLogMeta;
@@ -60,9 +60,9 @@ export const GATE_REGISTRY = {
60
60
  id: "Q4",
61
61
  scope: "slice",
62
62
  ownerTurn: "gate-evaluate",
63
- question: "What existing promises does this break?",
63
+ question: "Which existing requirements (R-IDs) does this slice touch, and which must be re-tested?",
64
64
  guidance: [
65
- "List which existing requirements (R001, R003, etc.) are touched by this slice.",
65
+ "List the R-IDs (e.g. R001, R003) touched by this slice; see the milestone requirements artifact at .gsd/milestones/<id>/REQUIREMENTS.md.",
66
66
  "Identify what must be re-tested after shipping.",
67
67
  "Flag decisions that should be revisited given the new scope.",
68
68
  "If no existing requirements are affected, return verdict 'omitted'.",
@@ -2,9 +2,38 @@
2
2
  * Shared git constants used across git-service and native-git-bridge.
3
3
  */
4
4
 
5
+ /**
6
+ * Parent process env vars that, if leaked into a git child process, can
7
+ * silently redirect every operation to a different repo or index.
8
+ *
9
+ * Stripped from GIT_NO_PROMPT_ENV so a GSD invoked from inside a git hook,
10
+ * a different worktree's terminal, or any context that pre-set these vars
11
+ * cannot redirect GSD's git operations to the wrong target.
12
+ * (Issue #4980 NEW-1)
13
+ */
14
+ const LEAKING_GIT_ENV_VARS = [
15
+ "GIT_DIR",
16
+ "GIT_WORK_TREE",
17
+ "GIT_INDEX_FILE",
18
+ "GIT_OBJECT_DIRECTORY",
19
+ "GIT_ALTERNATE_OBJECT_DIRECTORIES",
20
+ "GIT_COMMON_DIR",
21
+ "GIT_NAMESPACE",
22
+ ] as const;
23
+
24
+ function buildSafeParentEnv(): NodeJS.ProcessEnv {
25
+ const safe: NodeJS.ProcessEnv = {};
26
+ for (const [k, v] of Object.entries(process.env)) {
27
+ if (!LEAKING_GIT_ENV_VARS.includes(k as (typeof LEAKING_GIT_ENV_VARS)[number])) {
28
+ safe[k] = v;
29
+ }
30
+ }
31
+ return safe;
32
+ }
33
+
5
34
  /** Env overlay that suppresses interactive git credential prompts and git-svn noise. */
6
35
  export const GIT_NO_PROMPT_ENV = {
7
- ...process.env,
36
+ ...buildSafeParentEnv(),
8
37
  GIT_TERMINAL_PROMPT: "0",
9
38
  GIT_ASKPASS: "",
10
39
  GIT_SVN_ID: "",
@@ -10,6 +10,7 @@
10
10
  * user-friendly messages suggesting `/gsd doctor`.
11
11
  */
12
12
 
13
+ import { execFileSync } from "node:child_process";
13
14
  import { existsSync, unlinkSync } from "node:fs";
14
15
  import { join } from "node:path";
15
16
  import { MergeConflictError } from "./git-service.js";
@@ -24,6 +25,18 @@ export interface AbortAndResetResult {
24
25
  cleaned: string[];
25
26
  }
26
27
 
28
+ function hasWorkingTreeChanges(cwd: string): boolean {
29
+ try {
30
+ return execFileSync("git", ["status", "--porcelain"], {
31
+ cwd,
32
+ stdio: ["ignore", "pipe", "pipe"],
33
+ encoding: "utf-8",
34
+ }).trim().length > 0;
35
+ } catch {
36
+ return true;
37
+ }
38
+ }
39
+
27
40
  /**
28
41
  * Detect and clean up leftover merge/rebase state, then hard-reset.
29
42
  *
@@ -70,6 +83,24 @@ export function abortAndReset(cwd: string): AbortAndResetResult {
70
83
  }
71
84
  }
72
85
 
86
+ // Preserve any staged or untracked user work before the hard reset.
87
+ // Reset --hard discards staged changes (reflog only covers committed
88
+ // state), so a labeled stash gives the user a recovery handle if their
89
+ // in-flight inspection work would otherwise be silently lost.
90
+ // (Issue #4980 HIGH-5)
91
+ if (hasWorkingTreeChanges(cwd)) {
92
+ try {
93
+ execFileSync(
94
+ "git",
95
+ ["stash", "push", "--include-untracked", "-m", `gsd: pre-self-heal-reset ${new Date().toISOString()}`],
96
+ { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" },
97
+ );
98
+ cleaned.push("stashed working tree before reset");
99
+ } catch {
100
+ /* nothing to stash, or stash refused (e.g. unresolved conflicts) — proceed */
101
+ }
102
+ }
103
+
73
104
  // Always hard-reset to HEAD
74
105
  try {
75
106
  nativeResetHard(cwd);
@@ -8,7 +8,7 @@
8
8
  * paths, commit type inference, and the runGit shell helper.
9
9
  */
10
10
 
11
- import { execFileSync, execSync } from "node:child_process";
11
+ import { execFileSync } from "node:child_process";
12
12
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
13
13
  import { join } from "node:path";
14
14
  import { gsdRoot } from "./paths.js";
@@ -85,6 +85,22 @@ export interface GitPreferences {
85
85
  * for forensic inspection.
86
86
  */
87
87
  absorb_snapshot_commits?: boolean;
88
+ /** #4765 — when to collapse worktree commits back to main.
89
+ * - "milestone" (default): existing behavior — squash-merge happens once
90
+ * at milestone completion or transition.
91
+ * - "slice": squash-merge each slice's commits to main as soon as the
92
+ * slice passes validation. Shrinks the orphan window from
93
+ * milestone-size to slice-size and surfaces merge conflicts per slice
94
+ * rather than all at once at milestone end.
95
+ */
96
+ collapse_cadence?: "milestone" | "slice";
97
+ /** #4765 — when `collapse_cadence: "slice"`, optionally re-squash the per-
98
+ * slice commits on main into one milestone commit at milestone completion.
99
+ * Preserves the "one commit per milestone in main" history shape that
100
+ * `collapse_cadence: "milestone"` produces today.
101
+ * Default: true when collapse_cadence is "slice", ignored otherwise.
102
+ */
103
+ milestone_resquash?: boolean;
88
104
  }
89
105
 
90
106
  export const VALID_BRANCH_NAME = /^[a-zA-Z0-9_\-\/.]+$/;
@@ -393,6 +409,111 @@ export function resolveMilestoneIntegrationBranch(
393
409
  };
394
410
  }
395
411
 
412
+ // ─── Pre-Merge Command Tokenizer ──────────────────────────────────────────
413
+
414
+ /**
415
+ * Tokenize a user-supplied pre-merge command string into argv form, with
416
+ * minimal support for double- and single-quoted strings. Designed to be
417
+ * sufficient for typical commands ("npm test", `npm run lint:ci`,
418
+ * `pnpm run tsc --noEmit`) without spawning a shell.
419
+ *
420
+ * Returns [] when the input is empty or whitespace-only.
421
+ * Throws when quoting is malformed.
422
+ *
423
+ * Used by GitServiceImpl.runPreMergeCheck to eliminate the shell-injection
424
+ * surface that running an arbitrary user string through a shell would create.
425
+ * (Issue #4980 HIGH-2)
426
+ */
427
+ export function tokenizePreMergeCommand(input: string): string[] {
428
+ const tokens: string[] = [];
429
+ let current = "";
430
+ let i = 0;
431
+ let quote: "" | "'" | '"' = "";
432
+ let hasContent = false;
433
+
434
+ while (i < input.length) {
435
+ const ch = input[i]!;
436
+ if (quote) {
437
+ if (ch === quote) {
438
+ quote = "";
439
+ } else if (ch === "\\" && quote === '"' && i + 1 < input.length) {
440
+ current += input[i + 1];
441
+ i += 2;
442
+ continue;
443
+ } else {
444
+ current += ch;
445
+ }
446
+ i++;
447
+ continue;
448
+ }
449
+ if (ch === '"' || ch === "'") {
450
+ quote = ch;
451
+ hasContent = true;
452
+ i++;
453
+ continue;
454
+ }
455
+ if (ch === " " || ch === "\t") {
456
+ if (hasContent) {
457
+ tokens.push(current);
458
+ current = "";
459
+ hasContent = false;
460
+ }
461
+ i++;
462
+ continue;
463
+ }
464
+ if (ch === "\\" && i + 1 < input.length) {
465
+ current += input[i + 1];
466
+ i += 2;
467
+ hasContent = true;
468
+ continue;
469
+ }
470
+ current += ch;
471
+ hasContent = true;
472
+ i++;
473
+ }
474
+
475
+ if (quote) {
476
+ throw new Error(`Unterminated ${quote === '"' ? "double" : "single"} quote in pre-merge command`);
477
+ }
478
+ if (hasContent) tokens.push(current);
479
+ return tokens;
480
+ }
481
+
482
+ function containsUnquotedShellControl(input: string): boolean {
483
+ let i = 0;
484
+ let quote: "" | "'" | '"' = "";
485
+
486
+ while (i < input.length) {
487
+ const ch = input[i]!;
488
+ if (quote) {
489
+ if (ch === quote) {
490
+ quote = "";
491
+ } else if (ch === "\\" && quote === '"' && i + 1 < input.length) {
492
+ i += 2;
493
+ continue;
494
+ }
495
+ i++;
496
+ continue;
497
+ }
498
+
499
+ if (ch === '"' || ch === "'") {
500
+ quote = ch;
501
+ i++;
502
+ continue;
503
+ }
504
+ if (ch === "\\" && i + 1 < input.length) {
505
+ i += 2;
506
+ continue;
507
+ }
508
+ if (ch === ";" || ch === "&" || ch === "|" || ch === "`" || ch === "$" || ch === "<" || ch === ">") {
509
+ return true;
510
+ }
511
+ i++;
512
+ }
513
+
514
+ return false;
515
+ }
516
+
396
517
  // ─── Git Helper ────────────────────────────────────────────────────────────
397
518
 
398
519
 
@@ -786,8 +907,34 @@ export class GitServiceImpl {
786
907
  }
787
908
  }
788
909
 
910
+ // Tokenize and run via execFileSync (no shell). Shell metacharacters in
911
+ // user-supplied prefs.pre_merge_check would otherwise be interpreted as
912
+ // chaining/redirection (e.g. `;`, `&&`, `|`, backticks) — a privesc
913
+ // surface in repos with a checked-in `.gsd/PREFERENCES.md`.
914
+ // (Issue #4980 HIGH-2)
915
+ if (containsUnquotedShellControl(command)) {
916
+ return {
917
+ passed: false,
918
+ skipped: false,
919
+ command,
920
+ error:
921
+ "pre_merge_check contains shell metacharacters (;, &&, |, $, backticks, redirects). " +
922
+ "Put complex commands in a script file (e.g. './scripts/pre-merge.sh') and reference the script path instead.",
923
+ };
924
+ }
925
+
926
+ const tokens = tokenizePreMergeCommand(command);
927
+ if (tokens.length === 0) {
928
+ return { passed: true, skipped: true };
929
+ }
930
+
789
931
  try {
790
- execSync(command, { cwd: this.basePath, stdio: "pipe", encoding: "utf-8" });
932
+ execFileSync(tokens[0]!, tokens.slice(1), {
933
+ cwd: this.basePath,
934
+ stdio: "pipe",
935
+ encoding: "utf-8",
936
+ env: GIT_NO_PROMPT_ENV,
937
+ });
791
938
  return { passed: true, skipped: false, command };
792
939
  } catch (err) {
793
940
  const msg = getErrorMessage(err);
@@ -180,7 +180,7 @@ function openRawDb(path: string): unknown {
180
180
  return new Database(path);
181
181
  }
182
182
 
183
- const SCHEMA_VERSION = 22;
183
+ export const SCHEMA_VERSION = 22;
184
184
 
185
185
  function indexExists(db: DbAdapter, name: string): boolean {
186
186
  return !!db.prepare(
@@ -2946,6 +2946,9 @@ export function insertAssessment(entry: {
2946
2946
  fullContent: string;
2947
2947
  }): void {
2948
2948
  if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
2949
+ // Idempotent: PRIMARY KEY is `path`, which is deterministic given (milestone_id, scope) per
2950
+ // the artifact-path resolver. Retrying the same reassess-roadmap silently overwrites the row
2951
+ // instead of accumulating duplicates.
2949
2952
  currentDb.prepare(
2950
2953
  `INSERT OR REPLACE INTO assessments (path, milestone_id, slice_id, task_id, status, scope, full_content, created_at)
2951
2954
  VALUES (:path, :milestone_id, :slice_id, :task_id, :status, :scope, :full_content, :created_at)`,
@@ -3100,7 +3103,7 @@ function rowToGate(row: Record<string, unknown>): GateRow {
3100
3103
  scope: row["scope"] as GateScope,
3101
3104
  task_id: (row["task_id"] as string) ?? "",
3102
3105
  status: row["status"] as GateStatus,
3103
- verdict: (row["verdict"] as GateVerdict) || "",
3106
+ verdict: row["status"] === "pending" ? null : (row["verdict"] as GateVerdict),
3104
3107
  rationale: (row["rationale"] as string) || "",
3105
3108
  findings: (row["findings"] as string) || "",
3106
3109
  evaluated_at: (row["evaluated_at"] as string) ?? null,
@@ -3204,7 +3207,7 @@ export function getGateResults(milestoneId: string, sliceId: string, scope?: Gat
3204
3207
  export function markAllGatesOmitted(milestoneId: string, sliceId: string): void {
3205
3208
  if (!currentDb) return;
3206
3209
  currentDb.prepare(
3207
- `UPDATE quality_gates SET status = 'omitted', verdict = 'omitted', evaluated_at = :now
3210
+ `UPDATE quality_gates SET status = 'complete', verdict = 'omitted', evaluated_at = :now
3208
3211
  WHERE milestone_id = :mid AND slice_id = :sid AND status = 'pending'`,
3209
3212
  ).run({
3210
3213
  ":mid": milestoneId,
@@ -13,7 +13,7 @@ import { loadFile, saveFile } from "./files.js";
13
13
  import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
14
14
  import { parseRoadmapSlices } from "./roadmap-slices.js";
15
15
  import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
16
- import { buildSkillActivationBlock } from "./auto-prompts.js";
16
+ import { buildDiscussMilestonePrompt, buildSkillActivationBlock } from "./auto-prompts.js";
17
17
  import { deriveState } from "./state.js";
18
18
  import { invalidateAllCaches } from "./cache.js";
19
19
  import { startAutoDetached } from "./auto.js";
@@ -38,8 +38,8 @@ import { isInheritedRepo } from "./repo-identity.js";
38
38
  import { ensureGitignore, ensurePreferences, untrackRuntimeFiles } from "./gitignore.js";
39
39
  import { loadEffectiveGSDPreferences } from "./preferences.js";
40
40
  import { resolveUokFlags } from "./uok/flags.js";
41
- import { ensurePlanV2Graph } from "./uok/plan-v2.js";
42
- import { detectProjectState } from "./detection.js";
41
+ import { ensurePlanV2Graph, isMissingFinalizedContextResult } from "./uok/plan-v2.js";
42
+ import { detectProjectState, hasGsdBootstrapArtifacts } from "./detection.js";
43
43
  import { showProjectInit, offerMigration } from "./init-wizard.js";
44
44
  import { validateDirectory } from "./validate-directory.js";
45
45
  import { showConfirm } from "../shared/tui.js";
@@ -93,24 +93,29 @@ function needsPlanV2Gate(state: GSDState): boolean {
93
93
  || state.phase === "completing-milestone";
94
94
  }
95
95
 
96
+ type PlanV2GateDecision = "pass" | "recover-missing-context" | "block";
97
+
96
98
  function runPlanV2Gate(
97
99
  ctx: ExtensionContext,
98
100
  basePath: string,
99
101
  state: GSDState,
100
- ): boolean {
102
+ ): PlanV2GateDecision {
101
103
  const prefs = loadEffectiveGSDPreferences()?.preferences;
102
104
  const uokFlags = resolveUokFlags(prefs);
103
- if (!uokFlags.planV2 || !needsPlanV2Gate(state)) return true;
105
+ if (!uokFlags.planV2 || !needsPlanV2Gate(state)) return "pass";
104
106
  const compiled = ensurePlanV2Graph(basePath, state);
105
107
  if (!compiled.ok) {
108
+ if (isMissingFinalizedContextResult(compiled)) {
109
+ return "recover-missing-context";
110
+ }
106
111
  const reason = compiled.reason ?? "plan-v2 compilation failed";
107
112
  ctx.ui.notify(
108
113
  `Plan gate failed-closed: ${reason}. Complete plan/discuss artifacts before execution.\n\nIf this keeps happening, try: /gsd doctor heal`,
109
114
  "error",
110
115
  );
111
- return false;
116
+ return "block";
112
117
  }
113
- return true;
118
+ return "pass";
114
119
  }
115
120
 
116
121
  // ─── Commit Instruction Helpers ──────────────────────────────────────────────
@@ -310,12 +315,29 @@ function extractAssistantText(msg: any): string {
310
315
 
311
316
  /**
312
317
  * Return true if the assistant message contains any tool-use block.
318
+ *
319
+ * The canonical pi-ai `AssistantMessage.content` (see packages/pi-ai/src/types.ts)
320
+ * uses `type: "toolCall"` and `type: "serverToolUse"` for tool invocations —
321
+ * every provider (anthropic-direct, claude-code-cli, openai, etc.) normalizes
322
+ * incoming tool blocks into these two shapes before they reach guided-flow.
323
+ *
324
+ * The Anthropic API wire shape `"tool_use"` / `"server_tool_use"` does NOT appear
325
+ * in the internal AssistantMessage — those literals are only used when sending
326
+ * messages back out to the Anthropic API. Matching them here was a latent bug:
327
+ * `hasToolUse` returned `false` for every real tool call, which let the
328
+ * empty-turn nudge fire and pre-empt MCP tools that block on the user
329
+ * (e.g. `ask_user_questions`). See investigation in PR for #4658.
313
330
  */
314
331
  function hasToolUse(msg: any): boolean {
315
332
  if (!msg) return false;
316
333
  const content = msg.content;
317
334
  if (!Array.isArray(content)) return false;
318
- return content.some((b: any) => b && typeof b === "object" && (b.type === "tool_use" || b.type === "tool-use"));
335
+ return content.some(
336
+ (b: any) =>
337
+ b &&
338
+ typeof b === "object" &&
339
+ (b.type === "toolCall" || b.type === "serverToolUse"),
340
+ );
319
341
  }
320
342
 
321
343
  /**
@@ -825,8 +847,13 @@ export async function showHeadlessMilestoneCreation(
825
847
  // Set pending auto start (auto-mode triggers on "Milestone X ready." via checkAutoStartAfterDiscuss)
826
848
  pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, createdAt: Date.now() });
827
849
 
828
- // Dispatch headless milestone creation is a planning activity
829
- await dispatchWorkflow(pi, prompt, "gsd-run", ctx, "plan-milestone");
850
+ // Dispatch as discuss-milestone. The LLM writes PROJECT.md, REQUIREMENTS.md,
851
+ // and CONTEXT.md, then calls gsd_plan_milestone — this is semantically the
852
+ // discuss path, just non-interactive. Using "plan-milestone" here caused
853
+ // model/tool routing to skip discuss-flow tool scoping and
854
+ // `checkAutoStartAfterDiscuss` guardrails that rely on the
855
+ // "discuss-"-prefixed unitType.
856
+ await dispatchWorkflow(pi, prompt, "gsd-run", ctx, "discuss-milestone");
830
857
  }
831
858
 
832
859
 
@@ -1481,9 +1508,7 @@ export async function showSmartEntry(
1481
1508
  // A zombie .gsd/ state (symlink exists but missing PREFERENCES.md and
1482
1509
  // milestones/) must trigger the init wizard, not skip it (#2942).
1483
1510
  const gsdPath = gsdRoot(basePath);
1484
- const hasBootstrapArtifacts = existsSync(gsdPath)
1485
- && (existsSync(join(gsdPath, "PREFERENCES.md"))
1486
- || existsSync(join(gsdPath, "milestones")));
1511
+ const hasBootstrapArtifacts = hasGsdBootstrapArtifacts(gsdPath);
1487
1512
 
1488
1513
  if (!hasBootstrapArtifacts) {
1489
1514
  const detection = detectProjectState(basePath);
@@ -1573,7 +1598,8 @@ export async function showSmartEntry(
1573
1598
  logWarning("guided", `STATE.md rebuild failed: ${(err as Error).message}`);
1574
1599
  }
1575
1600
 
1576
- if (!runPlanV2Gate(ctx, basePath, state)) return;
1601
+ const planV2GateDecision = runPlanV2Gate(ctx, basePath, state);
1602
+ if (planV2GateDecision === "block") return;
1577
1603
 
1578
1604
  if (!state.activeMilestone?.id) {
1579
1605
  // Guard: if a discuss session is already in flight, don't re-inject the prompt.
@@ -1661,6 +1687,23 @@ export async function showSmartEntry(
1661
1687
  const milestoneId = state.activeMilestone.id;
1662
1688
  const milestoneTitle = state.activeMilestone.title;
1663
1689
 
1690
+ if (planV2GateDecision === "recover-missing-context") {
1691
+ pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId, step: stepMode, createdAt: Date.now() });
1692
+ await dispatchWorkflow(
1693
+ pi,
1694
+ await buildDiscussMilestonePrompt(
1695
+ milestoneId,
1696
+ milestoneTitle,
1697
+ basePath,
1698
+ getStructuredQuestionsAvailability(pi, ctx),
1699
+ ),
1700
+ "gsd-discuss",
1701
+ ctx,
1702
+ "discuss-milestone",
1703
+ );
1704
+ return;
1705
+ }
1706
+
1664
1707
  // ── All milestones complete → New milestone ──────────────────────────
1665
1708
  if (state.phase === "complete") {
1666
1709
  const choice = await showNextAction(ctx, {
@@ -50,7 +50,17 @@ export type JournalEventType =
50
50
  | "worktree-skip"
51
51
  | "worktree-merge-start"
52
52
  | "worktree-merge-failed"
53
- | "artifact-verification-retry";
53
+ | "artifact-verification-retry"
54
+ // #4764 — worktree lifespan / divergence telemetry
55
+ | "worktree-created"
56
+ | "worktree-merged"
57
+ | "worktree-orphaned"
58
+ | "auto-exit"
59
+ | "worktree-sync"
60
+ | "canonical-root-redirect"
61
+ // #4765 — slice-cadence collapse
62
+ | "slice-merged"
63
+ | "milestone-resquash";
54
64
 
55
65
  /** A single structured event in the journal. */
56
66
  export interface JournalEntry {