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
@@ -6,13 +6,83 @@
6
6
 
7
7
  import { describe, it } from "node:test";
8
8
  import assert from "node:assert/strict";
9
- import { readFileSync } from "node:fs";
9
+ import { execFileSync, spawn } from "node:child_process";
10
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
10
11
  import { join, dirname } from "node:path";
12
+ import { tmpdir } from "node:os";
11
13
  import { fileURLToPath } from "node:url";
14
+ import { restoreSliceState } from "../slice-parallel-orchestrator.ts";
12
15
 
13
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
14
17
  const gsdDir = join(__dirname, "..");
15
18
 
19
+ function readLinuxProcessStartFingerprint(pid: number): string | null {
20
+ try {
21
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf-8");
22
+ const afterCommand = stat.slice(stat.lastIndexOf(")") + 2).trim();
23
+ const fields = afterCommand.split(/\s+/);
24
+ const startTimeTicks = fields[19];
25
+ return startTimeTicks ? `linux-stat:${startTimeTicks}` : null;
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+
31
+ function readPsProcessStartFingerprint(pid: number): string | null {
32
+ try {
33
+ const raw = execFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
34
+ stdio: ["ignore", "pipe", "ignore"],
35
+ encoding: "utf-8",
36
+ }).trim().replace(/\s+/g, " ");
37
+ return raw ? `ps-lstart:${raw}` : null;
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+
43
+ function readProcessStartFingerprint(pid: number): string | null {
44
+ return readLinuxProcessStartFingerprint(pid) ?? readPsProcessStartFingerprint(pid);
45
+ }
46
+
47
+ function makeTempProject(): string {
48
+ const basePath = mkdtempSync(join(tmpdir(), "gsd-slice-parallel-"));
49
+ mkdirSync(join(basePath, ".gsd"), { recursive: true });
50
+ return basePath;
51
+ }
52
+
53
+ function writeSliceOrchestratorState(
54
+ basePath: string,
55
+ worker: {
56
+ pid: number;
57
+ workerToken?: string;
58
+ processStartFingerprint?: string | null;
59
+ },
60
+ ): void {
61
+ writeFileSync(
62
+ join(basePath, ".gsd", "slice-orchestrator.json"),
63
+ JSON.stringify({
64
+ active: true,
65
+ workers: [{
66
+ milestoneId: "M900",
67
+ sliceId: "S01",
68
+ pid: worker.pid,
69
+ workerToken: worker.workerToken,
70
+ processStartFingerprint: worker.processStartFingerprint,
71
+ worktreePath: join(basePath, ".gsd", "worktrees", "M900-S01"),
72
+ startedAt: Date.now(),
73
+ state: "running",
74
+ completedUnits: 0,
75
+ cost: 0,
76
+ }],
77
+ totalCost: 0,
78
+ maxWorkers: 1,
79
+ startedAt: Date.now(),
80
+ basePath,
81
+ }),
82
+ "utf-8",
83
+ );
84
+ }
85
+
16
86
  describe("slice-parallel-orchestrator structural tests", () => {
17
87
  it("orchestrator uses GSD_SLICE_LOCK env var", () => {
18
88
  const source = readFileSync(join(gsdDir, "slice-parallel-orchestrator.ts"), "utf-8");
@@ -46,6 +116,99 @@ describe("slice-parallel-orchestrator structural tests", () => {
46
116
  "Orchestrator must also pass GSD_MILESTONE_LOCK for milestone context",
47
117
  );
48
118
  });
119
+
120
+ it("recovery preserves terminal workers for coordinator-side collection", () => {
121
+ const source = readFileSync(join(gsdDir, "slice-parallel-orchestrator.ts"), "utf-8");
122
+ assert.ok(
123
+ source.includes('} else if (w.state === "running")') &&
124
+ source.includes("survivors.push(w);"),
125
+ "Recovery must only prune dead running workers, not stopped/error workers",
126
+ );
127
+ });
128
+
129
+ it("recovered PID-only workers are validated before signaling", () => {
130
+ const source = readFileSync(join(gsdDir, "slice-parallel-orchestrator.ts"), "utf-8");
131
+ assert.ok(
132
+ source.includes("isRecoveredSliceWorkerAlive(worker)") &&
133
+ source.includes('process.kill(worker.pid, "SIGTERM")'),
134
+ "stopSliceParallel must validate recovered worker identity before signaling a PID",
135
+ );
136
+ });
137
+
138
+ it("persists worker identity for crash recovery", () => {
139
+ const source = readFileSync(join(gsdDir, "slice-parallel-orchestrator.ts"), "utf-8");
140
+ assert.ok(
141
+ source.includes("workerToken") &&
142
+ source.includes("processStartFingerprint") &&
143
+ source.includes("GSD_SLICE_WORKER_TOKEN"),
144
+ "Orchestrator must persist stable worker identity metadata for recovered workers",
145
+ );
146
+ });
147
+
148
+ it("spawn failures remove stale worker state and worktree", () => {
149
+ const source = readFileSync(join(gsdDir, "slice-parallel-orchestrator.ts"), "utf-8");
150
+ assert.ok(
151
+ source.includes("sliceState.workers.delete(slice.id)") &&
152
+ source.includes("removeWorktree(basePath, wtName, { deleteBranch: true, force: true })"),
153
+ "Failed slice worker spawns must remove stale worker state and clean up the worktree",
154
+ );
155
+ });
156
+ });
157
+
158
+ describe("slice-parallel-orchestrator recovery identity", () => {
159
+ it("rejects a live PID when the process start fingerprint does not match", () => {
160
+ const basePath = makeTempProject();
161
+ try {
162
+ writeSliceOrchestratorState(basePath, {
163
+ pid: process.pid,
164
+ processStartFingerprint: "mismatched-fingerprint",
165
+ });
166
+
167
+ const restored = restoreSliceState(basePath);
168
+ assert.equal(restored, null, "mismatched fingerprint is treated as a dead worker");
169
+ assert.equal(
170
+ existsSync(join(basePath, ".gsd", "slice-orchestrator.json")),
171
+ false,
172
+ "state file is removed when no recovered worker identity validates",
173
+ );
174
+ } finally {
175
+ rmSync(basePath, { recursive: true, force: true });
176
+ }
177
+ });
178
+
179
+ it("keeps a recovered worker when PID, token, and process start fingerprint match", async () => {
180
+ const basePath = makeTempProject();
181
+ const token = `test-token-${Date.now()}`;
182
+ const child = spawn(
183
+ process.execPath,
184
+ ["-e", "setTimeout(() => {}, 30000)"],
185
+ {
186
+ env: { ...process.env, GSD_SLICE_WORKER_TOKEN: token },
187
+ stdio: "ignore",
188
+ },
189
+ );
190
+
191
+ try {
192
+ assert.ok(child.pid, "child process has a pid");
193
+ await new Promise((resolve) => setTimeout(resolve, 50));
194
+ const fingerprint = readProcessStartFingerprint(child.pid!);
195
+ if (!fingerprint) return;
196
+
197
+ writeSliceOrchestratorState(basePath, {
198
+ pid: child.pid!,
199
+ workerToken: token,
200
+ processStartFingerprint: fingerprint,
201
+ });
202
+
203
+ const restored = restoreSliceState(basePath);
204
+ assert.ok(restored, "matching worker identity is restored");
205
+ assert.equal(restored.workers.length, 1);
206
+ assert.equal(restored.workers[0].pid, child.pid);
207
+ } finally {
208
+ child.kill("SIGTERM");
209
+ rmSync(basePath, { recursive: true, force: true });
210
+ }
211
+ });
49
212
  });
50
213
 
51
214
  describe("slice_parallel preference gating", () => {
@@ -4,6 +4,7 @@ import { tmpdir } from "node:os";
4
4
 
5
5
  import { deriveState } from "../state.js";
6
6
  import { resolveMilestoneFile } from "../paths.js";
7
+ import { extractSourceRegion } from "./test-helpers.ts";
7
8
 
8
9
  let passed = 0;
9
10
  let failed = 0;
@@ -81,7 +82,7 @@ assert(
81
82
 
82
83
  // Check the branch has draft-aware menu options
83
84
  const branchIdx = guidedFlowSource.indexOf('state.phase === "needs-discussion"');
84
- const branchChunk = guidedFlowSource.slice(branchIdx, branchIdx + 4000);
85
+ const branchChunk = extractSourceRegion(guidedFlowSource, 'state.phase === "needs-discussion"');
85
86
 
86
87
  assert(
87
88
  branchChunk.includes("discuss_draft"),
@@ -0,0 +1,112 @@
1
+ /**
2
+ * GSD-2 / agent-end-recovery — regression tests for #4648
3
+ *
4
+ * Covers the stale `dirListCache` bug where `maybeHandleReadyPhraseWithoutFiles`
5
+ * (and `checkAutoStartAfterDiscuss`) falsely reported milestone artifacts as
6
+ * missing, because the directory-listing cache in `paths.ts` was populated
7
+ * before the LLM wrote the files during the same turn.
8
+ *
9
+ * The fix invalidates the cache at the top of `handleAgentEnd`, before any
10
+ * artifact-existence check runs.
11
+ */
12
+
13
+ import { describe, test } from "node:test";
14
+ import assert from "node:assert/strict";
15
+ import {
16
+ mkdtempSync,
17
+ mkdirSync,
18
+ rmSync,
19
+ writeFileSync,
20
+ readFileSync,
21
+ } from "node:fs";
22
+ import { join, dirname } from "node:path";
23
+ import { tmpdir } from "node:os";
24
+ import { fileURLToPath } from "node:url";
25
+
26
+ import { resolveMilestoneFile } from "../paths.ts";
27
+ import { clearPathCache } from "../paths.ts";
28
+
29
+ const __dirname = dirname(fileURLToPath(import.meta.url));
30
+ const AGENT_END_RECOVERY_PATH = join(
31
+ __dirname,
32
+ "..",
33
+ "bootstrap",
34
+ "agent-end-recovery.ts",
35
+ );
36
+
37
+ function mkBase(): string {
38
+ const base = mkdtempSync(join(tmpdir(), "gsd-4648-"));
39
+ mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
40
+ return base;
41
+ }
42
+
43
+ describe("#4648 stale dirListCache — behavioral", () => {
44
+ test("resolveMilestoneFile returns stale null until clearPathCache runs", () => {
45
+ const base = mkBase();
46
+ try {
47
+ clearPathCache();
48
+
49
+ // Prime the cache: directory exists but is empty at this point.
50
+ assert.equal(
51
+ resolveMilestoneFile(base, "M001", "CONTEXT"),
52
+ null,
53
+ "empty dir → null",
54
+ );
55
+
56
+ // Simulate the LLM writing CONTEXT.md during the turn.
57
+ writeFileSync(
58
+ join(base, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
59
+ "# M001 Context\n",
60
+ );
61
+
62
+ // Without a cache flush the resolver still reports null — this is the bug.
63
+ assert.equal(
64
+ resolveMilestoneFile(base, "M001", "CONTEXT"),
65
+ null,
66
+ "stale cache returns null even though the file exists on disk",
67
+ );
68
+
69
+ // The fix: clearPathCache() — after which the resolver finds the file.
70
+ clearPathCache();
71
+ const resolved = resolveMilestoneFile(base, "M001", "CONTEXT");
72
+ assert.ok(
73
+ resolved && /M001-CONTEXT\.md$/.test(resolved),
74
+ `after clearPathCache, resolver finds the file (got: ${resolved})`,
75
+ );
76
+ } finally {
77
+ clearPathCache();
78
+ rmSync(base, { recursive: true, force: true });
79
+ }
80
+ });
81
+ });
82
+
83
+ describe("#4648 agent-end-recovery wiring", () => {
84
+ test("handleAgentEnd invalidates the path cache before the discuss guards", () => {
85
+ const source = readFileSync(AGENT_END_RECOVERY_PATH, "utf-8");
86
+
87
+ assert.ok(
88
+ /import\s*\{\s*clearPathCache\s*\}\s*from\s*"\.\.\/paths\.js"/.test(source),
89
+ "agent-end-recovery.ts must import clearPathCache from ../paths.js",
90
+ );
91
+
92
+ const fnStart = source.indexOf("export async function handleAgentEnd");
93
+ assert.ok(fnStart > -1, "handleAgentEnd must exist");
94
+
95
+ const checkIdx = source.indexOf("checkAutoStartAfterDiscuss(", fnStart);
96
+ const clearIdx = source.indexOf("clearPathCache(", fnStart);
97
+ const readyIdx = source.indexOf(
98
+ "maybeHandleReadyPhraseWithoutFiles(",
99
+ fnStart,
100
+ );
101
+
102
+ assert.ok(clearIdx > -1, "handleAgentEnd must call clearPathCache");
103
+ assert.ok(
104
+ clearIdx < checkIdx,
105
+ "clearPathCache must run before checkAutoStartAfterDiscuss so the guard sees fresh disk state",
106
+ );
107
+ assert.ok(
108
+ clearIdx < readyIdx,
109
+ "clearPathCache must run before maybeHandleReadyPhraseWithoutFiles",
110
+ );
111
+ });
112
+ });
@@ -13,6 +13,7 @@ import {
13
13
  isValidationTerminal,
14
14
  isGhostMilestone,
15
15
  invalidateStateCache,
16
+ getActiveMilestoneId,
16
17
  } from "../state.ts";
17
18
  import {
18
19
  openDatabase,
@@ -667,6 +668,29 @@ describe("state-machine-full-walkthrough", () => {
667
668
  assert.notEqual(state.phase, "completing-milestone", "should be complete, not completing");
668
669
  assert.equal(state.phase, "complete");
669
670
  });
671
+
672
+ test("failure-path milestone SUMMARY is not terminal completion", async () => {
673
+ const base = createFixtureBase();
674
+ writeRoadmap(base, "M001", doneSliceRoadmap());
675
+ writeMilestoneValidation(base, "M001", "pass");
676
+ const dir = join(base, ".gsd", "milestones", "M001");
677
+ writeFileSync(join(dir, "M001-SUMMARY.md"), [
678
+ "---",
679
+ "status: failed",
680
+ "---",
681
+ "",
682
+ "# BLOCKER",
683
+ "",
684
+ "auto-mode recovery failed; milestone is not complete.",
685
+ ].join("\n"));
686
+ invalidateStateCache();
687
+
688
+ const state = await deriveState(base);
689
+
690
+ assert.equal(state.phase, "completing-milestone");
691
+ assert.equal(state.registry[0]?.status, "active");
692
+ assert.equal(await getActiveMilestoneId(base), "M001");
693
+ });
670
694
  });
671
695
 
672
696
  // ═══════════════════════════════════════════════════════════════════════════
@@ -811,9 +835,9 @@ describe("state-machine-full-walkthrough", () => {
811
835
  assert.ok(state.blockers.length > 0, "should have blockers");
812
836
  });
813
837
 
814
- test("no eligible slice (all deps unmet) → fallback picks slice with most deps satisfied", async () => {
838
+ test("no eligible slice (all deps unmet) → blocked", async () => {
815
839
  const base = createFixtureBase();
816
- // S01 depends on S00 which doesn't exist — fallback picks S01 anyway
840
+ // S01 depends on S00 which doesn't exist.
817
841
  writeRoadmap(base, "M001", [
818
842
  "# M001: Test Milestone",
819
843
  "",
@@ -827,9 +851,9 @@ describe("state-machine-full-walkthrough", () => {
827
851
  invalidateStateCache();
828
852
  const state = await deriveState(base);
829
853
 
830
- // With partial-dep fallback, S01 is picked despite unmet dep on S00
831
- assert.equal(state.phase, "planning");
832
- assert.equal(state.activeSlice?.id, "S01");
854
+ assert.equal(state.phase, "blocked");
855
+ assert.equal(state.activeSlice, null);
856
+ assert.ok(state.blockers.some(b => b.includes("No slice eligible")));
833
857
  });
834
858
  });
835
859
 
@@ -0,0 +1,44 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import {
5
+ STATE_TRANSITION_MATRIX,
6
+ findTransition,
7
+ validateTransitionMatrix,
8
+ } from "../state-transition-matrix.ts";
9
+
10
+ test("state transition matrix covers required swarm hardening events", () => {
11
+ const result = validateTransitionMatrix([
12
+ "context-ready",
13
+ "research-ready",
14
+ "plan-ready",
15
+ "task-dispatched",
16
+ "slice-complete",
17
+ "validation-pass",
18
+ "recovery-plan-ready",
19
+ "closeout-complete",
20
+ ]);
21
+
22
+ assert.equal(result.ok, true);
23
+ assert.deepEqual(result.missingEvents, []);
24
+ assert.deepEqual(result.duplicateKeys, []);
25
+ });
26
+
27
+ test("state transition matrix fails closed for recovery and closeout guards", () => {
28
+ const recovery = findTransition("blocked", "recovery-plan-ready");
29
+ assert.equal(recovery?.to, "executing");
30
+ assert.equal(recovery?.onFail, "blocked");
31
+ assert.equal(recovery?.reasonCode, "recovery");
32
+
33
+ const closeout = findTransition("completing-milestone", "closeout-complete");
34
+ assert.equal(closeout?.to, "complete");
35
+ assert.equal(closeout?.onFail, "blocked");
36
+ });
37
+
38
+ test("state transition matrix entries all have guard and reason codes", () => {
39
+ assert.ok(STATE_TRANSITION_MATRIX.length >= 8);
40
+ for (const entry of STATE_TRANSITION_MATRIX) {
41
+ assert.ok(entry.guard.length > 0, `${entry.event} must document its guard`);
42
+ assert.ok(entry.reasonCode.length > 0, `${entry.event} must include reason code`);
43
+ }
44
+ });
@@ -13,7 +13,7 @@
13
13
 
14
14
  import { readFileSync } from "node:fs";
15
15
  import { join } from "node:path";
16
- import { createTestContext } from "./test-helpers.ts";
16
+ import { createTestContext, extractSourceRegion } from "./test-helpers.ts";
17
17
 
18
18
  const { assertTrue, report } = createTestContext();
19
19
 
@@ -35,7 +35,7 @@ assertTrue(
35
35
  );
36
36
 
37
37
  // Extract the region from the closeout comment to the next section comment
38
- const closeoutRegion = phasesSrc.slice(closeoutIdx, closeoutIdx + 500);
38
+ const closeoutRegion = extractSourceRegion(phasesSrc, closeoutComment);
39
39
  assertTrue(
40
40
  closeoutRegion.includes("if (s.currentUnit)"),
41
41
  "closeoutUnit call is guarded by `if (s.currentUnit)` check (#2939)",
@@ -52,7 +52,7 @@ assertTrue(
52
52
  "phases.ts contains the 'Zero tool-call guard' comment block",
53
53
  );
54
54
 
55
- const zeroToolRegion = phasesSrc.slice(zeroToolIdx, zeroToolIdx + 600);
55
+ const zeroToolRegion = extractSourceRegion(phasesSrc, zeroToolComment);
56
56
 
57
57
  // The non-null assertion `s.currentUnit!.startedAt` must be replaced with
58
58
  // optional chaining `s.currentUnit?.startedAt`
@@ -271,96 +271,15 @@ describe("structured-data-formatter: measureSavings", () => {
271
271
  });
272
272
 
273
273
  // ---------------------------------------------------------------------------
274
- // Realistic token savings measurement
274
+ // Dropped (#4836): the previous "realistic savings" suite asserted that the
275
+ // compact formatter beat hand-authored "typical markdown" baselines by 30%+.
276
+ // Those baselines were written by the test author to make the assertion pass
277
+ // — they are not the format GSD actually emits anywhere else, so shifting
278
+ // the compact output by any amount could be absorbed by padding the baseline.
279
+ // There was no regression signal.
280
+ //
281
+ // The unit tests above already pin the compact format's structure byte for
282
+ // byte; a genuine regression changes one of those exact-string assertions.
283
+ // If a size-budget guarantee is needed later, capture a real production
284
+ // baseline into a fixture file and assert against a checked-in byte count.
275
285
  // ---------------------------------------------------------------------------
276
-
277
- describe("structured-data-formatter: realistic savings", () => {
278
- it("decisions compact format saves 30%+ vs markdown table", () => {
279
- const decisions = [sampleDecision, sampleDecision2];
280
-
281
- // Simulate a typical markdown table
282
- const markdownTable = [
283
- "| ID | When | Scope | Decision | Choice | Rationale | Revisable |",
284
- "|------|------------|--------------|-------------------------|------------------------|--------------------------|-----------|",
285
- "| D001 | M001/S01 | architecture | Use SQLite for storage | WAL mode, single-writer | Built-in, no external deps | yes |",
286
- "| D002 | M001/S02 | testing | Unit test all parsers | node:test framework | Fast, zero-dependency | no |",
287
- ].join("\n");
288
-
289
- const compactOutput = formatDecisionsCompact(decisions);
290
- const savings = measureSavings(compactOutput, markdownTable);
291
- assert.ok(
292
- savings >= 30,
293
- `expected >=30% savings, got ${savings.toFixed(1)}%`,
294
- );
295
- });
296
-
297
- it("requirements compact format saves 30%+ vs markdown sections", () => {
298
- const requirements = [sampleRequirement, sampleRequirement2];
299
-
300
- // Simulate verbose markdown format with all fields
301
- const markdownSections = [
302
- "## R001",
303
- "",
304
- "- **Class:** functional",
305
- "- **Status:** active",
306
- "- **Description:** Response latency < 200ms for API endpoints",
307
- "- **Why:** Critical for user experience",
308
- "- **Source:** architecture review",
309
- "- **Primary Owner:** S01",
310
- "- **Supporting Slices:** S02, S03",
311
- "- **Validation:** Load test confirms P99 < 200ms",
312
- "- **Notes:** Monitor in production",
313
- "",
314
- "## R002",
315
- "",
316
- "- **Class:** non-functional",
317
- "- **Status:** active",
318
- "- **Description:** Data consistency across writes",
319
- "- **Why:** Prevents data loss",
320
- "- **Source:** data team review",
321
- "- **Primary Owner:** S02",
322
- "- **Supporting Slices:** S01",
323
- "- **Validation:** Integration test suite",
324
- "- **Notes:** Requires WAL mode",
325
- ].join("\n");
326
-
327
- const compactOutput = formatRequirementsCompact(requirements);
328
- const savings = measureSavings(compactOutput, markdownSections);
329
- assert.ok(
330
- savings >= 30,
331
- `expected >=30% savings, got ${savings.toFixed(1)}%`,
332
- );
333
- });
334
-
335
- it("task plan compact format saves 30%+ vs markdown sections", () => {
336
- const tasks = [sampleTaskDone, sampleTaskPending];
337
-
338
- // Simulate verbose markdown task format
339
- const markdownTasks = [
340
- "## T01 - Database schema",
341
- "",
342
- "- **Status:** Done",
343
- "- **Estimate:** 30m",
344
- "- **Description:** Create tables for decisions and requirements",
345
- "- **Files:**",
346
- " - src/db.ts",
347
- " - src/schema.ts",
348
- "",
349
- "## T02 - API endpoints",
350
- "",
351
- "- **Status:** Pending",
352
- "- **Estimate:** 1h",
353
- "- **Description:** REST endpoints for CRUD operations",
354
- "- **Files:**",
355
- " - src/api.ts",
356
- "- **Verify:** npm test",
357
- ].join("\n");
358
-
359
- const compactOutput = formatTaskPlanCompact(tasks);
360
- const savings = measureSavings(compactOutput, markdownTasks);
361
- assert.ok(
362
- savings >= 30,
363
- `expected >=30% savings, got ${savings.toFixed(1)}%`,
364
- );
365
- });
366
- });
@@ -15,6 +15,7 @@ import { join, dirname } from "node:path";
15
15
  import { tmpdir } from "node:os";
16
16
  import { fileURLToPath } from "node:url";
17
17
  import { validatePreferences } from "../preferences-validation.ts";
18
+ import { extractSourceRegion } from "./test-helpers.ts";
18
19
 
19
20
  const __dirname = dirname(fileURLToPath(import.meta.url));
20
21
  const promptsSrc = readFileSync(join(__dirname, "..", "auto-prompts.ts"), "utf-8");
@@ -59,7 +60,7 @@ test("reactive_execution: subagent_model rejects empty string", () => {
59
60
  test("buildReactiveExecutePrompt: accepts subagentModel parameter", () => {
60
61
  const fnStart = promptsSrc.indexOf("export async function buildReactiveExecutePrompt");
61
62
  assert.ok(fnStart !== -1, "buildReactiveExecutePrompt should be exported");
62
- const signature = promptsSrc.slice(fnStart, fnStart + 300);
63
+ const signature = extractSourceRegion(promptsSrc, "export async function buildReactiveExecutePrompt", { fromIdx: fnStart });
63
64
  assert.ok(
64
65
  signature.includes("subagentModel"),
65
66
  "buildReactiveExecutePrompt should accept a subagentModel parameter",
@@ -69,7 +70,7 @@ test("buildReactiveExecutePrompt: accepts subagentModel parameter", () => {
69
70
  test("buildParallelResearchSlicesPrompt: accepts subagentModel parameter", () => {
70
71
  const fnStart = promptsSrc.indexOf("export async function buildParallelResearchSlicesPrompt");
71
72
  assert.ok(fnStart !== -1, "buildParallelResearchSlicesPrompt should be exported");
72
- const signature = promptsSrc.slice(fnStart, fnStart + 300);
73
+ const signature = extractSourceRegion(promptsSrc, "export async function buildParallelResearchSlicesPrompt", { fromIdx: fnStart });
73
74
  assert.ok(
74
75
  signature.includes("subagentModel"),
75
76
  "buildParallelResearchSlicesPrompt should accept a subagentModel parameter",
@@ -79,7 +80,7 @@ test("buildParallelResearchSlicesPrompt: accepts subagentModel parameter", () =>
79
80
  test("buildGateEvaluatePrompt: accepts subagentModel parameter", () => {
80
81
  const fnStart = promptsSrc.indexOf("export async function buildGateEvaluatePrompt");
81
82
  assert.ok(fnStart !== -1, "buildGateEvaluatePrompt should be exported");
82
- const signature = promptsSrc.slice(fnStart, fnStart + 300);
83
+ const signature = extractSourceRegion(promptsSrc, "export async function buildGateEvaluatePrompt", { fromIdx: fnStart });
83
84
  assert.ok(
84
85
  signature.includes("subagentModel"),
85
86
  "buildGateEvaluatePrompt should accept a subagentModel parameter",
@@ -129,7 +130,7 @@ test("auto-dispatch: passes model to buildReactiveExecutePrompt", () => {
129
130
  // Find the reactive-execute dispatch rule
130
131
  const ruleStart = dispatchSrc.indexOf("reactive-execute (parallel dispatch)");
131
132
  assert.ok(ruleStart !== -1, "reactive-execute dispatch rule should exist");
132
- const ruleBlock = dispatchSrc.slice(ruleStart, ruleStart + 1000);
133
+ const ruleBlock = extractSourceRegion(dispatchSrc, "reactive-execute (parallel dispatch)", { fromIdx: ruleStart });
133
134
  assert.ok(
134
135
  ruleBlock.includes("subagent_model") || ruleBlock.includes("subagentModel"),
135
136
  "reactive-execute rule should resolve and pass the subagent model",
@@ -140,7 +141,7 @@ test("auto-dispatch: passes model to buildParallelResearchSlicesPrompt", () => {
140
141
  const callIdx = dispatchSrc.indexOf("buildParallelResearchSlicesPrompt(");
141
142
  assert.ok(callIdx !== -1, "buildParallelResearchSlicesPrompt call should exist");
142
143
  // The call site should pass a model argument (not just 4 args)
143
- const callSite = dispatchSrc.slice(callIdx, callIdx + 300);
144
+ const callSite = extractSourceRegion(dispatchSrc, "buildParallelResearchSlicesPrompt(", { fromIdx: callIdx });
144
145
  assert.ok(
145
146
  callSite.includes("subagentModel") || callSite.includes("resolveModelWithFallbacksForUnit"),
146
147
  "buildParallelResearchSlicesPrompt call should include model argument",
@@ -150,7 +151,7 @@ test("auto-dispatch: passes model to buildParallelResearchSlicesPrompt", () => {
150
151
  test("auto-dispatch: passes model to buildGateEvaluatePrompt", () => {
151
152
  const callIdx = dispatchSrc.indexOf("buildGateEvaluatePrompt(");
152
153
  assert.ok(callIdx !== -1, "buildGateEvaluatePrompt call should exist");
153
- const callSite = dispatchSrc.slice(callIdx, callIdx + 300);
154
+ const callSite = extractSourceRegion(dispatchSrc, "buildGateEvaluatePrompt(", { fromIdx: callIdx });
154
155
  assert.ok(
155
156
  callSite.includes("subagentModel") || callSite.includes("resolveModelWithFallbacksForUnit"),
156
157
  "buildGateEvaluatePrompt call should include model argument",