gsd-pi 2.74.0-dev.b741afb → 2.74.0-dev.b7c5f96

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 (430) hide show
  1. package/dist/resources/extensions/gsd/activity-log.js +16 -0
  2. package/dist/resources/extensions/gsd/auto/loop.js +147 -10
  3. package/dist/resources/extensions/gsd/auto/phases.js +164 -9
  4. package/dist/resources/extensions/gsd/auto/session.js +10 -0
  5. package/dist/resources/extensions/gsd/auto-dispatch.js +11 -1
  6. package/dist/resources/extensions/gsd/auto-model-selection.js +54 -8
  7. package/dist/resources/extensions/gsd/auto-post-unit.js +215 -8
  8. package/dist/resources/extensions/gsd/auto-recovery.js +24 -10
  9. package/dist/resources/extensions/gsd/auto-unit-closeout.js +18 -0
  10. package/dist/resources/extensions/gsd/auto-verification.js +100 -2
  11. package/dist/resources/extensions/gsd/auto-worktree.js +2 -0
  12. package/dist/resources/extensions/gsd/auto.js +28 -2
  13. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +5 -3
  14. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +10 -1
  15. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +61 -9
  16. package/dist/resources/extensions/gsd/cache.js +16 -5
  17. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  18. package/dist/resources/extensions/gsd/commands/handlers/core.js +5 -1
  19. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  20. package/dist/resources/extensions/gsd/commands-extract-learnings.js +225 -0
  21. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +51 -4
  22. package/dist/resources/extensions/gsd/docs/preferences-reference.md +16 -1
  23. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +144 -0
  24. package/dist/resources/extensions/gsd/ecosystem/loader.js +145 -0
  25. package/dist/resources/extensions/gsd/git-service.js +49 -1
  26. package/dist/resources/extensions/gsd/graph-context.js +98 -7
  27. package/dist/resources/extensions/gsd/gsd-db.js +260 -2
  28. package/dist/resources/extensions/gsd/guided-flow.js +31 -6
  29. package/dist/resources/extensions/gsd/init-wizard.js +1 -0
  30. package/dist/resources/extensions/gsd/journal.js +27 -0
  31. package/dist/resources/extensions/gsd/metrics.js +19 -0
  32. package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
  33. package/dist/resources/extensions/gsd/preferences-models.js +20 -3
  34. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  35. package/dist/resources/extensions/gsd/preferences-validation.js +118 -2
  36. package/dist/resources/extensions/gsd/preferences.js +31 -0
  37. package/dist/resources/extensions/gsd/safety/evidence-collector.js +15 -30
  38. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
  39. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +19 -0
  40. package/dist/resources/extensions/gsd/tools/complete-slice.js +5 -0
  41. package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
  42. package/dist/resources/extensions/gsd/unit-ownership.js +1 -1
  43. package/dist/resources/extensions/gsd/uok/audit-toggle.js +7 -0
  44. package/dist/resources/extensions/gsd/uok/audit.js +40 -0
  45. package/dist/resources/extensions/gsd/uok/contracts.js +1 -0
  46. package/dist/resources/extensions/gsd/uok/execution-graph.js +179 -0
  47. package/dist/resources/extensions/gsd/uok/flags.js +29 -0
  48. package/dist/resources/extensions/gsd/uok/gate-runner.js +109 -0
  49. package/dist/resources/extensions/gsd/uok/gitops.js +53 -0
  50. package/dist/resources/extensions/gsd/uok/kernel.js +80 -0
  51. package/dist/resources/extensions/gsd/uok/loop-adapter.js +133 -0
  52. package/dist/resources/extensions/gsd/uok/model-policy.js +66 -0
  53. package/dist/resources/extensions/gsd/uok/plan-v2.js +132 -0
  54. package/dist/resources/extensions/gsd/workflow-logger.js +22 -0
  55. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  56. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  57. package/dist/web/standalone/.next/BUILD_ID +1 -1
  58. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  59. package/dist/web/standalone/.next/build-manifest.json +2 -2
  60. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  61. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  82. package/dist/web/standalone/.next/server/app/index.html +1 -1
  83. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  90. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  91. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  93. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  94. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  95. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  96. package/package.json +1 -1
  97. package/packages/mcp-server/dist/readers/graph.d.ts +1 -1
  98. package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -1
  99. package/packages/mcp-server/dist/readers/graph.js +107 -0
  100. package/packages/mcp-server/dist/readers/graph.js.map +1 -1
  101. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  102. package/packages/mcp-server/dist/workflow-tools.js +88 -6
  103. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  104. package/packages/mcp-server/src/readers/graph.test.ts +178 -0
  105. package/packages/mcp-server/src/readers/graph.ts +148 -1
  106. package/packages/mcp-server/src/workflow-tools.ts +95 -10
  107. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  108. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  109. package/packages/pi-ai/dist/index.d.ts +1 -9
  110. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  111. package/packages/pi-ai/dist/index.js +1 -9
  112. package/packages/pi-ai/dist/index.js.map +1 -1
  113. package/packages/pi-ai/dist/models/capability-patches.d.ts +19 -0
  114. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -0
  115. package/packages/pi-ai/dist/models/capability-patches.js +36 -0
  116. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -0
  117. package/packages/pi-ai/dist/{models.custom.d.ts → models/custom.d.ts} +1 -1
  118. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -0
  119. package/packages/pi-ai/dist/{models.custom.js → models/custom.js} +4 -4
  120. package/packages/pi-ai/dist/models/custom.js.map +1 -0
  121. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +1482 -0
  122. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -0
  123. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +1484 -0
  124. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -0
  125. package/packages/pi-ai/dist/models/generated/anthropic.d.ts +377 -0
  126. package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -0
  127. package/packages/pi-ai/dist/models/generated/anthropic.js +379 -0
  128. package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -0
  129. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts +700 -0
  130. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts.map +1 -0
  131. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js +702 -0
  132. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js.map +1 -0
  133. package/packages/pi-ai/dist/models/generated/cerebras.d.ts +71 -0
  134. package/packages/pi-ai/dist/models/generated/cerebras.d.ts.map +1 -0
  135. package/packages/pi-ai/dist/models/generated/cerebras.js +73 -0
  136. package/packages/pi-ai/dist/models/generated/cerebras.js.map +1 -0
  137. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts +590 -0
  138. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts.map +1 -0
  139. package/packages/pi-ai/dist/models/generated/github-copilot.js +444 -0
  140. package/packages/pi-ai/dist/models/generated/github-copilot.js.map +1 -0
  141. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +156 -0
  142. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -0
  143. package/packages/pi-ai/dist/models/generated/google-antigravity.js +158 -0
  144. package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -0
  145. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts +105 -0
  146. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts.map +1 -0
  147. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js +107 -0
  148. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js.map +1 -0
  149. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts +207 -0
  150. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts.map +1 -0
  151. package/packages/pi-ai/dist/models/generated/google-vertex.js +209 -0
  152. package/packages/pi-ai/dist/models/generated/google-vertex.js.map +1 -0
  153. package/packages/pi-ai/dist/models/generated/google.d.ts +462 -0
  154. package/packages/pi-ai/dist/models/generated/google.d.ts.map +1 -0
  155. package/packages/pi-ai/dist/models/generated/google.js +464 -0
  156. package/packages/pi-ai/dist/models/generated/google.js.map +1 -0
  157. package/packages/pi-ai/dist/models/generated/groq.d.ts +309 -0
  158. package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -0
  159. package/packages/pi-ai/dist/models/generated/groq.js +311 -0
  160. package/packages/pi-ai/dist/models/generated/groq.js.map +1 -0
  161. package/packages/pi-ai/dist/models/generated/huggingface.d.ts +383 -0
  162. package/packages/pi-ai/dist/models/generated/huggingface.d.ts.map +1 -0
  163. package/packages/pi-ai/dist/models/generated/huggingface.js +347 -0
  164. package/packages/pi-ai/dist/models/generated/huggingface.js.map +1 -0
  165. package/packages/pi-ai/dist/{models.generated.d.ts → models/generated/index.d.ts} +1 -1
  166. package/packages/pi-ai/dist/{models.generated.d.ts.map → models/generated/index.d.ts.map} +1 -1
  167. package/packages/pi-ai/dist/models/generated/index.js +51 -0
  168. package/packages/pi-ai/dist/models/generated/index.js.map +1 -0
  169. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts +37 -0
  170. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts.map +1 -0
  171. package/packages/pi-ai/dist/models/generated/kimi-coding.js +39 -0
  172. package/packages/pi-ai/dist/models/generated/kimi-coding.js.map +1 -0
  173. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts +105 -0
  174. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts.map +1 -0
  175. package/packages/pi-ai/dist/models/generated/minimax-cn.js +107 -0
  176. package/packages/pi-ai/dist/models/generated/minimax-cn.js.map +1 -0
  177. package/packages/pi-ai/dist/models/generated/minimax.d.ts +105 -0
  178. package/packages/pi-ai/dist/models/generated/minimax.d.ts.map +1 -0
  179. package/packages/pi-ai/dist/models/generated/minimax.js +107 -0
  180. package/packages/pi-ai/dist/models/generated/minimax.js.map +1 -0
  181. package/packages/pi-ai/dist/models/generated/mistral.d.ts +445 -0
  182. package/packages/pi-ai/dist/models/generated/mistral.d.ts.map +1 -0
  183. package/packages/pi-ai/dist/models/generated/mistral.js +447 -0
  184. package/packages/pi-ai/dist/models/generated/mistral.js.map +1 -0
  185. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +139 -0
  186. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -0
  187. package/packages/pi-ai/dist/models/generated/openai-codex.js +141 -0
  188. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -0
  189. package/packages/pi-ai/dist/models/generated/openai.d.ts +700 -0
  190. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -0
  191. package/packages/pi-ai/dist/models/generated/openai.js +702 -0
  192. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -0
  193. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts +122 -0
  194. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts.map +1 -0
  195. package/packages/pi-ai/dist/models/generated/opencode-go.js +124 -0
  196. package/packages/pi-ai/dist/models/generated/opencode-go.js.map +1 -0
  197. package/packages/pi-ai/dist/models/generated/opencode.d.ts +530 -0
  198. package/packages/pi-ai/dist/models/generated/opencode.d.ts.map +1 -0
  199. package/packages/pi-ai/dist/models/generated/opencode.js +532 -0
  200. package/packages/pi-ai/dist/models/generated/opencode.js.map +1 -0
  201. package/packages/pi-ai/dist/models/generated/openrouter.d.ts +4270 -0
  202. package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -0
  203. package/packages/pi-ai/dist/models/generated/openrouter.js +4272 -0
  204. package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -0
  205. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts +2604 -0
  206. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts.map +1 -0
  207. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js +2606 -0
  208. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js.map +1 -0
  209. package/packages/pi-ai/dist/models/generated/xai.d.ts +411 -0
  210. package/packages/pi-ai/dist/models/generated/xai.d.ts.map +1 -0
  211. package/packages/pi-ai/dist/models/generated/xai.js +413 -0
  212. package/packages/pi-ai/dist/models/generated/xai.js.map +1 -0
  213. package/packages/pi-ai/dist/models/generated/zai.d.ts +276 -0
  214. package/packages/pi-ai/dist/models/generated/zai.d.ts.map +1 -0
  215. package/packages/pi-ai/dist/models/generated/zai.js +239 -0
  216. package/packages/pi-ai/dist/models/generated/zai.js.map +1 -0
  217. package/packages/pi-ai/dist/models/index.d.ts +27 -0
  218. package/packages/pi-ai/dist/models/index.d.ts.map +1 -0
  219. package/packages/pi-ai/dist/models/index.js +80 -0
  220. package/packages/pi-ai/dist/models/index.js.map +1 -0
  221. package/packages/pi-ai/dist/models.d.ts +1 -36
  222. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  223. package/packages/pi-ai/dist/models.generated.test.js +1 -2
  224. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  225. package/packages/pi-ai/dist/models.js +3 -112
  226. package/packages/pi-ai/dist/models.js.map +1 -1
  227. package/packages/pi-ai/dist/models.test.js +6 -5
  228. package/packages/pi-ai/dist/models.test.js.map +1 -1
  229. package/packages/pi-ai/scripts/generate-models.ts +74 -40
  230. package/packages/pi-ai/src/index.ts +1 -9
  231. package/packages/pi-ai/src/models/capability-patches.ts +40 -0
  232. package/packages/pi-ai/src/{models.custom.ts → models/custom.ts} +4 -4
  233. package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1486 -0
  234. package/packages/pi-ai/src/models/generated/anthropic.ts +381 -0
  235. package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
  236. package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
  237. package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
  238. package/packages/pi-ai/src/models/generated/google-antigravity.ts +160 -0
  239. package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
  240. package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
  241. package/packages/pi-ai/src/models/generated/google.ts +466 -0
  242. package/packages/pi-ai/src/models/generated/groq.ts +313 -0
  243. package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
  244. package/packages/pi-ai/src/models/generated/index.ts +52 -0
  245. package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
  246. package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
  247. package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
  248. package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
  249. package/packages/pi-ai/src/models/generated/openai-codex.ts +143 -0
  250. package/packages/pi-ai/src/models/generated/openai.ts +704 -0
  251. package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
  252. package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
  253. package/packages/pi-ai/src/models/generated/openrouter.ts +4274 -0
  254. package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
  255. package/packages/pi-ai/src/models/generated/xai.ts +415 -0
  256. package/packages/pi-ai/src/models/generated/zai.ts +241 -0
  257. package/packages/pi-ai/src/models/index.ts +106 -0
  258. package/packages/pi-ai/src/models.generated.test.ts +1 -2
  259. package/packages/pi-ai/src/models.test.ts +6 -5
  260. package/packages/pi-ai/src/models.ts +3 -153
  261. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  262. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  263. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -2
  264. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  265. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +472 -0
  266. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  267. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts +2 -0
  268. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts.map +1 -0
  269. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js +52 -0
  270. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js.map +1 -0
  271. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  273. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  274. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.d.ts +2 -0
  275. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.d.ts.map +1 -0
  276. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +61 -0
  277. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -0
  278. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +11 -0
  279. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  280. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +1 -0
  281. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  282. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +23 -9
  283. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +11 -0
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -0
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +53 -0
  287. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.d.ts +8 -5
  289. package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.js +27 -13
  291. package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  294. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +68 -8
  295. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +22 -22
  298. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +232 -18
  301. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts +2 -0
  303. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts.map +1 -0
  304. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +38 -0
  305. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -0
  306. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +14 -0
  307. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  308. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +70 -6
  309. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  310. package/packages/pi-coding-agent/src/core/agent-session.ts +12 -6
  311. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +612 -0
  312. package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
  313. package/packages/pi-coding-agent/src/core/model-registry.ts +2 -1
  314. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +92 -0
  315. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +19 -0
  316. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +25 -10
  317. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +75 -0
  318. package/packages/pi-coding-agent/src/modes/interactive/components/compaction-summary-message.ts +36 -15
  319. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +83 -7
  320. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +23 -26
  321. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +298 -41
  322. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +44 -0
  323. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +92 -6
  324. package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
  325. package/packages/pi-coding-agent/tsconfig.json +2 -2
  326. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  327. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  328. package/packages/pi-tui/dist/tui.js +9 -2
  329. package/packages/pi-tui/dist/tui.js.map +1 -1
  330. package/packages/pi-tui/src/tui.ts +9 -1
  331. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  332. package/src/resources/extensions/gsd/activity-log.ts +21 -0
  333. package/src/resources/extensions/gsd/auto/loop-deps.ts +4 -0
  334. package/src/resources/extensions/gsd/auto/loop.ts +159 -10
  335. package/src/resources/extensions/gsd/auto/phases.ts +193 -9
  336. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  337. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -6
  338. package/src/resources/extensions/gsd/auto-model-selection.ts +69 -8
  339. package/src/resources/extensions/gsd/auto-post-unit.ts +226 -9
  340. package/src/resources/extensions/gsd/auto-recovery.ts +29 -9
  341. package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
  342. package/src/resources/extensions/gsd/auto-verification.ts +129 -2
  343. package/src/resources/extensions/gsd/auto-worktree.ts +1 -0
  344. package/src/resources/extensions/gsd/auto.ts +34 -2
  345. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +5 -3
  346. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -1
  347. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +72 -8
  348. package/src/resources/extensions/gsd/cache.ts +16 -5
  349. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  350. package/src/resources/extensions/gsd/commands/handlers/core.ts +5 -1
  351. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  352. package/src/resources/extensions/gsd/commands-extract-learnings.ts +304 -0
  353. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +58 -4
  354. package/src/resources/extensions/gsd/docs/preferences-reference.md +16 -1
  355. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +228 -0
  356. package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
  357. package/src/resources/extensions/gsd/git-service.ts +68 -0
  358. package/src/resources/extensions/gsd/graph-context.ts +139 -12
  359. package/src/resources/extensions/gsd/gsd-db.ts +321 -3
  360. package/src/resources/extensions/gsd/guided-flow.ts +36 -2
  361. package/src/resources/extensions/gsd/init-wizard.ts +3 -2
  362. package/src/resources/extensions/gsd/journal.ts +30 -0
  363. package/src/resources/extensions/gsd/metrics.ts +26 -0
  364. package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
  365. package/src/resources/extensions/gsd/preferences-models.ts +20 -3
  366. package/src/resources/extensions/gsd/preferences-types.ts +38 -0
  367. package/src/resources/extensions/gsd/preferences-validation.ts +117 -2
  368. package/src/resources/extensions/gsd/preferences.ts +34 -0
  369. package/src/resources/extensions/gsd/safety/evidence-collector.ts +15 -31
  370. package/src/resources/extensions/gsd/session-lock.ts +14 -2
  371. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +20 -1
  372. package/src/resources/extensions/gsd/templates/PREFERENCES.md +19 -0
  373. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +177 -0
  374. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +7 -3
  375. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
  376. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
  377. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +272 -0
  378. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +117 -0
  379. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
  380. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +340 -0
  381. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  382. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  383. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
  384. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  385. package/src/resources/extensions/gsd/tests/health-widget.test.ts +1 -1
  386. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +3 -3
  387. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -2
  388. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -3
  389. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  390. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +2 -1
  391. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +40 -1
  392. package/src/resources/extensions/gsd/tests/preferences.test.ts +145 -0
  393. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +57 -2
  394. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
  395. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -5
  396. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
  397. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +85 -0
  398. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +69 -0
  399. package/src/resources/extensions/gsd/tests/uok-flags.test.ts +39 -0
  400. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +70 -0
  401. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +85 -0
  402. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +35 -0
  403. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
  404. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +167 -0
  405. package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
  406. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
  407. package/src/resources/extensions/gsd/tools/complete-slice.ts +9 -2
  408. package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
  409. package/src/resources/extensions/gsd/types.ts +14 -1
  410. package/src/resources/extensions/gsd/unit-ownership.ts +2 -2
  411. package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
  412. package/src/resources/extensions/gsd/uok/audit.ts +51 -0
  413. package/src/resources/extensions/gsd/uok/contracts.ts +135 -0
  414. package/src/resources/extensions/gsd/uok/execution-graph.ts +241 -0
  415. package/src/resources/extensions/gsd/uok/flags.ts +45 -0
  416. package/src/resources/extensions/gsd/uok/gate-runner.ts +146 -0
  417. package/src/resources/extensions/gsd/uok/gitops.ts +75 -0
  418. package/src/resources/extensions/gsd/uok/kernel.ts +105 -0
  419. package/src/resources/extensions/gsd/uok/loop-adapter.ts +162 -0
  420. package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
  421. package/src/resources/extensions/gsd/uok/plan-v2.ts +156 -0
  422. package/src/resources/extensions/gsd/workflow-logger.ts +27 -1
  423. package/src/resources/extensions/ttsr/ttsr-manager.ts +10 -5
  424. package/packages/pi-ai/dist/models.custom.d.ts.map +0 -1
  425. package/packages/pi-ai/dist/models.custom.js.map +0 -1
  426. package/packages/pi-ai/dist/models.generated.js +0 -14343
  427. package/packages/pi-ai/dist/models.generated.js.map +0 -1
  428. package/packages/pi-ai/src/models.generated.ts +0 -14345
  429. /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → k1VZ0h-SB6uWSZgPhgNwi}/_buildManifest.js +0 -0
  430. /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → k1VZ0h-SB6uWSZgPhgNwi}/_ssgManifest.js +0 -0
@@ -39,6 +39,24 @@ dynamic_routing:
39
39
  budget_pressure:
40
40
  cross_provider:
41
41
  hooks:
42
+ uok:
43
+ enabled: true
44
+ legacy_fallback:
45
+ enabled: false
46
+ gates:
47
+ enabled: false
48
+ model_policy:
49
+ enabled: false
50
+ execution_graph:
51
+ enabled: false
52
+ gitops:
53
+ enabled: false
54
+ turn_action: status-only
55
+ turn_push: false
56
+ audit_unified:
57
+ enabled: false
58
+ plan_v2:
59
+ enabled: false
42
60
  auto_visualize:
43
61
  auto_report:
44
62
  parallel:
@@ -71,6 +89,7 @@ remote_questions:
71
89
  uat_dispatch:
72
90
  post_unit_hooks: []
73
91
  pre_dispatch_hooks: []
92
+ # language:
74
93
  # experimental:
75
94
  # rtk: false
76
95
  ---
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Regression test: invalidateAllCaches() must NOT wipe the artifacts table.
3
+ *
4
+ * Prior to this fix, `cache.ts` bundled `clearArtifacts()` (which runs
5
+ * `DELETE FROM artifacts`) into `invalidateAllCaches()`. That helper fires
6
+ * on every post-unit pass, so rows written by `saveArtifactToDb` and
7
+ * `writeAndStore` (RESEARCH, CONTEXT, VALIDATION, ASSESSMENT, PLAN,
8
+ * ROADMAP, task PLAN, task SUMMARY) got deleted within seconds of being
9
+ * written. The milestone completed on disk, but `SELECT COUNT(*) FROM
10
+ * artifacts` returned 0, and the agent fell into a "file exists but DB
11
+ * record missing" recovery loop.
12
+ *
13
+ * The artifacts table is a write-through store, not a read cache. Routine
14
+ * cache invalidation must preserve its contents.
15
+ *
16
+ * Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
17
+ */
18
+
19
+ import { describe, test, afterEach } from "node:test";
20
+ import assert from "node:assert/strict";
21
+ import { readFileSync } from "node:fs";
22
+ import { resolve } from "node:path";
23
+
24
+ import { invalidateAllCaches } from "../cache.ts";
25
+ import {
26
+ openDatabase,
27
+ closeDatabase,
28
+ insertArtifact,
29
+ isDbAvailable,
30
+ _getAdapter,
31
+ } from "../gsd-db.ts";
32
+
33
+ afterEach(() => {
34
+ if (isDbAvailable()) {
35
+ try {
36
+ closeDatabase();
37
+ } catch {
38
+ /* best-effort teardown */
39
+ }
40
+ }
41
+ });
42
+
43
+ describe("invalidateAllCaches() must preserve the artifacts table", () => {
44
+ test("rows survive a single invalidate call", () => {
45
+ const opened = openDatabase(":memory:");
46
+ assert.equal(opened, true, "in-memory DB must open");
47
+
48
+ insertArtifact({
49
+ path: "milestones/M001/slices/S01/S01-RESEARCH.md",
50
+ artifact_type: "RESEARCH",
51
+ milestone_id: "M001",
52
+ slice_id: "S01",
53
+ task_id: null,
54
+ full_content: "# Research\n\nFindings go here.\n",
55
+ });
56
+
57
+ invalidateAllCaches();
58
+
59
+ const adapter = _getAdapter();
60
+ assert.ok(adapter, "adapter should be available");
61
+ const row = adapter!
62
+ .prepare(
63
+ "SELECT path, artifact_type, length(full_content) AS len FROM artifacts WHERE path = :path",
64
+ )
65
+ .get({ ":path": "milestones/M001/slices/S01/S01-RESEARCH.md" }) as
66
+ | { path: string; artifact_type: string; len: number }
67
+ | undefined;
68
+
69
+ assert.ok(
70
+ row,
71
+ "artifact row must still exist after invalidateAllCaches — this is the Phase B bug",
72
+ );
73
+ assert.equal(row!.artifact_type, "RESEARCH");
74
+ assert.ok((row!.len ?? 0) > 0, "full_content must not be truncated");
75
+ });
76
+
77
+ test("multiple rows for a full milestone survive repeated invalidates", () => {
78
+ openDatabase(":memory:");
79
+
80
+ const inserts = [
81
+ {
82
+ path: "milestones/M001/M001-ROADMAP.md",
83
+ artifact_type: "ROADMAP",
84
+ milestone_id: "M001",
85
+ slice_id: null,
86
+ task_id: null,
87
+ },
88
+ {
89
+ path: "milestones/M001/slices/S01/S01-RESEARCH.md",
90
+ artifact_type: "RESEARCH",
91
+ milestone_id: "M001",
92
+ slice_id: "S01",
93
+ task_id: null,
94
+ },
95
+ {
96
+ path: "milestones/M001/slices/S01/S01-PLAN.md",
97
+ artifact_type: "PLAN",
98
+ milestone_id: "M001",
99
+ slice_id: "S01",
100
+ task_id: null,
101
+ },
102
+ {
103
+ path: "milestones/M001/slices/S01/tasks/T01-PLAN.md",
104
+ artifact_type: "PLAN",
105
+ milestone_id: "M001",
106
+ slice_id: "S01",
107
+ task_id: "T01",
108
+ },
109
+ {
110
+ path: "milestones/M001/slices/S01/tasks/T01-SUMMARY.md",
111
+ artifact_type: "SUMMARY",
112
+ milestone_id: "M001",
113
+ slice_id: "S01",
114
+ task_id: "T01",
115
+ },
116
+ {
117
+ path: "milestones/M001/M001-SUMMARY.md",
118
+ artifact_type: "SUMMARY",
119
+ milestone_id: "M001",
120
+ slice_id: null,
121
+ task_id: null,
122
+ },
123
+ ];
124
+
125
+ for (const i of inserts) {
126
+ insertArtifact({ ...i, full_content: `# ${i.artifact_type} content\n` });
127
+ }
128
+
129
+ // Simulate a full milestone's worth of post-unit cycles.
130
+ for (let i = 0; i < 10; i++) {
131
+ invalidateAllCaches();
132
+ }
133
+
134
+ const adapter = _getAdapter()!;
135
+ const count = (
136
+ adapter.prepare("SELECT COUNT(*) AS n FROM artifacts").get() as { n: number }
137
+ ).n;
138
+
139
+ assert.equal(
140
+ count,
141
+ inserts.length,
142
+ `all ${inserts.length} artifact rows must survive repeated invalidate calls; got ${count}`,
143
+ );
144
+ });
145
+ });
146
+
147
+ describe("cache.ts must not re-import clearArtifacts into invalidateAllCaches", () => {
148
+ const src = readFileSync(
149
+ resolve(process.cwd(), "src", "resources", "extensions", "gsd", "cache.ts"),
150
+ "utf-8",
151
+ );
152
+
153
+ test("clearArtifacts is not imported from gsd-db", () => {
154
+ assert.ok(
155
+ !/import\s*\{[^}]*clearArtifacts[^}]*\}\s*from\s*['"]\.\/gsd-db/.test(src),
156
+ "cache.ts must not import clearArtifacts — it causes the artifacts-table-wipe regression",
157
+ );
158
+ });
159
+
160
+ test("invalidateAllCaches does not call clearArtifacts", () => {
161
+ const fnIdx = src.indexOf("function invalidateAllCaches");
162
+ assert.ok(fnIdx !== -1);
163
+ const body = src.slice(fnIdx, fnIdx + 1000);
164
+ assert.ok(
165
+ !/\bclearArtifacts\s*\(/.test(body),
166
+ "invalidateAllCaches must not call clearArtifacts() — it wipes the write-through store",
167
+ );
168
+ });
169
+
170
+ test("cache.ts documents why clearArtifacts is not bundled here", () => {
171
+ // Future reviewers need to see the rationale or they'll re-add it.
172
+ assert.ok(
173
+ /artifacts.*NOT included|write-through store/i.test(src),
174
+ "cache.ts must explain why the artifacts table is NOT invalidated here",
175
+ );
176
+ });
177
+ });
@@ -1267,7 +1267,7 @@ test("auto-loop.ts barrel re-exports autoLoop, runUnit, and resolveAgentEnd", ()
1267
1267
  );
1268
1268
  });
1269
1269
 
1270
- test("auto.ts startAuto calls autoLoop (not dispatchNextUnit as first dispatch)", () => {
1270
+ test("auto.ts startAuto dispatches through the UOK kernel wrapper (legacy loop adapter)", () => {
1271
1271
  const src = readFileSync(
1272
1272
  resolve(import.meta.dirname, "..", "auto.ts"),
1273
1273
  "utf-8",
@@ -1279,8 +1279,12 @@ test("auto.ts startAuto calls autoLoop (not dispatchNextUnit as first dispatch)"
1279
1279
  const fnBlock =
1280
1280
  fnEnd > -1 ? src.slice(fnIdx, fnEnd) : src.slice(fnIdx, fnIdx + 5000);
1281
1281
  assert.ok(
1282
- fnBlock.includes("autoLoop("),
1283
- "startAuto must call autoLoop() instead of dispatchNextUnit()",
1282
+ fnBlock.includes("runAutoLoopWithUok("),
1283
+ "startAuto must dispatch through runAutoLoopWithUok()",
1284
+ );
1285
+ assert.ok(
1286
+ fnBlock.includes("runLegacyLoop: autoLoop"),
1287
+ "startAuto must preserve the legacy autoLoop adapter in kernel dispatch",
1284
1288
  );
1285
1289
  });
1286
1290
 
@@ -227,6 +227,26 @@ test("model change notify in selectAndApplyModel is gated behind verbose flag",
227
227
  );
228
228
  });
229
229
 
230
+ test("model policy resolves candidates from the policy-eligible pool", () => {
231
+ const src = readFileSync(join(__dirname, "..", "auto-model-selection.ts"), "utf-8");
232
+ assert.ok(
233
+ src.includes("const resolutionPool = uokFlags.modelPolicy ? routingEligibleModels : availableModels"),
234
+ "selectAndApplyModel should resolve model IDs against policy-eligible models when model policy is enabled",
235
+ );
236
+ });
237
+
238
+ test("model policy receives task metadata for requirement-vector decisions", () => {
239
+ const src = readFileSync(join(__dirname, "..", "auto-model-selection.ts"), "utf-8");
240
+ assert.ok(
241
+ src.includes("taskMetadata: taskMetadataForPolicy"),
242
+ "applyModelPolicyFilter should receive task metadata so requirement vectors are unit-aware",
243
+ );
244
+ assert.ok(
245
+ src.includes("extractTaskMetadata(unitId, basePath)"),
246
+ "execute-task dispatch should derive metadata before policy filtering",
247
+ );
248
+ });
249
+
230
250
  test("resolveModelId: anthropic wins over claude-code when session provider is not claude-code", () => {
231
251
  const availableModels = [
232
252
  { id: "claude-sonnet-4-6", provider: "claude-code" },
@@ -13,11 +13,15 @@ test("auto-mode captures GSD_PROJECT_ROOT before entering the dispatch loop", ()
13
13
  const resumeCallIdx = source.indexOf("captureProjectRootEnv(s.originalBasePath || s.basePath);");
14
14
  assert.ok(resumeCallIdx > -1, "auto.ts should capture GSD_PROJECT_ROOT before resume autoLoop");
15
15
 
16
- const firstAutoLoopIdx = source.indexOf("await autoLoop(ctx, pi, s, buildLoopDeps());");
17
- assert.ok(firstAutoLoopIdx > -1, "auto.ts should invoke autoLoop()");
16
+ const firstLoopIdxCandidates = [
17
+ source.indexOf("await runAutoLoopWithUok({"),
18
+ source.indexOf("await autoLoop(ctx, pi, s, buildLoopDeps());"),
19
+ ].filter((idx) => idx > -1);
20
+ const firstAutoLoopIdx = firstLoopIdxCandidates.length > 0 ? Math.min(...firstLoopIdxCandidates) : -1;
21
+ assert.ok(firstAutoLoopIdx > -1, "auto.ts should invoke the auto dispatch loop");
18
22
  assert.ok(
19
23
  resumeCallIdx < firstAutoLoopIdx,
20
- "auto.ts must set GSD_PROJECT_ROOT before the first autoLoop() call",
24
+ "auto.ts must set GSD_PROJECT_ROOT before the first loop call",
21
25
  );
22
26
  });
23
27
 
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Regression tests for PR #4288 — auto-retry bug, .mcp.json churn, and MCP
3
+ * worktree routing fixes.
4
+ *
5
+ * Covers four source-file changes:
6
+ * 1. src/resources/extensions/gsd/safety/evidence-collector.ts (functional)
7
+ * 2. src/resources/extensions/gsd/bootstrap/register-hooks.ts (source shape)
8
+ * 3. src/resources/extensions/gsd/auto-recovery.ts (source shape)
9
+ * 4. packages/mcp-server/src/workflow-tools.ts (source shape)
10
+ *
11
+ * Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
12
+ */
13
+
14
+ import { describe, it, beforeEach } from "node:test";
15
+ import assert from "node:assert/strict";
16
+ import { readFileSync } from "node:fs";
17
+ import { resolve } from "node:path";
18
+
19
+ import {
20
+ resetEvidence,
21
+ getEvidence,
22
+ recordToolCall,
23
+ recordToolResult,
24
+ type BashEvidence,
25
+ } from "../safety/evidence-collector.js";
26
+
27
+ // ─── 1. evidence-collector: functional ─────────────────────────────────────
28
+
29
+ describe("evidence-collector: toolCallId-based matching (A-3)", () => {
30
+ beforeEach(() => {
31
+ resetEvidence();
32
+ });
33
+
34
+ it("records bash calls with their toolCallId at dispatch time", () => {
35
+ recordToolCall("tc-1", "bash", { command: "ls -la" });
36
+ recordToolCall("tc-2", "bash", { command: "git status" });
37
+
38
+ const entries = getEvidence();
39
+ assert.equal(entries.length, 2);
40
+ assert.equal(entries[0].toolCallId, "tc-1");
41
+ assert.equal(entries[1].toolCallId, "tc-2");
42
+ });
43
+
44
+ it("matches results to the correct entry by toolCallId, not insertion order", () => {
45
+ // Simulate two parallel bash calls dispatched in order tc-1, tc-2.
46
+ recordToolCall("tc-1", "bash", { command: "slow-thing" });
47
+ recordToolCall("tc-2", "bash", { command: "fast-thing" });
48
+
49
+ // Results arrive out of order: tc-2 first (fast), then tc-1 (slow).
50
+ // With the old empty-string-matching strategy, tc-2's result would be
51
+ // stapled to tc-1's entry because findLastUnresolved scanned backwards
52
+ // for empty ids. Now we match by id directly.
53
+ recordToolResult("tc-2", "bash", "Command exited with code 0\nfast-output", false);
54
+ recordToolResult("tc-1", "bash", "Command exited with code 1\nslow-failure", true);
55
+
56
+ const entries = getEvidence() as readonly BashEvidence[];
57
+ const tc1 = entries.find(e => e.toolCallId === "tc-1") as BashEvidence | undefined;
58
+ const tc2 = entries.find(e => e.toolCallId === "tc-2") as BashEvidence | undefined;
59
+
60
+ assert.ok(tc1, "tc-1 entry must exist");
61
+ assert.ok(tc2, "tc-2 entry must exist");
62
+
63
+ // The original command stays attached to the entry it was recorded with,
64
+ // and the result matches the id it was reported for.
65
+ assert.equal(tc1.command, "slow-thing");
66
+ assert.equal(tc1.exitCode, 1);
67
+ assert.ok(tc1.outputSnippet.includes("slow-failure"));
68
+
69
+ assert.equal(tc2.command, "fast-thing");
70
+ assert.equal(tc2.exitCode, 0);
71
+ assert.ok(tc2.outputSnippet.includes("fast-output"));
72
+ });
73
+
74
+ it("ignores results with unknown toolCallIds rather than corrupting nearby entries", () => {
75
+ recordToolCall("tc-1", "bash", { command: "real" });
76
+ recordToolResult("tc-UNKNOWN", "bash", "Command exited with code 0\n", false);
77
+
78
+ const entries = getEvidence() as readonly BashEvidence[];
79
+ assert.equal(entries.length, 1);
80
+ assert.equal(entries[0].toolCallId, "tc-1");
81
+ // tc-1 must be untouched — no result was reported for it.
82
+ assert.equal(entries[0].exitCode, -1);
83
+ assert.equal(entries[0].outputSnippet, "");
84
+ });
85
+
86
+ it("records write/edit entries with their toolCallId", () => {
87
+ recordToolCall("tc-write", "write", { file_path: "/tmp/a.md" });
88
+ recordToolCall("tc-edit", "edit", { file_path: "/tmp/b.md" });
89
+
90
+ const entries = getEvidence();
91
+ assert.equal(entries.length, 2);
92
+ assert.equal(entries[0].kind, "write");
93
+ assert.equal(entries[0].toolCallId, "tc-write");
94
+ assert.equal(entries[1].kind, "edit");
95
+ assert.equal(entries[1].toolCallId, "tc-edit");
96
+ });
97
+ });
98
+
99
+ // ─── 2. register-hooks: MCP auto-prep gated inside auto-worktrees (A-1) ────
100
+
101
+ describe("register-hooks: skip prepareWorkflowMcpForProject inside auto-worktrees (A-1)", () => {
102
+ const src = readFileSync(
103
+ resolve(process.cwd(), "src", "resources", "extensions", "gsd", "bootstrap", "register-hooks.ts"),
104
+ "utf-8",
105
+ );
106
+
107
+ it("session_start hook is gated on isInAutoWorktree", () => {
108
+ const idx = src.indexOf('pi.on("session_start"');
109
+ assert.ok(idx !== -1, "session_start handler must exist");
110
+ const block = src.slice(idx, idx + 2500);
111
+ assert.ok(
112
+ block.includes("isInAutoWorktree"),
113
+ "session_start must consult isInAutoWorktree before preparing MCP",
114
+ );
115
+ assert.ok(
116
+ block.includes("prepareWorkflowMcpForProject"),
117
+ "session_start still prepares MCP for non-worktree paths",
118
+ );
119
+ });
120
+
121
+ it("session_switch hook is gated on isInAutoWorktree", () => {
122
+ const idx = src.indexOf('pi.on("session_switch"');
123
+ assert.ok(idx !== -1, "session_switch handler must exist");
124
+ const block = src.slice(idx, idx + 2500);
125
+ assert.ok(
126
+ block.includes("isInAutoWorktree"),
127
+ "session_switch must consult isInAutoWorktree before preparing MCP",
128
+ );
129
+ });
130
+
131
+ it("tool_call hook forwards event.toolCallId into safetyRecordToolCall (A-3)", () => {
132
+ // Find the call site (skip the import line by looking for the opening paren).
133
+ const idx = src.indexOf("safetyRecordToolCall(");
134
+ assert.ok(idx !== -1, "safetyRecordToolCall call must exist");
135
+ const line = src.slice(idx, src.indexOf("\n", idx));
136
+ assert.ok(
137
+ line.includes("event.toolCallId"),
138
+ "safetyRecordToolCall must receive event.toolCallId as the first argument",
139
+ );
140
+ });
141
+ });
142
+
143
+ // ─── 3. auto-recovery: verify-fail instrumentation ─────────────────────────
144
+
145
+ describe("verifyExpectedArtifact: verify-fail exit-point logging (Phase B diag)", () => {
146
+ const src = readFileSync(
147
+ resolve(process.cwd(), "src", "resources", "extensions", "gsd", "auto-recovery.ts"),
148
+ "utf-8",
149
+ );
150
+
151
+ it("logs a verify-fail warning on the null-absPath exit", () => {
152
+ assert.ok(
153
+ src.includes('verify-fail ${unitType} ${unitId}: resolveExpectedArtifactPath returned null'),
154
+ "null-absPath branch must emit a diagnostic line",
155
+ );
156
+ });
157
+
158
+ it("logs a verify-fail warning on the existsSync-false exit", () => {
159
+ assert.ok(
160
+ src.includes("verify-fail ${unitType} ${unitId}: existsSync false"),
161
+ "existsSync-false branch must emit a diagnostic line",
162
+ );
163
+ });
164
+
165
+ it("logs a verify-fail warning on the plan-slice no-task-entry exit", () => {
166
+ assert.ok(
167
+ src.includes("verify-fail ${unitType} ${unitId}: plan has no task checkbox/heading"),
168
+ "plan-slice no-task branch must emit a diagnostic line",
169
+ );
170
+ });
171
+
172
+ it("plan-slice task-plan-files check fails fast on missing tasks dir (hardening)", () => {
173
+ // The original check silently passed when resolveTasksDir returned null.
174
+ // The new check returns false with a diagnostic, which is correct — if
175
+ // the tool successfully planned tasks, the tasks/ dir must exist.
176
+ const idx = src.indexOf('verify-fail ${unitType} ${unitId}: resolveTasksDir returned null');
177
+ assert.ok(
178
+ idx !== -1,
179
+ "resolveTasksDir-null branch must emit a diagnostic and return false",
180
+ );
181
+ });
182
+ });
183
+
184
+ // ─── 4. workflow-tools (mcp-server): guard + optional projectDir + routing ─
185
+
186
+ describe("mcp-server workflow-tools: projectDir routing (Phase B root cause)", () => {
187
+ const src = readFileSync(
188
+ resolve(process.cwd(), "packages", "mcp-server", "src", "workflow-tools.ts"),
189
+ "utf-8",
190
+ );
191
+
192
+ it("projectDirParam is optional and documents the default", () => {
193
+ const idx = src.indexOf("const projectDirParam");
194
+ assert.ok(idx !== -1, "projectDirParam definition must exist");
195
+ const block = src.slice(idx, idx + 600);
196
+ assert.ok(
197
+ block.includes(".optional()"),
198
+ "projectDirParam must be optional so the agent stops deliberating",
199
+ );
200
+ assert.ok(
201
+ /Omit this field/i.test(block),
202
+ "description must tell the agent to omit the field",
203
+ );
204
+ });
205
+
206
+ it("parseWorkflowArgs defaults projectDir to process.cwd() when omitted", () => {
207
+ const idx = src.indexOf("function parseWorkflowArgs");
208
+ assert.ok(idx !== -1, "parseWorkflowArgs must exist");
209
+ const block = src.slice(idx, idx + 1500);
210
+ assert.ok(
211
+ block.includes("parsed.projectDir ?? process.cwd()"),
212
+ "parseWorkflowArgs must fall back to process.cwd() when projectDir is omitted",
213
+ );
214
+ });
215
+
216
+ it("validateProjectDir accepts external-state worktree paths via .gsd symlink target", () => {
217
+ const idx = src.indexOf("function validateProjectDir");
218
+ assert.ok(idx !== -1, "validateProjectDir must exist");
219
+ const block = src.slice(idx, idx + 2500);
220
+ assert.ok(
221
+ block.includes("resolveExternalStateRoot"),
222
+ "validateProjectDir must consult resolveExternalStateRoot for external-state layouts",
223
+ );
224
+
225
+ const helperIdx = src.indexOf("function resolveExternalStateRoot");
226
+ assert.ok(helperIdx !== -1, "resolveExternalStateRoot helper must exist");
227
+ const helperBlock = src.slice(helperIdx, helperIdx + 600);
228
+ assert.ok(
229
+ helperBlock.includes("realpathSync"),
230
+ "resolveExternalStateRoot must use realpathSync to follow the symlink",
231
+ );
232
+ assert.ok(
233
+ /join\([^)]*\.gsd/.test(helperBlock),
234
+ "resolveExternalStateRoot must resolve <allowedRoot>/.gsd",
235
+ );
236
+ });
237
+
238
+ it("parseWorkflowArgs routes tool writes to the active worktree when one exists", () => {
239
+ // This is the Phase B root-cause fix: when the tool call is scoped to a
240
+ // milestone that has an auto-worktree at <projectRoot>/.gsd/worktrees/<MID>/,
241
+ // tool writes must go to the worktree .gsd rather than the shared project .gsd.
242
+ const parseIdx = src.indexOf("function parseWorkflowArgs");
243
+ const parseBlock = src.slice(parseIdx, parseIdx + 2500);
244
+ assert.ok(
245
+ parseBlock.includes("resolveActiveWorktreeBasePath"),
246
+ "parseWorkflowArgs must consult resolveActiveWorktreeBasePath",
247
+ );
248
+ assert.ok(
249
+ parseBlock.includes("extractMilestoneId"),
250
+ "parseWorkflowArgs must extract the milestoneId to locate the worktree",
251
+ );
252
+ });
253
+
254
+ it("resolveActiveWorktreeBasePath checks .git presence to avoid hijacking stray directories", () => {
255
+ const idx = src.indexOf("function resolveActiveWorktreeBasePath");
256
+ assert.ok(idx !== -1, "resolveActiveWorktreeBasePath helper must exist");
257
+ const block = src.slice(idx, idx + 1200);
258
+ assert.ok(
259
+ block.includes('existsSync(join(wtPath, ".git"))'),
260
+ "resolveActiveWorktreeBasePath must verify a .git file exists in the worktree",
261
+ );
262
+ });
263
+
264
+ it("extractMilestoneId handles camelCase, snake_case, and short aliases", () => {
265
+ const idx = src.indexOf("function extractMilestoneId");
266
+ assert.ok(idx !== -1, "extractMilestoneId helper must exist");
267
+ const block = src.slice(idx, idx + 600);
268
+ assert.ok(block.includes("milestoneId"), "must check milestoneId");
269
+ assert.ok(block.includes("milestone_id"), "must check milestone_id");
270
+ assert.ok(block.includes("mid"), "must check mid");
271
+ });
272
+ });
@@ -0,0 +1,117 @@
1
+ // GSD Extension — Regression tests for auto-mode warning noise (PR #4294)
2
+ //
3
+ // Three independent bug fixes, three regression tests:
4
+ //
5
+ // 1. auto-model-selection.ts — buildFlatRateContext detached
6
+ // getProviderAuthMode from its receiver, losing `this` and throwing
7
+ // "Cannot read properties of undefined (reading 'registeredProviders')".
8
+ // Runtime test: pass a registry whose method actually uses `this` and
9
+ // verify the returned authMode survives (proves the method is called
10
+ // with correct binding).
11
+ //
12
+ // 2. auto-worktree.ts — isSamePath logged every error as a warning,
13
+ // including ENOENT when a worktree's .gsd dir hadn't been created yet.
14
+ // Source-check test: the catch block must short-circuit on ENOENT
15
+ // before hitting logWarning. Follows the same style as
16
+ // copy-planning-artifacts-samepath.test.ts.
17
+ //
18
+ // 3. guided-flow.ts — checkAutoStartAfterDiscuss unconditionally tried
19
+ // to unlink DISCUSSION-MANIFEST.json and warned on ENOENT even when
20
+ // the milestone never had a discussion phase. Source-check test:
21
+ // the unlink must be guarded with existsSync, matching the
22
+ // CONTEXT-DRAFT.md cleanup pattern two lines above.
23
+
24
+ import test from "node:test";
25
+ import assert from "node:assert/strict";
26
+ import { readFileSync } from "node:fs";
27
+ import { join } from "node:path";
28
+
29
+ import { buildFlatRateContext } from "../auto-model-selection.ts";
30
+
31
+ // ─── Bug 2: this-binding regression ─────────────────────────────────────
32
+
33
+ test("buildFlatRateContext invokes getProviderAuthMode with correct `this`", () => {
34
+ // Mimics ModelRegistry: getProviderAuthMode reads from an instance field.
35
+ // Detaching the method to a local variable would break this — the old code
36
+ // did `const fn = ctx.modelRegistry.getProviderAuthMode; fn(provider)`,
37
+ // which called the method with `this === undefined` and threw.
38
+ const providerData = new Map<string, string>([
39
+ ["claude-code", "externalCli"],
40
+ ["anthropic", "apiKey"],
41
+ ]);
42
+ const registry = {
43
+ _providers: providerData,
44
+ getProviderAuthMode(provider: string): string {
45
+ // Access via `this` — fails loudly if the method was called unbound.
46
+ const map = this._providers;
47
+ return map.get(provider) ?? "apiKey";
48
+ },
49
+ };
50
+
51
+ const ctx = buildFlatRateContext("claude-code", { modelRegistry: registry });
52
+ assert.equal(
53
+ ctx.authMode,
54
+ "externalCli",
55
+ "authMode should be extracted when getProviderAuthMode is called as a method",
56
+ );
57
+
58
+ const ctx2 = buildFlatRateContext("anthropic", { modelRegistry: registry });
59
+ assert.equal(ctx2.authMode, "apiKey");
60
+ });
61
+
62
+ // ─── Bug 1: isSamePath source check ─────────────────────────────────────
63
+
64
+ test("isSamePath short-circuits ENOENT before logging a warning", () => {
65
+ const srcPath = join(import.meta.dirname, "..", "auto-worktree.ts");
66
+ const src = readFileSync(srcPath, "utf-8");
67
+
68
+ const fnIdx = src.indexOf("function isSamePath");
69
+ assert.ok(fnIdx !== -1, "isSamePath function exists");
70
+
71
+ // Grab the function body (enough to cover the catch block).
72
+ const fnBody = src.slice(fnIdx, fnIdx + 600);
73
+
74
+ const catchIdx = fnBody.indexOf("catch");
75
+ assert.ok(catchIdx !== -1, "isSamePath has a catch block");
76
+
77
+ const enoentIdx = fnBody.indexOf("ENOENT", catchIdx);
78
+ const warnIdx = fnBody.indexOf("logWarning", catchIdx);
79
+
80
+ assert.ok(enoentIdx !== -1, "catch block must handle ENOENT explicitly");
81
+ assert.ok(warnIdx !== -1, "catch block still warns on non-ENOENT errors");
82
+ assert.ok(
83
+ enoentIdx < warnIdx,
84
+ "ENOENT early-return must precede the logWarning call",
85
+ );
86
+ });
87
+
88
+ // ─── Bug 3: guided-flow manifest unlink source check ────────────────────
89
+
90
+ test("checkAutoStartAfterDiscuss guards DISCUSSION-MANIFEST.json unlink with existsSync", () => {
91
+ const srcPath = join(import.meta.dirname, "..", "guided-flow.ts");
92
+ const src = readFileSync(srcPath, "utf-8");
93
+
94
+ const fnIdx = src.indexOf("function checkAutoStartAfterDiscuss");
95
+ assert.ok(fnIdx !== -1, "checkAutoStartAfterDiscuss function exists");
96
+
97
+ // Locate the manifest cleanup comment and its surrounding block.
98
+ const cleanupIdx = src.indexOf(
99
+ "remove discussion manifest after auto-start",
100
+ fnIdx,
101
+ );
102
+ assert.ok(cleanupIdx !== -1, "manifest cleanup block still exists");
103
+
104
+ // Everything from the comment to a short distance below should contain
105
+ // the existsSync guard before the unlinkSync call.
106
+ const block = src.slice(cleanupIdx, cleanupIdx + 400);
107
+
108
+ const existsIdx = block.indexOf("existsSync(manifestPath)");
109
+ const unlinkIdx = block.indexOf("unlinkSync(manifestPath)");
110
+
111
+ assert.ok(existsIdx !== -1, "manifest unlink must be guarded by existsSync");
112
+ assert.ok(unlinkIdx !== -1, "manifest unlink still happens when file exists");
113
+ assert.ok(
114
+ existsIdx < unlinkIdx,
115
+ "existsSync guard must precede the unlinkSync call",
116
+ );
117
+ });