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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (545) hide show
  1. package/README.md +53 -17
  2. package/dist/claude-cli-check.js +46 -10
  3. package/dist/headless.js +49 -4
  4. package/dist/resource-loader.d.ts +40 -0
  5. package/dist/resource-loader.js +32 -13
  6. package/dist/resources/extensions/browser-tools/capture.js +9 -0
  7. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  8. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  9. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  10. package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
  11. package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
  12. package/dist/resources/extensions/claude-code-cli/readiness.js +72 -16
  13. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
  14. package/dist/resources/extensions/github-sync/templates.js +103 -0
  15. package/dist/resources/extensions/google-search/index.js +3 -2
  16. package/dist/resources/extensions/gsd/auto/loop.js +124 -2
  17. package/dist/resources/extensions/gsd/auto/phases.js +57 -39
  18. package/dist/resources/extensions/gsd/auto/session.js +6 -2
  19. package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
  20. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  21. package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
  22. package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
  23. package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
  24. package/dist/resources/extensions/gsd/auto-start.js +107 -29
  25. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  26. package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
  27. package/dist/resources/extensions/gsd/auto.js +76 -21
  28. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  30. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
  31. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  32. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  33. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  34. package/dist/resources/extensions/gsd/component-types.js +69 -0
  35. package/dist/resources/extensions/gsd/context-store.js +23 -7
  36. package/dist/resources/extensions/gsd/detection.js +49 -1
  37. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
  38. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  39. package/dist/resources/extensions/gsd/forensics.js +106 -0
  40. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  41. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  42. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  43. package/dist/resources/extensions/gsd/git-service.js +126 -2
  44. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  45. package/dist/resources/extensions/gsd/guided-flow.js +39 -13
  46. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  47. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  48. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  49. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  50. package/dist/resources/extensions/gsd/model-router.js +6 -0
  51. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  52. package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
  53. package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
  54. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  55. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  56. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  57. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  58. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  59. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  60. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  61. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  62. package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
  63. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  64. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  65. package/dist/resources/extensions/gsd/state.js +69 -58
  66. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  67. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
  68. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  69. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  70. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  71. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  72. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  73. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  74. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  75. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  76. package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
  77. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  78. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  79. package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
  80. package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
  81. package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
  82. package/dist/resources/extensions/mcp-client/index.js +3 -1
  83. package/dist/resources/extensions/ollama/index.js +5 -1
  84. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  85. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  86. package/dist/web/standalone/.next/BUILD_ID +1 -1
  87. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  88. package/dist/web/standalone/.next/build-manifest.json +2 -2
  89. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/index.html +1 -1
  108. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  115. package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
  116. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  117. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  119. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  120. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  121. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  122. package/package.json +2 -3
  123. package/packages/daemon/package.json +2 -2
  124. package/packages/daemon/src/logger.ts +4 -3
  125. package/packages/mcp-server/dist/server.d.ts +24 -0
  126. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  127. package/packages/mcp-server/dist/server.js +88 -87
  128. package/packages/mcp-server/dist/server.js.map +1 -1
  129. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  130. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  131. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  132. package/packages/mcp-server/package.json +2 -2
  133. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  134. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  135. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  136. package/packages/mcp-server/src/server.ts +131 -105
  137. package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
  138. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  139. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  140. package/packages/native/package.json +2 -2
  141. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  142. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  143. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  144. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  145. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  146. package/packages/pi-agent-core/package.json +1 -1
  147. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  148. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  149. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  150. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  151. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  152. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  153. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  154. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  155. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  156. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  157. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  158. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  159. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  160. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  161. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  162. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  163. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  164. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  165. package/packages/pi-ai/dist/models.test.js +36 -11
  166. package/packages/pi-ai/dist/models.test.js.map +1 -1
  167. package/packages/pi-ai/package.json +1 -1
  168. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  169. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  170. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  171. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  172. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  173. package/packages/pi-ai/src/models.test.ts +48 -11
  174. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  175. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  176. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  178. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  180. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  182. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  184. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  186. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  188. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  190. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  193. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  195. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  197. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  198. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  199. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  201. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  203. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  205. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  206. package/packages/pi-coding-agent/dist/index.js +1 -0
  207. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
  209. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  217. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  218. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  219. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  220. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  221. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  224. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  225. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  226. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  227. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  228. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  229. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  230. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  231. package/packages/pi-coding-agent/package.json +1 -1
  232. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  233. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  234. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  235. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  236. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  237. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  238. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  239. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  240. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  241. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  242. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  243. package/packages/pi-coding-agent/src/index.ts +1 -0
  244. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
  245. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  246. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
  247. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  248. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  249. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  250. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  251. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  252. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  253. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  254. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  255. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  256. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  257. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +37 -11
  258. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  259. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  260. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  261. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  262. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  263. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  264. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  265. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  266. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  267. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  268. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  269. package/packages/pi-tui/dist/components/editor.js +19 -0
  270. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  271. package/packages/pi-tui/dist/components/image.test.js +6 -5
  272. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  273. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  274. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  275. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  276. package/packages/pi-tui/package.json +1 -1
  277. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  278. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  279. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +42 -11
  280. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  281. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  282. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  283. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  284. package/packages/pi-tui/src/components/editor.ts +22 -0
  285. package/packages/pi-tui/src/components/image.test.ts +10 -5
  286. package/packages/pi-tui/src/editor-component.ts +3 -0
  287. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  288. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  289. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  290. package/packages/rpc-client/package.json +1 -1
  291. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  292. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  293. package/pkg/package.json +1 -1
  294. package/scripts/install.js +15 -1
  295. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  296. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  297. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  298. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  299. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  300. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  301. package/src/resources/extensions/claude-code-cli/readiness.ts +75 -16
  302. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
  303. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
  304. package/src/resources/extensions/github-sync/templates.ts +151 -0
  305. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  306. package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
  307. package/src/resources/extensions/google-search/index.ts +3 -2
  308. package/src/resources/extensions/gsd/auto/loop.ts +142 -2
  309. package/src/resources/extensions/gsd/auto/phases.ts +62 -38
  310. package/src/resources/extensions/gsd/auto/session.ts +7 -2
  311. package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
  312. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  313. package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
  314. package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
  315. package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
  316. package/src/resources/extensions/gsd/auto-start.ts +127 -9
  317. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  318. package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
  319. package/src/resources/extensions/gsd/auto.ts +90 -23
  320. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
  321. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  322. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
  323. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  324. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  325. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  326. package/src/resources/extensions/gsd/component-types.ts +362 -0
  327. package/src/resources/extensions/gsd/context-store.ts +25 -8
  328. package/src/resources/extensions/gsd/detection.ts +58 -1
  329. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
  330. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  331. package/src/resources/extensions/gsd/forensics.ts +118 -1
  332. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  333. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  334. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  335. package/src/resources/extensions/gsd/git-service.ts +149 -2
  336. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  337. package/src/resources/extensions/gsd/guided-flow.ts +57 -14
  338. package/src/resources/extensions/gsd/journal.ts +11 -1
  339. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  340. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  341. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  342. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  343. package/src/resources/extensions/gsd/model-router.ts +6 -0
  344. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  345. package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
  346. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
  347. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  348. package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  349. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  350. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  351. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  352. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  353. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  354. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  355. package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
  356. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  357. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  358. package/src/resources/extensions/gsd/state.ts +76 -66
  359. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  360. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  361. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
  362. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  363. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  364. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +133 -292
  365. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  366. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  367. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  368. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  369. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
  370. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
  371. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
  372. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
  373. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  374. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
  375. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
  376. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
  377. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
  378. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  379. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  380. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  381. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  382. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  383. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
  384. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  385. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  386. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  387. package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
  388. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
  389. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  390. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
  391. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  392. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  393. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  394. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  395. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
  396. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
  397. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
  398. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
  399. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  400. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  401. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  402. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
  403. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
  404. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  405. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  406. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
  407. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  408. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  409. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
  410. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  411. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  412. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
  413. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  414. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  415. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  416. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  417. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  418. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  419. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
  420. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  421. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
  422. package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
  423. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
  424. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  425. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
  426. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  427. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  428. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  429. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  430. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
  431. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  432. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
  433. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
  434. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  435. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  436. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
  437. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
  438. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
  439. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
  440. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
  441. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
  442. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
  443. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  444. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  445. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  446. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  447. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  448. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
  449. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  450. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  451. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  452. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
  453. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  454. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  455. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  456. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  457. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
  458. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
  459. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  460. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
  461. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  462. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
  463. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  464. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
  465. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  466. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
  467. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  468. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  469. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
  470. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  471. package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
  472. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  473. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  474. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  475. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  476. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  477. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  478. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  479. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  480. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  481. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  482. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  483. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
  484. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  485. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
  486. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
  487. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  488. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  489. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  490. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  491. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  492. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  493. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  494. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  495. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
  496. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  497. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  498. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  499. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  500. package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
  501. package/src/resources/extensions/gsd/types.ts +3 -3
  502. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  503. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  504. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  505. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  506. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  507. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  508. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  509. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  510. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  511. package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
  512. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  513. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  514. package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
  515. package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
  516. package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
  517. package/src/resources/extensions/mcp-client/index.ts +3 -1
  518. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  519. package/src/resources/extensions/ollama/index.ts +5 -1
  520. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  521. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  522. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  523. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  524. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  525. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  526. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  527. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  528. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  529. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  530. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  531. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
  532. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  533. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  534. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  535. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  536. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  537. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  538. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
  539. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  540. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  541. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  542. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
  543. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
  544. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_buildManifest.js +0 -0
  545. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_ssgManifest.js +0 -0
@@ -2,65 +2,237 @@
2
2
  * merge-conflict-stops-loop.test.ts — #2330
3
3
  *
4
4
  * When a squash merge has real code conflicts (not just .gsd/ files),
5
- * the merge retries forever because MergeConflictError is caught
6
- * silently in mergeAndExit. This test verifies that:
7
- * 1. worktree-resolver re-throws MergeConflictError for code conflicts
8
- * 2. auto/phases.ts wraps mergeAndExit calls to stop the loop on conflict
5
+ * the merge used to retry forever because `MergeConflictError` was
6
+ * caught silently in `mergeAndExit`. The fix:
7
+ *
8
+ * 1. `WorktreeResolver.mergeAndExit` **re-throws** `MergeConflictError`
9
+ * (and other unexpected errors) so the caller sees the failure.
10
+ * 2. `auto/phases.ts` catches `MergeConflictError` from `mergeAndExit`
11
+ * and returns `{ action: "break", reason: "merge-conflict" }` +
12
+ * calls `stopAuto`, instead of looping.
13
+ *
14
+ * The previous version of this file was three source-grep assertions
15
+ * (`src.includes("MergeConflictError")` / `src.includes("throw err")` /
16
+ * `extractSourceRegion(..., "instanceof MergeConflictError").includes("stopAuto")`).
17
+ * Those all pass even if the bug reappears verbatim — the catch block
18
+ * could swallow the error silently as long as the identifier text
19
+ * remains somewhere in the file. Called out in #4784 / #4824 as the
20
+ * canonical source-grep false-coverage case.
21
+ *
22
+ * This rewrite tests the invariant at the `WorktreeResolver` layer
23
+ * (where the re-throw happens) with injected deps: we wire
24
+ * `mergeMilestoneToMain` to throw `MergeConflictError`, call
25
+ * `mergeAndExit`, and assert the error propagates. That is the ONLY
26
+ * assertion that fails if someone reverts the re-throw to a silent
27
+ * catch.
9
28
  */
10
29
 
11
- import { readFileSync } from "node:fs";
30
+ import { describe, test, beforeEach, afterEach } from "node:test";
31
+ import assert from "node:assert/strict";
32
+ import { mkdtempSync, rmSync, mkdirSync } from "node:fs";
12
33
  import { join } from "node:path";
13
- import { createTestContext } from "./test-helpers.ts";
14
-
15
- const { assertTrue, report } = createTestContext();
16
-
17
- const resolverPath = join(import.meta.dirname, "..", "worktree-resolver.ts");
18
- const resolverSrc = readFileSync(resolverPath, "utf-8");
19
-
20
- const phasesPath = join(import.meta.dirname, "..", "auto", "phases.ts");
21
- const phasesSrc = readFileSync(phasesPath, "utf-8");
22
-
23
- console.log("\n=== #2330: Merge conflict stops auto loop ===");
24
-
25
- // ── Test 1: worktree-resolver re-throws MergeConflictError ──────────────
26
-
27
- const methodStart = resolverSrc.indexOf("Worktree-mode merge:");
28
- assertTrue(methodStart > 0, "worktree-resolver has _mergeWorktreeMode method");
29
-
30
- const methodBody = resolverSrc.slice(methodStart, methodStart + 6000);
31
- const rethrowsConflict =
32
- methodBody.includes("MergeConflictError") &&
33
- methodBody.includes("throw err");
34
-
35
- assertTrue(
36
- rethrowsConflict,
37
- "worktree-resolver._mergeWorktreeMode re-throws MergeConflictError (#2330)",
38
- );
39
-
40
- // ── Test 2: auto/phases.ts imports and uses MergeConflictError ──────────
41
-
42
- assertTrue(
43
- phasesSrc.includes("MergeConflictError") && phasesSrc.includes("mergeAndExit"),
44
- "auto/phases.ts handles MergeConflictError from mergeAndExit (#2330)",
45
- );
46
-
47
- // ── Test 3: The handler stops the loop (doesn't just warn) ──────────────
48
-
49
- // Find the instanceof MergeConflictError check (not the import line)
50
- const instanceofIdx = phasesSrc.indexOf("instanceof MergeConflictError");
51
- assertTrue(instanceofIdx > 0, "auto/phases.ts has instanceof MergeConflictError check");
34
+ import { tmpdir } from "node:os";
35
+
36
+ import { WorktreeResolver } from "../worktree-resolver.ts";
37
+ import { MergeConflictError } from "../git-service.ts";
38
+ import type { WorktreeResolverDeps } from "../worktree-resolver.ts";
39
+ import type { AutoSession } from "../auto/session.ts";
40
+
41
+ // ─── Test-only session double ───────────────────────────────────────────
42
+ // `AutoSession` is a large class but `WorktreeResolver` only reads a few
43
+ // fields from it (basePath, originalBasePath, currentMilestoneId).
44
+ function makeSession(basePath: string): AutoSession {
45
+ return {
46
+ basePath,
47
+ originalBasePath: basePath,
48
+ currentMilestoneId: "M001",
49
+ } as unknown as AutoSession;
50
+ }
52
51
 
53
- if (instanceofIdx > 0) {
54
- const afterHandler = phasesSrc.slice(instanceofIdx, instanceofIdx + 500);
55
- const stopsLoop =
56
- afterHandler.includes("stopAuto") ||
57
- afterHandler.includes('action: "break"') ||
58
- afterHandler.includes("reason: \"merge-conflict\"");
52
+ /**
53
+ * Build a deps object where every method is a no-op or a controlled
54
+ * value, except the ones the caller explicitly overrides. This is the
55
+ * boring-tech approach — no mocking library, just plain objects.
56
+ */
57
+ function makeDeps(
58
+ overrides: Partial<WorktreeResolverDeps> = {},
59
+ ): WorktreeResolverDeps {
60
+ return {
61
+ isInAutoWorktree: () => true,
62
+ shouldUseWorktreeIsolation: () => true,
63
+ getIsolationMode: () => "worktree",
64
+ mergeMilestoneToMain: () => ({ pushed: false, codeFilesChanged: true }),
65
+ syncWorktreeStateBack: () => ({ synced: [] }),
66
+ teardownAutoWorktree: () => undefined,
67
+ createAutoWorktree: () => "",
68
+ enterAutoWorktree: () => "",
69
+ enterBranchModeForMilestone: () => undefined,
70
+ getAutoWorktreePath: () => null,
71
+ autoCommitCurrentBranch: () => undefined,
72
+ getCurrentBranch: () => "worktree/M001",
73
+ autoWorktreeBranch: (mid: string) => `worktree/${mid}`,
74
+ resolveMilestoneFile: () => null, // no roadmap → early return path
75
+ readFileSync: () => "",
76
+ GitServiceImpl: class {
77
+ constructor(_basePath: string, _config: unknown) {}
78
+ } as never,
79
+ loadEffectiveGSDPreferences: () => ({ preferences: {} }),
80
+ invalidateAllCaches: () => undefined,
81
+ captureIntegrationBranch: () => undefined,
82
+ ...overrides,
83
+ };
84
+ }
59
85
 
60
- assertTrue(
61
- stopsLoop,
62
- "auto/phases.ts stops the loop when merge conflict is detected (#2330)",
63
- );
86
+ function makeNotifyCtx(): {
87
+ notify: (msg: string, level?: "info" | "warning" | "error" | "success") => void;
88
+ calls: Array<{ msg: string; level?: string }>;
89
+ } {
90
+ const calls: Array<{ msg: string; level?: string }> = [];
91
+ return {
92
+ notify: (msg, level) => {
93
+ calls.push({ msg, level });
94
+ },
95
+ calls,
96
+ };
64
97
  }
65
98
 
66
- report();
99
+ describe("WorktreeResolver.mergeAndExit re-throws MergeConflictError (#2330)", () => {
100
+ let baseDir: string;
101
+
102
+ beforeEach(() => {
103
+ baseDir = mkdtempSync(join(tmpdir(), "merge-conflict-stops-loop-"));
104
+ // Fake out a milestone directory so mergeAndExit reaches mergeMilestoneToMain.
105
+ mkdirSync(join(baseDir, ".gsd", "milestones", "M001"), { recursive: true });
106
+ });
107
+
108
+ afterEach(() => {
109
+ try {
110
+ rmSync(baseDir, { recursive: true, force: true });
111
+ } catch {
112
+ // best-effort
113
+ }
114
+ });
115
+
116
+ test("propagates MergeConflictError with conflicted file list", () => {
117
+ const conflicted = ["src/feature.ts", "README.md"];
118
+ const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
119
+ const deps = makeDeps({
120
+ resolveMilestoneFile: (_base, _mid, type) =>
121
+ type === "ROADMAP" ? roadmapPath : null,
122
+ readFileSync: () => "# M001\n",
123
+ mergeMilestoneToMain: () => {
124
+ throw new MergeConflictError(conflicted, "squash", "worktree/M001", "main");
125
+ },
126
+ });
127
+
128
+ const resolver = new WorktreeResolver(makeSession(baseDir), deps);
129
+ const ctx = makeNotifyCtx();
130
+
131
+ assert.throws(
132
+ () => resolver.mergeAndExit("M001", ctx),
133
+ (err: unknown) => {
134
+ assert.ok(
135
+ err instanceof MergeConflictError,
136
+ `expected MergeConflictError, got: ${err}`,
137
+ );
138
+ assert.deepEqual(err.conflictedFiles, conflicted);
139
+ assert.equal(err.strategy, "squash");
140
+ assert.equal(err.branch, "worktree/M001");
141
+ assert.equal(err.mainBranch, "main");
142
+ return true;
143
+ },
144
+ );
145
+ });
146
+
147
+ test("propagates non-conflict errors too (#4380 — never swallow silently)", () => {
148
+ const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
149
+ class FakePermError extends Error {}
150
+ const deps = makeDeps({
151
+ resolveMilestoneFile: (_base, _mid, type) =>
152
+ type === "ROADMAP" ? roadmapPath : null,
153
+ readFileSync: () => "# M001\n",
154
+ mergeMilestoneToMain: () => {
155
+ throw new FakePermError("EACCES: permission denied");
156
+ },
157
+ });
158
+
159
+ const resolver = new WorktreeResolver(makeSession(baseDir), deps);
160
+ const ctx = makeNotifyCtx();
161
+
162
+ assert.throws(
163
+ () => resolver.mergeAndExit("M001", ctx),
164
+ (err: unknown) => {
165
+ assert.ok(
166
+ err instanceof FakePermError,
167
+ `expected FakePermError, got: ${err}`,
168
+ );
169
+ return true;
170
+ },
171
+ );
172
+ });
173
+
174
+ test("successful merge does not throw", () => {
175
+ const roadmapPath = join(baseDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md");
176
+ const deps = makeDeps({
177
+ resolveMilestoneFile: (_base, _mid, type) =>
178
+ type === "ROADMAP" ? roadmapPath : null,
179
+ readFileSync: () => "# M001\n",
180
+ mergeMilestoneToMain: () => ({ pushed: false, codeFilesChanged: true }),
181
+ });
182
+
183
+ const resolver = new WorktreeResolver(makeSession(baseDir), deps);
184
+ const ctx = makeNotifyCtx();
185
+
186
+ // Should not throw — the success path.
187
+ assert.doesNotThrow(() => resolver.mergeAndExit("M001", ctx));
188
+ });
189
+ });
190
+
191
+ // ─── phases.ts handler contract ──────────────────────────────────────────
192
+ //
193
+ // The inline handler at `auto/phases.ts:580-598 / 695-712 / 823-840`:
194
+ //
195
+ // if (mergeErr instanceof MergeConflictError) {
196
+ // ctx.ui.notify(`Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. ...`);
197
+ // await deps.stopAuto(...);
198
+ // return { action: "break", reason: "merge-conflict" };
199
+ // }
200
+ //
201
+ // Testing it end-to-end requires constructing a full `IterationContext`
202
+ // + `LoopState` + `deps` surface (hundreds of fields). Extracting the
203
+ // handler into a reusable helper is the right refactor and is tracked
204
+ // alongside this issue. In the meantime, defend the contract between
205
+ // the thrower and the handler: if the fields the handler formats drift,
206
+ // the handler silently regresses.
207
+
208
+ describe("Merge-conflict handler contract (#2330 — phases.ts inline pattern)", () => {
209
+ test("MergeConflictError exposes fields the phases.ts handler formats", () => {
210
+ const err = new MergeConflictError(
211
+ ["a.ts", "b.ts"],
212
+ "squash",
213
+ "worktree/M001",
214
+ "main",
215
+ );
216
+ assert.deepEqual(err.conflictedFiles, ["a.ts", "b.ts"]);
217
+ assert.equal(err.strategy, "squash");
218
+ assert.equal(err.branch, "worktree/M001");
219
+ assert.equal(err.mainBranch, "main");
220
+ // instanceof is the type-discriminant the handler uses.
221
+ assert.ok(err instanceof MergeConflictError);
222
+ // The class extends Error so the non-conflict fallback message path
223
+ // (`String(mergeErr)` / `mergeErr.message`) still works.
224
+ assert.ok(err instanceof Error);
225
+ assert.match(err.message, /worktree\/M001/);
226
+ assert.match(err.message, /main/);
227
+ });
228
+
229
+ test("MergeConflictError with empty conflicted list still serializes (edge)", () => {
230
+ // The handler's `conflictedFiles.join(", ")` must not crash on empty
231
+ // list. Defensive: some producers could legitimately emit a
232
+ // zero-length array.
233
+ const err = new MergeConflictError([], "merge", "feature/x", "main");
234
+ assert.deepEqual(err.conflictedFiles, []);
235
+ assert.equal(err.conflictedFiles.join(", "), "");
236
+ assert.ok(err instanceof MergeConflictError);
237
+ });
238
+ });
@@ -0,0 +1,187 @@
1
+ // GSD-2 — #4781: classifier behavior matrix. Pure-function tests, no I/O.
2
+
3
+ import test from "node:test";
4
+ import assert from "node:assert/strict";
5
+
6
+ import {
7
+ classifyMilestoneScope,
8
+ type MilestoneScopeInput,
9
+ } from "../milestone-scope-classifier.ts";
10
+
11
+ // ─── Classification matrix ────────────────────────────────────────────────
12
+
13
+ test("#4781 classifier: single static HTML to-do app → trivial (b23 forensic case)", () => {
14
+ const input: MilestoneScopeInput = {
15
+ title: "To-Do App",
16
+ vision: "A minimal, clean browser-based to-do app. Pure HTML/CSS/JS, no build step, no backend. Tasks persist in localStorage.",
17
+ successCriteria: [
18
+ "Open index.html in any browser without a server",
19
+ "Add tasks by typing and pressing Enter or clicking Add",
20
+ "Mark tasks complete (toggleable)",
21
+ "Delete individual tasks",
22
+ "Tasks survive a page reload via localStorage",
23
+ ],
24
+ };
25
+ const r = classifyMilestoneScope(input);
26
+ assert.strictEqual(r.variant, "trivial", `expected trivial, got ${r.variant} — reasons: ${r.reasons.join("; ")}`);
27
+ assert.ok(r.reasons.some(s => s.includes("trivial keywords")), "should cite trivial keywords");
28
+ });
29
+
30
+ test("#4781 classifier: readme typo fix → trivial", () => {
31
+ const r = classifyMilestoneScope({
32
+ title: "Fix README typo",
33
+ vision: "Correct spelling error in the installation section.",
34
+ successCriteria: ["Typo fixed", "README renders correctly"],
35
+ });
36
+ assert.strictEqual(r.variant, "trivial");
37
+ });
38
+
39
+ test("#4781 classifier: auth flow single file → standard (override beats trivial)", () => {
40
+ const r = classifyMilestoneScope({
41
+ title: "Add login",
42
+ vision: "Implement authentication flow in a single file with OAuth credentials.",
43
+ successCriteria: ["User can log in"],
44
+ });
45
+ assert.strictEqual(r.variant, "standard", `override should beat single-file signal. reasons: ${r.reasons.join("; ")}`);
46
+ assert.ok(r.signals.triggeredOverride, "override signals should be flagged");
47
+ assert.ok(r.reasons.some(s => s.includes("override keywords")));
48
+ });
49
+
50
+ test("#4781 classifier: security review scope → standard (even if small)", () => {
51
+ const r = classifyMilestoneScope({
52
+ title: "Harden session tokens",
53
+ vision: "Review and patch security vulnerability in one session token helper.",
54
+ successCriteria: ["No XSS via token"],
55
+ });
56
+ assert.strictEqual(r.variant, "standard");
57
+ assert.ok(r.signals.triggeredOverride);
58
+ });
59
+
60
+ test("#4781 classifier: schema migration mentioned → standard (override-level signal)", () => {
61
+ const r = classifyMilestoneScope({
62
+ title: "User profile v2",
63
+ vision: "Perform schema migration to split user.name into first_name and last_name across the users table.",
64
+ successCriteria: ["Migration lands", "Existing rows backfilled", "Rollback path validated"],
65
+ });
66
+ // "migration" / "migrate" / "backfill" are OVERRIDE_KEYWORDS, not
67
+ // COMPLEX_KEYWORDS — migration is override-level (forces at least
68
+ // `standard`), not complex-level. Safe behavior: migrations need the
69
+ // full standard pipeline but not the extra ceremony of complex.
70
+ assert.strictEqual(r.variant, "standard", `reasons: ${r.reasons.join("; ")}`);
71
+ });
72
+
73
+ test("#4781 classifier: architecture keyword → complex", () => {
74
+ const r = classifyMilestoneScope({
75
+ title: "Redesign plugin registry",
76
+ vision: "Refactor core architecture of the plugin registry to support versioned contracts.",
77
+ });
78
+ assert.strictEqual(r.variant, "complex");
79
+ assert.ok(r.reasons.some(s => s.includes("complex keywords")));
80
+ });
81
+
82
+ test("#4781 classifier: >=8 files hint → complex", () => {
83
+ const r = classifyMilestoneScope({
84
+ title: "Multi-file refactor",
85
+ vision: "Touch 12 files to extract shared helpers.",
86
+ });
87
+ assert.strictEqual(r.variant, "complex");
88
+ assert.strictEqual(r.signals.fileCountHint, 12);
89
+ });
90
+
91
+ test("#4781 classifier: backend API mention → standard (not trivial)", () => {
92
+ const r = classifyMilestoneScope({
93
+ title: "Health endpoint",
94
+ vision: "Add a single-file API endpoint returning status.",
95
+ successCriteria: ["/health returns 200"],
96
+ });
97
+ // Single file + no override + but backend mentioned → not trivial
98
+ assert.strictEqual(r.variant, "standard");
99
+ });
100
+
101
+ test("#4781 classifier: tests mentioned → standard (not trivial)", () => {
102
+ const r = classifyMilestoneScope({
103
+ title: "Landing page",
104
+ vision: "Ship a static one-page landing page with unit tests for the form validation.",
105
+ });
106
+ assert.strictEqual(r.variant, "standard", `reasons: ${r.reasons.join("; ")}`);
107
+ });
108
+
109
+ test("#4781 classifier: ambiguous prose → standard (safe default)", () => {
110
+ const r = classifyMilestoneScope({
111
+ title: "Generic improvements",
112
+ vision: "Make the system better.",
113
+ successCriteria: ["It's better"],
114
+ });
115
+ assert.strictEqual(r.variant, "standard");
116
+ assert.ok(r.reasons.includes("no strong signals — default"));
117
+ });
118
+
119
+ test("#4781 classifier: empty input → standard (safe default)", () => {
120
+ const r = classifyMilestoneScope({});
121
+ assert.strictEqual(r.variant, "standard");
122
+ });
123
+
124
+ // ─── Override precedence over trivial ──────────────────────────────────────
125
+
126
+ test("#4781 classifier: override + trivial keyword → standard (override wins)", () => {
127
+ const r = classifyMilestoneScope({
128
+ title: "Token rotation",
129
+ vision: "Single file change to rotate the oauth token expiry schedule.",
130
+ });
131
+ // "single file" is trivial signal; "oauth" is override signal. Override wins.
132
+ assert.strictEqual(r.variant, "standard");
133
+ assert.ok(r.signals.triggeredOverride);
134
+ });
135
+
136
+ test("#4781 classifier: complex + override → complex (complex wins, flagged)", () => {
137
+ const r = classifyMilestoneScope({
138
+ title: "Auth service refactor",
139
+ vision: "Refactor core authentication architecture across services.",
140
+ });
141
+ // Complex (architecture, refactor core) wins over override (auth).
142
+ assert.strictEqual(r.variant, "complex");
143
+ // Override still recorded in signals for telemetry.
144
+ assert.ok(r.signals.triggeredOverride, "override hits should still be tracked in signals");
145
+ });
146
+
147
+ // ─── File count hint extraction ───────────────────────────────────────────
148
+
149
+ test("#4781 classifier: 'a single file' hint parsed as 1", () => {
150
+ const r = classifyMilestoneScope({
151
+ title: "Tweak",
152
+ vision: "Update a single file to flip the copy.",
153
+ });
154
+ assert.strictEqual(r.signals.fileCountHint, 1);
155
+ });
156
+
157
+ test("#4781 classifier: 'two files' hint parsed as 2", () => {
158
+ const r = classifyMilestoneScope({
159
+ title: "Minor",
160
+ vision: "Touch two files.",
161
+ });
162
+ assert.strictEqual(r.signals.fileCountHint, 2);
163
+ });
164
+
165
+ test("#4781 classifier: '12 files' hint parsed as 12", () => {
166
+ const r = classifyMilestoneScope({
167
+ title: "Bulk",
168
+ vision: "Update 12 files.",
169
+ });
170
+ assert.strictEqual(r.signals.fileCountHint, 12);
171
+ });
172
+
173
+ // ─── Reasons surface useful debugging info ─────────────────────────────────
174
+
175
+ test("#4781 classifier: reasons array populated for every branch", () => {
176
+ const branches: Array<[string, MilestoneScopeInput]> = [
177
+ ["trivial", { title: "Readme typo", vision: "Fix a single file typo." }],
178
+ ["standard (override)", { title: "Auth", vision: "Touch auth helper." }],
179
+ ["complex (keyword)", { title: "Arch", vision: "Refactor core system design." }],
180
+ ["complex (file count)", { title: "Bulk", vision: "Update 9 files." }],
181
+ ["standard (default)", { title: "Generic", vision: "General work." }],
182
+ ];
183
+ for (const [label, input] of branches) {
184
+ const r = classifyMilestoneScope(input);
185
+ assert.ok(r.reasons.length > 0, `${label}: reasons must not be empty`);
186
+ }
187
+ });
@@ -0,0 +1,30 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import { classifyMilestoneSummaryContent } from "../milestone-summary-classifier.ts";
5
+
6
+ test("milestone SUMMARY classifier treats explicit failed status as failure", () => {
7
+ assert.equal(
8
+ classifyMilestoneSummaryContent([
9
+ "---",
10
+ "status: failed",
11
+ "---",
12
+ "",
13
+ "# M001 Summary",
14
+ "Recovery stopped.",
15
+ ].join("\n")),
16
+ "failure",
17
+ );
18
+ });
19
+
20
+ test("milestone SUMMARY classifier does not treat historical not-complete prose as failure", () => {
21
+ assert.equal(
22
+ classifyMilestoneSummaryContent([
23
+ "# M001 Summary",
24
+ "",
25
+ "This milestone was previously not complete, now resolved.",
26
+ ].join("\n")),
27
+ "unknown",
28
+ );
29
+ });
30
+
@@ -74,7 +74,7 @@ test("#2885: cost table includes openai-codex provider models", () => {
74
74
  const ids = BUNDLED_COST_TABLE.map(e => e.id);
75
75
  const codexModels = [
76
76
  "gpt-5.1", "gpt-5.1-codex-max", "gpt-5.1-codex-mini",
77
- "gpt-5.2", "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.3-codex-spark", "gpt-5.4", "gpt-5.4-mini",
77
+ "gpt-5.2", "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.3-codex-spark", "gpt-5.4", "gpt-5.4-mini", "gpt-5.5",
78
78
  ];
79
79
  for (const model of codexModels) {
80
80
  assert.ok(ids.includes(model), `cost table should include openai-codex model "${model}"`);
@@ -101,3 +101,11 @@ test("#2885: lookupModelCost returns costs for new models (not 999 fallback)", (
101
101
  assert.ok(entry.inputPer1k < 999, `${model} should have a real cost, not the 999 fallback`);
102
102
  }
103
103
  });
104
+
105
+ test("gpt-5.5 uses official OpenAI list pricing", () => {
106
+ const entry = lookupModelCost("gpt-5.5");
107
+ assert.ok(entry, "lookupModelCost should find gpt-5.5");
108
+ assert.equal(entry.inputPer1k, 0.005);
109
+ assert.equal(entry.outputPer1k, 0.03);
110
+ assert.equal(entry.updatedAt, "2026-04-23");
111
+ });
@@ -382,7 +382,7 @@ test("#2885: openai-codex standard-tier models are recognized", () => {
382
382
 
383
383
  test("#2885: openai-codex heavy-tier models are recognized", () => {
384
384
  const config = { ...defaultRoutingConfig(), enabled: true };
385
- const heavyModels = ["gpt-5", "gpt-5-pro", "gpt-5.1", "gpt-5.2", "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.4", "o4-mini", "o4-mini-deep-research"];
385
+ const heavyModels = ["gpt-5", "gpt-5-pro", "gpt-5.1", "gpt-5.2", "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.4", "gpt-5.5", "o4-mini", "o4-mini-deep-research"];
386
386
  for (const model of heavyModels) {
387
387
  const result = resolveModelForComplexity(
388
388
  makeClassification("heavy"),
@@ -18,54 +18,12 @@ import { tmpdir } from "node:os";
18
18
  import { execFileSync } from "node:child_process";
19
19
  import { nativeIsRepo, nativeCommit, nativeResetHard } from "../native-git-bridge.js";
20
20
 
21
- // ─── Static analysis ──────────────────────────────────────────────────────
22
- // Verify the fallback paths of the three affected functions do not call the
23
- // raw execSync() string-command variant. Replacing all execFileSync( tokens
24
- // first ensures we match only the bare execSync( form.
25
-
26
- const SRC_PATH = join(import.meta.dirname, "..", "native-git-bridge.ts");
27
-
28
- function extractFunctionBody(src: string, fnName: string): string {
29
- const idx = src.indexOf(`export function ${fnName}`);
30
- if (idx === -1) throw new Error(`${fnName} not found in source`);
31
- return src.slice(idx, idx + 1500);
32
- }
33
-
34
- function hasRawExecSync(body: string): boolean {
35
- const withoutFileSync = body.replace(/execFileSync\(/g, "__FILESYNC__");
36
- return withoutFileSync.includes("execSync(");
37
- }
38
-
39
- describe("native-git-bridge #4180: fallback paths use execFileSync not execSync", () => {
40
- const src = readFileSync(SRC_PATH, "utf-8");
41
-
42
- test("nativeIsRepo fallback does not use raw execSync", () => {
43
- const body = extractFunctionBody(src, "nativeIsRepo");
44
- assert.equal(
45
- hasRawExecSync(body),
46
- false,
47
- "nativeIsRepo fallback must use execFileSync to avoid cmd.exe PATH failures on Windows",
48
- );
49
- });
50
-
51
- test("nativeCommit fallback does not use raw execSync", () => {
52
- const body = extractFunctionBody(src, "nativeCommit");
53
- assert.equal(
54
- hasRawExecSync(body),
55
- false,
56
- "nativeCommit fallback must use execFileSync to avoid cmd.exe PATH failures on Windows",
57
- );
58
- });
59
-
60
- test("nativeResetHard fallback does not use raw execSync", () => {
61
- const body = extractFunctionBody(src, "nativeResetHard");
62
- assert.equal(
63
- hasRawExecSync(body),
64
- false,
65
- "nativeResetHard fallback must use execFileSync to avoid cmd.exe PATH failures on Windows",
66
- );
67
- });
68
- });
21
+ // Note: prior static-analysis tests that scanned native-git-bridge.ts for
22
+ // the raw shell-spawn pattern were removed under #4827 the integration
23
+ // tests below already exercise the fallback path end-to-end with the native
24
+ // module disabled (GSD_ENABLE_NATIVE_GSD_GIT unset). Any cmd.exe PATH
25
+ // regression on Windows surfaces through a real fallback failure, not a
26
+ // grep miss in source text.
69
27
 
70
28
  // ─── Integration tests ────────────────────────────────────────────────────
71
29
  // Verify correct runtime behaviour through the fallback path (native module
@@ -16,9 +16,12 @@ test("buildNotificationWidgetLines shows unread count with shortcut pair", () =>
16
16
  appendNotification("Need attention", "warning");
17
17
 
18
18
  const lines = buildNotificationWidgetLines();
19
- assert.equal(lines.length, 1);
20
- assert.match(lines[0]!, /🔔\s+1 unread/);
21
- assert.match(lines[0]!, /\(.+\/.+\)/);
19
+ // Widget must render at least one line; may add secondary lines later
20
+ // (e.g., "View with /gsd notif") without breaking this assertion.
21
+ assert.ok(lines.length >= 1, `expected at least 1 widget line, got ${lines.length}`);
22
+ const combined = lines.join("\n");
23
+ assert.match(combined, /🔔\s+1 unread/);
24
+ assert.match(combined, /\(.+\/.+\)/);
22
25
  } finally {
23
26
  _resetNotificationStore();
24
27
  rmSync(tmp, { recursive: true, force: true });