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

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 (403) 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 +113 -3
  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 +51 -5
  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.js +28 -2
  12. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +10 -1
  13. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +61 -9
  14. package/dist/resources/extensions/gsd/cache.js +16 -5
  15. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  16. package/dist/resources/extensions/gsd/commands-extract-learnings.js +225 -0
  17. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  18. package/dist/resources/extensions/gsd/docs/preferences-reference.md +14 -1
  19. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +144 -0
  20. package/dist/resources/extensions/gsd/ecosystem/loader.js +145 -0
  21. package/dist/resources/extensions/gsd/git-service.js +49 -1
  22. package/dist/resources/extensions/gsd/graph-context.js +98 -7
  23. package/dist/resources/extensions/gsd/gsd-db.js +260 -2
  24. package/dist/resources/extensions/gsd/guided-flow.js +24 -1
  25. package/dist/resources/extensions/gsd/init-wizard.js +1 -0
  26. package/dist/resources/extensions/gsd/journal.js +27 -0
  27. package/dist/resources/extensions/gsd/metrics.js +19 -0
  28. package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
  29. package/dist/resources/extensions/gsd/preferences-models.js +20 -3
  30. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  31. package/dist/resources/extensions/gsd/preferences-validation.js +108 -2
  32. package/dist/resources/extensions/gsd/preferences.js +26 -0
  33. package/dist/resources/extensions/gsd/safety/evidence-collector.js +15 -30
  34. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
  35. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  36. package/dist/resources/extensions/gsd/tools/complete-slice.js +5 -0
  37. package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
  38. package/dist/resources/extensions/gsd/unit-ownership.js +1 -1
  39. package/dist/resources/extensions/gsd/uok/audit-toggle.js +7 -0
  40. package/dist/resources/extensions/gsd/uok/audit.js +40 -0
  41. package/dist/resources/extensions/gsd/uok/contracts.js +1 -0
  42. package/dist/resources/extensions/gsd/uok/execution-graph.js +179 -0
  43. package/dist/resources/extensions/gsd/uok/flags.js +29 -0
  44. package/dist/resources/extensions/gsd/uok/gate-runner.js +109 -0
  45. package/dist/resources/extensions/gsd/uok/gitops.js +53 -0
  46. package/dist/resources/extensions/gsd/uok/kernel.js +80 -0
  47. package/dist/resources/extensions/gsd/uok/loop-adapter.js +133 -0
  48. package/dist/resources/extensions/gsd/uok/model-policy.js +66 -0
  49. package/dist/resources/extensions/gsd/uok/plan-v2.js +132 -0
  50. package/dist/resources/extensions/gsd/workflow-logger.js +22 -0
  51. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  52. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  53. package/dist/web/standalone/.next/BUILD_ID +1 -1
  54. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  55. package/dist/web/standalone/.next/build-manifest.json +2 -2
  56. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  57. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  58. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/index.html +1 -1
  79. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  86. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  87. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  89. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  90. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  91. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  92. package/package.json +1 -1
  93. package/packages/mcp-server/dist/readers/graph.d.ts +1 -1
  94. package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -1
  95. package/packages/mcp-server/dist/readers/graph.js +107 -0
  96. package/packages/mcp-server/dist/readers/graph.js.map +1 -1
  97. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  98. package/packages/mcp-server/dist/workflow-tools.js +88 -6
  99. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  100. package/packages/mcp-server/src/readers/graph.test.ts +178 -0
  101. package/packages/mcp-server/src/readers/graph.ts +148 -1
  102. package/packages/mcp-server/src/workflow-tools.ts +95 -10
  103. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  104. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  105. package/packages/pi-ai/dist/index.d.ts +1 -9
  106. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  107. package/packages/pi-ai/dist/index.js +1 -9
  108. package/packages/pi-ai/dist/index.js.map +1 -1
  109. package/packages/pi-ai/dist/models/capability-patches.d.ts +19 -0
  110. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -0
  111. package/packages/pi-ai/dist/models/capability-patches.js +36 -0
  112. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -0
  113. package/packages/pi-ai/dist/{models.custom.d.ts → models/custom.d.ts} +1 -1
  114. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -0
  115. package/packages/pi-ai/dist/{models.custom.js → models/custom.js} +4 -4
  116. package/packages/pi-ai/dist/models/custom.js.map +1 -0
  117. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +1482 -0
  118. package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -0
  119. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +1484 -0
  120. package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -0
  121. package/packages/pi-ai/dist/models/generated/anthropic.d.ts +377 -0
  122. package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -0
  123. package/packages/pi-ai/dist/models/generated/anthropic.js +379 -0
  124. package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -0
  125. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts +700 -0
  126. package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts.map +1 -0
  127. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js +702 -0
  128. package/packages/pi-ai/dist/models/generated/azure-openai-responses.js.map +1 -0
  129. package/packages/pi-ai/dist/models/generated/cerebras.d.ts +71 -0
  130. package/packages/pi-ai/dist/models/generated/cerebras.d.ts.map +1 -0
  131. package/packages/pi-ai/dist/models/generated/cerebras.js +73 -0
  132. package/packages/pi-ai/dist/models/generated/cerebras.js.map +1 -0
  133. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts +590 -0
  134. package/packages/pi-ai/dist/models/generated/github-copilot.d.ts.map +1 -0
  135. package/packages/pi-ai/dist/models/generated/github-copilot.js +444 -0
  136. package/packages/pi-ai/dist/models/generated/github-copilot.js.map +1 -0
  137. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +156 -0
  138. package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -0
  139. package/packages/pi-ai/dist/models/generated/google-antigravity.js +158 -0
  140. package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -0
  141. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts +105 -0
  142. package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts.map +1 -0
  143. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js +107 -0
  144. package/packages/pi-ai/dist/models/generated/google-gemini-cli.js.map +1 -0
  145. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts +207 -0
  146. package/packages/pi-ai/dist/models/generated/google-vertex.d.ts.map +1 -0
  147. package/packages/pi-ai/dist/models/generated/google-vertex.js +209 -0
  148. package/packages/pi-ai/dist/models/generated/google-vertex.js.map +1 -0
  149. package/packages/pi-ai/dist/models/generated/google.d.ts +462 -0
  150. package/packages/pi-ai/dist/models/generated/google.d.ts.map +1 -0
  151. package/packages/pi-ai/dist/models/generated/google.js +464 -0
  152. package/packages/pi-ai/dist/models/generated/google.js.map +1 -0
  153. package/packages/pi-ai/dist/models/generated/groq.d.ts +309 -0
  154. package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -0
  155. package/packages/pi-ai/dist/models/generated/groq.js +311 -0
  156. package/packages/pi-ai/dist/models/generated/groq.js.map +1 -0
  157. package/packages/pi-ai/dist/models/generated/huggingface.d.ts +383 -0
  158. package/packages/pi-ai/dist/models/generated/huggingface.d.ts.map +1 -0
  159. package/packages/pi-ai/dist/models/generated/huggingface.js +347 -0
  160. package/packages/pi-ai/dist/models/generated/huggingface.js.map +1 -0
  161. package/packages/pi-ai/dist/{models.generated.d.ts → models/generated/index.d.ts} +1 -1
  162. package/packages/pi-ai/dist/{models.generated.d.ts.map → models/generated/index.d.ts.map} +1 -1
  163. package/packages/pi-ai/dist/models/generated/index.js +51 -0
  164. package/packages/pi-ai/dist/models/generated/index.js.map +1 -0
  165. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts +37 -0
  166. package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts.map +1 -0
  167. package/packages/pi-ai/dist/models/generated/kimi-coding.js +39 -0
  168. package/packages/pi-ai/dist/models/generated/kimi-coding.js.map +1 -0
  169. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts +105 -0
  170. package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts.map +1 -0
  171. package/packages/pi-ai/dist/models/generated/minimax-cn.js +107 -0
  172. package/packages/pi-ai/dist/models/generated/minimax-cn.js.map +1 -0
  173. package/packages/pi-ai/dist/models/generated/minimax.d.ts +105 -0
  174. package/packages/pi-ai/dist/models/generated/minimax.d.ts.map +1 -0
  175. package/packages/pi-ai/dist/models/generated/minimax.js +107 -0
  176. package/packages/pi-ai/dist/models/generated/minimax.js.map +1 -0
  177. package/packages/pi-ai/dist/models/generated/mistral.d.ts +445 -0
  178. package/packages/pi-ai/dist/models/generated/mistral.d.ts.map +1 -0
  179. package/packages/pi-ai/dist/models/generated/mistral.js +447 -0
  180. package/packages/pi-ai/dist/models/generated/mistral.js.map +1 -0
  181. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +139 -0
  182. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -0
  183. package/packages/pi-ai/dist/models/generated/openai-codex.js +141 -0
  184. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -0
  185. package/packages/pi-ai/dist/models/generated/openai.d.ts +700 -0
  186. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -0
  187. package/packages/pi-ai/dist/models/generated/openai.js +702 -0
  188. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -0
  189. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts +122 -0
  190. package/packages/pi-ai/dist/models/generated/opencode-go.d.ts.map +1 -0
  191. package/packages/pi-ai/dist/models/generated/opencode-go.js +124 -0
  192. package/packages/pi-ai/dist/models/generated/opencode-go.js.map +1 -0
  193. package/packages/pi-ai/dist/models/generated/opencode.d.ts +530 -0
  194. package/packages/pi-ai/dist/models/generated/opencode.d.ts.map +1 -0
  195. package/packages/pi-ai/dist/models/generated/opencode.js +532 -0
  196. package/packages/pi-ai/dist/models/generated/opencode.js.map +1 -0
  197. package/packages/pi-ai/dist/models/generated/openrouter.d.ts +4270 -0
  198. package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -0
  199. package/packages/pi-ai/dist/models/generated/openrouter.js +4272 -0
  200. package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -0
  201. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts +2604 -0
  202. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts.map +1 -0
  203. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js +2606 -0
  204. package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js.map +1 -0
  205. package/packages/pi-ai/dist/models/generated/xai.d.ts +411 -0
  206. package/packages/pi-ai/dist/models/generated/xai.d.ts.map +1 -0
  207. package/packages/pi-ai/dist/models/generated/xai.js +413 -0
  208. package/packages/pi-ai/dist/models/generated/xai.js.map +1 -0
  209. package/packages/pi-ai/dist/models/generated/zai.d.ts +276 -0
  210. package/packages/pi-ai/dist/models/generated/zai.d.ts.map +1 -0
  211. package/packages/pi-ai/dist/models/generated/zai.js +239 -0
  212. package/packages/pi-ai/dist/models/generated/zai.js.map +1 -0
  213. package/packages/pi-ai/dist/models/index.d.ts +27 -0
  214. package/packages/pi-ai/dist/models/index.d.ts.map +1 -0
  215. package/packages/pi-ai/dist/models/index.js +80 -0
  216. package/packages/pi-ai/dist/models/index.js.map +1 -0
  217. package/packages/pi-ai/dist/models.d.ts +1 -36
  218. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  219. package/packages/pi-ai/dist/models.generated.test.js +1 -2
  220. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  221. package/packages/pi-ai/dist/models.js +3 -112
  222. package/packages/pi-ai/dist/models.js.map +1 -1
  223. package/packages/pi-ai/dist/models.test.js +6 -5
  224. package/packages/pi-ai/dist/models.test.js.map +1 -1
  225. package/packages/pi-ai/scripts/generate-models.ts +74 -40
  226. package/packages/pi-ai/src/index.ts +1 -9
  227. package/packages/pi-ai/src/models/capability-patches.ts +40 -0
  228. package/packages/pi-ai/src/{models.custom.ts → models/custom.ts} +4 -4
  229. package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1486 -0
  230. package/packages/pi-ai/src/models/generated/anthropic.ts +381 -0
  231. package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
  232. package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
  233. package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
  234. package/packages/pi-ai/src/models/generated/google-antigravity.ts +160 -0
  235. package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
  236. package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
  237. package/packages/pi-ai/src/models/generated/google.ts +466 -0
  238. package/packages/pi-ai/src/models/generated/groq.ts +313 -0
  239. package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
  240. package/packages/pi-ai/src/models/generated/index.ts +52 -0
  241. package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
  242. package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
  243. package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
  244. package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
  245. package/packages/pi-ai/src/models/generated/openai-codex.ts +143 -0
  246. package/packages/pi-ai/src/models/generated/openai.ts +704 -0
  247. package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
  248. package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
  249. package/packages/pi-ai/src/models/generated/openrouter.ts +4274 -0
  250. package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
  251. package/packages/pi-ai/src/models/generated/xai.ts +415 -0
  252. package/packages/pi-ai/src/models/generated/zai.ts +241 -0
  253. package/packages/pi-ai/src/models/index.ts +106 -0
  254. package/packages/pi-ai/src/models.generated.test.ts +1 -2
  255. package/packages/pi-ai/src/models.test.ts +6 -5
  256. package/packages/pi-ai/src/models.ts +3 -153
  257. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  258. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  259. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -2
  260. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  261. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +472 -0
  262. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts +2 -0
  264. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts.map +1 -0
  265. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js +52 -0
  266. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js.map +1 -0
  267. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  269. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +11 -0
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +1 -0
  273. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  274. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +23 -9
  275. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +11 -0
  277. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -0
  278. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +47 -0
  279. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -0
  280. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  281. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  282. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +68 -8
  283. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +22 -22
  286. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  288. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +232 -18
  289. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  290. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts +2 -0
  291. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts.map +1 -0
  292. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +38 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +14 -0
  295. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +70 -6
  297. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  298. package/packages/pi-coding-agent/src/core/agent-session.ts +12 -6
  299. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +612 -0
  300. package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
  301. package/packages/pi-coding-agent/src/core/model-registry.ts +2 -1
  302. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +19 -0
  303. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +25 -10
  304. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +67 -0
  305. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +83 -7
  306. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +23 -26
  307. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +298 -41
  308. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +44 -0
  309. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +92 -6
  310. package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
  311. package/packages/pi-coding-agent/tsconfig.json +2 -2
  312. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  313. package/src/resources/extensions/gsd/activity-log.ts +21 -0
  314. package/src/resources/extensions/gsd/auto/loop-deps.ts +4 -0
  315. package/src/resources/extensions/gsd/auto/loop.ts +159 -10
  316. package/src/resources/extensions/gsd/auto/phases.ts +123 -3
  317. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  318. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -6
  319. package/src/resources/extensions/gsd/auto-model-selection.ts +66 -5
  320. package/src/resources/extensions/gsd/auto-post-unit.ts +226 -9
  321. package/src/resources/extensions/gsd/auto-recovery.ts +29 -9
  322. package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
  323. package/src/resources/extensions/gsd/auto-verification.ts +129 -2
  324. package/src/resources/extensions/gsd/auto.ts +34 -2
  325. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -1
  326. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +72 -8
  327. package/src/resources/extensions/gsd/cache.ts +16 -5
  328. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  329. package/src/resources/extensions/gsd/commands-extract-learnings.ts +304 -0
  330. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  331. package/src/resources/extensions/gsd/docs/preferences-reference.md +14 -1
  332. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +228 -0
  333. package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
  334. package/src/resources/extensions/gsd/git-service.ts +68 -0
  335. package/src/resources/extensions/gsd/graph-context.ts +139 -12
  336. package/src/resources/extensions/gsd/gsd-db.ts +321 -3
  337. package/src/resources/extensions/gsd/guided-flow.ts +33 -1
  338. package/src/resources/extensions/gsd/init-wizard.ts +3 -2
  339. package/src/resources/extensions/gsd/journal.ts +30 -0
  340. package/src/resources/extensions/gsd/metrics.ts +26 -0
  341. package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
  342. package/src/resources/extensions/gsd/preferences-models.ts +20 -3
  343. package/src/resources/extensions/gsd/preferences-types.ts +32 -0
  344. package/src/resources/extensions/gsd/preferences-validation.ts +107 -2
  345. package/src/resources/extensions/gsd/preferences.ts +28 -0
  346. package/src/resources/extensions/gsd/safety/evidence-collector.ts +15 -31
  347. package/src/resources/extensions/gsd/session-lock.ts +14 -2
  348. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +20 -1
  349. package/src/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  350. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +177 -0
  351. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +7 -3
  352. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
  353. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
  354. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +272 -0
  355. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
  356. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +340 -0
  357. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  358. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  359. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
  360. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  361. package/src/resources/extensions/gsd/tests/health-widget.test.ts +1 -1
  362. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -2
  363. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -3
  364. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  365. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +2 -1
  366. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +40 -1
  367. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
  368. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -5
  369. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
  370. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +85 -0
  371. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +69 -0
  372. package/src/resources/extensions/gsd/tests/uok-flags.test.ts +39 -0
  373. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +70 -0
  374. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +85 -0
  375. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +35 -0
  376. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
  377. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +167 -0
  378. package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
  379. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
  380. package/src/resources/extensions/gsd/tools/complete-slice.ts +9 -2
  381. package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
  382. package/src/resources/extensions/gsd/types.ts +14 -1
  383. package/src/resources/extensions/gsd/unit-ownership.ts +2 -2
  384. package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
  385. package/src/resources/extensions/gsd/uok/audit.ts +51 -0
  386. package/src/resources/extensions/gsd/uok/contracts.ts +135 -0
  387. package/src/resources/extensions/gsd/uok/execution-graph.ts +241 -0
  388. package/src/resources/extensions/gsd/uok/flags.ts +45 -0
  389. package/src/resources/extensions/gsd/uok/gate-runner.ts +146 -0
  390. package/src/resources/extensions/gsd/uok/gitops.ts +75 -0
  391. package/src/resources/extensions/gsd/uok/kernel.ts +105 -0
  392. package/src/resources/extensions/gsd/uok/loop-adapter.ts +162 -0
  393. package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
  394. package/src/resources/extensions/gsd/uok/plan-v2.ts +156 -0
  395. package/src/resources/extensions/gsd/workflow-logger.ts +27 -1
  396. package/src/resources/extensions/ttsr/ttsr-manager.ts +10 -5
  397. package/packages/pi-ai/dist/models.custom.d.ts.map +0 -1
  398. package/packages/pi-ai/dist/models.custom.js.map +0 -1
  399. package/packages/pi-ai/dist/models.generated.js +0 -14343
  400. package/packages/pi-ai/dist/models.generated.js.map +0 -1
  401. package/packages/pi-ai/src/models.generated.ts +0 -14345
  402. /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_buildManifest.js +0 -0
  403. /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_ssgManifest.js +0 -0
@@ -0,0 +1,70 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import { closeDatabase, openDatabase, _getAdapter } from "../gsd-db.ts";
5
+ import { UokGateRunner } from "../uok/gate-runner.ts";
6
+
7
+ test.beforeEach(() => {
8
+ closeDatabase();
9
+ const ok = openDatabase(":memory:");
10
+ assert.equal(ok, true);
11
+ });
12
+
13
+ test.afterEach(() => {
14
+ closeDatabase();
15
+ });
16
+
17
+ test("uok gate runner retries timeout failures using deterministic matrix", async () => {
18
+ const runner = new UokGateRunner();
19
+
20
+ let calls = 0;
21
+ runner.register({
22
+ id: "timeout-gate",
23
+ type: "verification",
24
+ execute: async (_ctx, attempt) => {
25
+ calls += 1;
26
+ if (attempt < 2) {
27
+ return {
28
+ outcome: "fail",
29
+ failureClass: "timeout",
30
+ rationale: "first attempt timed out",
31
+ };
32
+ }
33
+ return {
34
+ outcome: "pass",
35
+ failureClass: "none",
36
+ rationale: "second attempt passed",
37
+ };
38
+ },
39
+ });
40
+
41
+ const result = await runner.run("timeout-gate", {
42
+ basePath: process.cwd(),
43
+ traceId: "trace-a",
44
+ turnId: "turn-a",
45
+ milestoneId: "M001",
46
+ sliceId: "S01",
47
+ taskId: "T01",
48
+ });
49
+
50
+ assert.equal(result.outcome, "pass");
51
+ assert.equal(calls, 2);
52
+
53
+ const adapter = _getAdapter();
54
+ const rows = adapter?.prepare("SELECT gate_id, outcome, attempt FROM gate_runs ORDER BY id").all() ?? [];
55
+ assert.equal(rows.length, 2);
56
+ assert.equal(rows[0]?.["outcome"], "retry");
57
+ assert.equal(rows[1]?.["outcome"], "pass");
58
+ });
59
+
60
+ test("uok gate runner returns manual-attention for unknown gate id", async () => {
61
+ const runner = new UokGateRunner();
62
+ const result = await runner.run("missing-gate", {
63
+ basePath: process.cwd(),
64
+ traceId: "trace-b",
65
+ turnId: "turn-b",
66
+ });
67
+
68
+ assert.equal(result.outcome, "manual-attention");
69
+ assert.equal(result.failureClass, "unknown");
70
+ });
@@ -0,0 +1,85 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { execSync } from "node:child_process";
7
+ import { runTurnGitAction } from "../git-service.ts";
8
+
9
+ function run(cmd: string, cwd: string): string {
10
+ return execSync(cmd, { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
11
+ }
12
+
13
+ function makeRepo(): string {
14
+ const repo = mkdtempSync(join(tmpdir(), "gsd-uok-gitops-"));
15
+ run("git init", repo);
16
+ run('git config user.email "test@example.com"', repo);
17
+ run('git config user.name "Test User"', repo);
18
+ writeFileSync(join(repo, "README.md"), "# Test\n", "utf-8");
19
+ run("git add README.md", repo);
20
+ run('git commit -m "chore: init"', repo);
21
+ return repo;
22
+ }
23
+
24
+ test("uok gitops turn action status-only reports working tree dirtiness", () => {
25
+ const repo = makeRepo();
26
+ try {
27
+ const clean = runTurnGitAction({
28
+ basePath: repo,
29
+ action: "status-only",
30
+ unitType: "execute-task",
31
+ unitId: "M001/S01/T01",
32
+ });
33
+ assert.equal(clean.status, "ok");
34
+ assert.equal(clean.dirty, false);
35
+
36
+ writeFileSync(join(repo, "README.md"), "# Dirty\n", "utf-8");
37
+ const dirty = runTurnGitAction({
38
+ basePath: repo,
39
+ action: "status-only",
40
+ unitType: "execute-task",
41
+ unitId: "M001/S01/T01",
42
+ });
43
+ assert.equal(dirty.status, "ok");
44
+ assert.equal(dirty.dirty, true);
45
+ } finally {
46
+ rmSync(repo, { recursive: true, force: true });
47
+ }
48
+ });
49
+
50
+ test("uok gitops turn action snapshot writes snapshot refs", () => {
51
+ const repo = makeRepo();
52
+ try {
53
+ const result = runTurnGitAction({
54
+ basePath: repo,
55
+ action: "snapshot",
56
+ unitType: "execute-task",
57
+ unitId: "M001/S01/T01",
58
+ });
59
+ assert.equal(result.status, "ok");
60
+ assert.ok(result.snapshotLabel?.includes("execute-task/M001/S01/T01"));
61
+ const refs = run("git for-each-ref refs/gsd/snapshots/ --format='%(refname)'", repo);
62
+ assert.ok(refs.includes("refs/gsd/snapshots/execute-task/M001/S01/T01/"));
63
+ } finally {
64
+ rmSync(repo, { recursive: true, force: true });
65
+ }
66
+ });
67
+
68
+ test("uok gitops turn action commit creates commit with unit trailer", () => {
69
+ const repo = makeRepo();
70
+ try {
71
+ writeFileSync(join(repo, "feature.ts"), "export const x = 1;\n", "utf-8");
72
+ const result = runTurnGitAction({
73
+ basePath: repo,
74
+ action: "commit",
75
+ unitType: "execute-task",
76
+ unitId: "M001/S01/T02",
77
+ });
78
+ assert.equal(result.status, "ok");
79
+ assert.ok(result.commitMessage?.includes("chore: auto-commit after execute-task"));
80
+ const body = run("git log -1 --pretty=%B", repo);
81
+ assert.ok(body.includes("GSD-Unit: M001/S01/T02"));
82
+ } finally {
83
+ rmSync(repo, { recursive: true, force: true });
84
+ }
85
+ });
@@ -0,0 +1,35 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { readFileSync } from "node:fs";
4
+ import { join, dirname } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const gsdDir = join(__dirname, "..");
9
+
10
+ test("post-unit pre-verification selects turn git action from UOK gitops flags", () => {
11
+ const source = readFileSync(join(gsdDir, "auto-post-unit.ts"), "utf-8");
12
+ assert.ok(
13
+ source.includes("const turnAction: TurnGitActionMode = uokFlags.gitops ? uokFlags.gitopsTurnAction : \"commit\""),
14
+ "postUnitPreVerification should derive turn action from uok.gitops.turn_action when enabled",
15
+ );
16
+ });
17
+
18
+ test("post-unit pre-verification routes git failures through closeout gate", () => {
19
+ const source = readFileSync(join(gsdDir, "auto-post-unit.ts"), "utf-8");
20
+ assert.ok(
21
+ source.includes('id: "closeout-git-action"') &&
22
+ source.includes('type: "closeout"') &&
23
+ source.includes('failureClass: "git"'),
24
+ "git failures should be persisted via a closeout gate with failureClass=git",
25
+ );
26
+ });
27
+
28
+ test("auto snapshot opts carry trace/turn IDs for turn closeout records", () => {
29
+ const source = readFileSync(join(gsdDir, "auto.ts"), "utf-8");
30
+ assert.ok(
31
+ source.includes("traceId: s.currentTraceId ?? undefined") &&
32
+ source.includes("turnId: s.currentTurnId ?? undefined"),
33
+ "buildSnapshotOpts should pass trace/turn IDs into closeout options",
34
+ );
35
+ });
@@ -0,0 +1,89 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, mkdirSync, readFileSync, rmSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+
7
+ import {
8
+ applyModelPolicyFilter,
9
+ buildRequirementVector,
10
+ } from "../uok/model-policy.ts";
11
+ import {
12
+ registerToolCompatibility,
13
+ resetToolCompatibilityRegistry,
14
+ } from "@gsd/pi-coding-agent";
15
+
16
+ test.afterEach(() => {
17
+ resetToolCompatibilityRegistry();
18
+ });
19
+
20
+ test("uok model policy builds requirement vectors from unit metadata", () => {
21
+ const requirements = buildRequirementVector("execute-task", {
22
+ tags: ["docs"],
23
+ fileCount: 8,
24
+ estimatedLines: 600,
25
+ });
26
+
27
+ assert.equal(requirements.instruction, 0.9);
28
+ assert.equal(requirements.coding, 0.3);
29
+ assert.equal(requirements.speed, 0.7);
30
+ });
31
+
32
+ test("uok model policy enforces provider/api/tool constraints and emits decision audit events", () => {
33
+ const basePath = mkdtempSync(join(tmpdir(), "gsd-uok-model-policy-"));
34
+ try {
35
+ mkdirSync(join(basePath, ".gsd"), { recursive: true });
36
+ registerToolCompatibility("screenshot", { producesImages: true });
37
+
38
+ const result = applyModelPolicyFilter(
39
+ [
40
+ { id: "openai-image", provider: "openai", api: "openai-responses" },
41
+ { id: "anthropic-ok", provider: "anthropic", api: "anthropic-messages" },
42
+ { id: "gemini-api-deny", provider: "google", api: "google-generative-ai" },
43
+ { id: "blocked-provider", provider: "blocked", api: "anthropic-messages" },
44
+ ],
45
+ {
46
+ basePath,
47
+ traceId: "trace-model-policy-1",
48
+ turnId: "turn-model-policy-1",
49
+ unitType: "execute-task",
50
+ taskMetadata: { tags: ["docs"] },
51
+ allowCrossProvider: true,
52
+ requiredTools: ["screenshot"],
53
+ allowedApis: ["anthropic-messages", "openai-responses"],
54
+ deniedProviders: ["blocked"],
55
+ },
56
+ );
57
+
58
+ assert.deepEqual(
59
+ result.eligible.map((m) => m.id),
60
+ ["anthropic-ok"],
61
+ "only the policy-compliant anthropic model should remain eligible",
62
+ );
63
+ assert.equal(result.decisions.length, 4);
64
+ assert.equal(result.decisions[0]?.allowed, false);
65
+ assert.match(result.decisions[0]?.reason ?? "", /tool policy denied/);
66
+ assert.equal(result.decisions[1]?.allowed, true);
67
+ assert.equal(result.decisions[2]?.allowed, false);
68
+ assert.match(result.decisions[2]?.reason ?? "", /transport\/api denied by policy/);
69
+ assert.equal(result.decisions[3]?.allowed, false);
70
+ assert.match(result.decisions[3]?.reason ?? "", /provider denied by policy/);
71
+
72
+ const auditLogPath = join(basePath, ".gsd", "audit", "events.jsonl");
73
+ const auditLines = readFileSync(auditLogPath, "utf-8")
74
+ .trim()
75
+ .split("\n")
76
+ .map((line) => JSON.parse(line) as { type: string; payload?: { reason?: string } });
77
+ const decisionTypes = auditLines.map((event) => event.type);
78
+
79
+ assert.equal(auditLines.length, 4);
80
+ assert.ok(decisionTypes.includes("model-policy-allow"));
81
+ assert.ok(decisionTypes.includes("model-policy-deny"));
82
+ assert.ok(
83
+ auditLines.some((event) => (event.payload?.reason ?? "").includes("tool policy denied")),
84
+ "audit stream should include explicit deny reasons",
85
+ );
86
+ } finally {
87
+ rmSync(basePath, { recursive: true, force: true });
88
+ }
89
+ });
@@ -0,0 +1,167 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
+ import { join, dirname } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ import {
9
+ closeDatabase,
10
+ insertMilestone,
11
+ insertSlice,
12
+ insertTask,
13
+ openDatabase,
14
+ } from "../gsd-db.ts";
15
+ import type { GSDState, Phase } from "../types.ts";
16
+ import { ensurePlanV2Graph } from "../uok/plan-v2.ts";
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ const gsdDir = join(__dirname, "..");
20
+ const MILESTONE_ID = "M001";
21
+ const SLICE_ID = "S01";
22
+ const TASK_ID = "T01";
23
+ const tempDirs = new Set<string>();
24
+
25
+ function createBasePath(): string {
26
+ const basePath = mkdtempSync(join(tmpdir(), "gsd-uok-planv2-"));
27
+ mkdirSync(join(basePath, ".gsd", "milestones", MILESTONE_ID), { recursive: true });
28
+ tempDirs.add(basePath);
29
+ return basePath;
30
+ }
31
+
32
+ function writeMilestoneFile(basePath: string, suffix: string, content: string): void {
33
+ const milestoneDir = join(basePath, ".gsd", "milestones", MILESTONE_ID);
34
+ mkdirSync(milestoneDir, { recursive: true });
35
+ writeFileSync(join(milestoneDir, `${MILESTONE_ID}-${suffix}.md`), `${content}\n`, "utf-8");
36
+ }
37
+
38
+ function writeSliceFile(basePath: string, suffix: string, content: string): void {
39
+ const sliceDir = join(basePath, ".gsd", "milestones", MILESTONE_ID, "slices", SLICE_ID);
40
+ mkdirSync(sliceDir, { recursive: true });
41
+ writeFileSync(join(sliceDir, `${SLICE_ID}-${suffix}.md`), `${content}\n`, "utf-8");
42
+ }
43
+
44
+ function seedGraphRows(): void {
45
+ insertMilestone({ id: MILESTONE_ID, title: "Milestone", status: "active" });
46
+ insertSlice({
47
+ id: SLICE_ID,
48
+ milestoneId: MILESTONE_ID,
49
+ title: "Slice",
50
+ status: "in_progress",
51
+ sequence: 1,
52
+ });
53
+ insertTask({
54
+ id: TASK_ID,
55
+ milestoneId: MILESTONE_ID,
56
+ sliceId: SLICE_ID,
57
+ title: "Task",
58
+ status: "pending",
59
+ keyFiles: ["src/task.ts"],
60
+ sequence: 1,
61
+ });
62
+ }
63
+
64
+ function buildState(phase: Phase): GSDState {
65
+ return {
66
+ phase,
67
+ activeMilestone: { id: MILESTONE_ID, title: "Milestone" },
68
+ activeSlice: null,
69
+ activeTask: null,
70
+ recentDecisions: [],
71
+ blockers: [],
72
+ nextAction: "dispatch",
73
+ registry: [],
74
+ };
75
+ }
76
+
77
+ test.beforeEach(() => {
78
+ closeDatabase();
79
+ const opened = openDatabase(":memory:");
80
+ assert.equal(opened, true);
81
+ });
82
+
83
+ test.afterEach(() => {
84
+ closeDatabase();
85
+ for (const path of tempDirs) {
86
+ rmSync(path, { recursive: true, force: true });
87
+ }
88
+ tempDirs.clear();
89
+ });
90
+
91
+ test("guided flow enforces plan-v2 gate before execution-oriented dispatch", () => {
92
+ const source = readFileSync(join(gsdDir, "guided-flow.ts"), "utf-8");
93
+ assert.ok(
94
+ source.includes("needsPlanV2Gate") &&
95
+ source.includes("ensurePlanV2Graph") &&
96
+ source.includes("Plan gate failed-closed"),
97
+ "guided flow should fail-closed when plan-v2 graph compilation fails",
98
+ );
99
+ });
100
+
101
+ test("plan-v2 gate fails closed for execution phase when finalized context is missing", () => {
102
+ const basePath = createBasePath();
103
+ seedGraphRows();
104
+
105
+ writeMilestoneFile(basePath, "CONTEXT-DRAFT", "Draft context only.");
106
+
107
+ const compiled = ensurePlanV2Graph(basePath, buildState("executing"));
108
+ assert.equal(compiled.ok, false);
109
+ assert.match(compiled.reason ?? "", /CONTEXT\.md/i);
110
+ });
111
+
112
+ test("plan-v2 compiler writes pipeline metadata for clarify/research/draft stages", () => {
113
+ const basePath = createBasePath();
114
+ seedGraphRows();
115
+
116
+ writeMilestoneFile(basePath, "CONTEXT", "Finalized context.");
117
+ writeMilestoneFile(basePath, "CONTEXT-DRAFT", "Draft context retained.");
118
+ writeMilestoneFile(basePath, "RESEARCH", "Milestone research synthesis.");
119
+ writeSliceFile(basePath, "RESEARCH", "Slice research detail.");
120
+
121
+ const compiled = ensurePlanV2Graph(basePath, buildState("executing"));
122
+ assert.equal(compiled.ok, true);
123
+ assert.equal(compiled.clarifyRoundLimit, 3);
124
+ assert.equal(compiled.researchSynthesized, true);
125
+ assert.equal(compiled.draftContextIncluded, true);
126
+ assert.equal(compiled.finalizedContextIncluded, true);
127
+
128
+ const graphPath = compiled.graphPath ?? "";
129
+ const graphRaw = readFileSync(graphPath, "utf-8");
130
+ const graph = JSON.parse(graphRaw) as {
131
+ pipeline?: Record<string, unknown>;
132
+ nodes?: unknown[];
133
+ };
134
+
135
+ assert.equal(graph.pipeline?.["clarifyRoundLimit"], 3);
136
+ assert.equal(graph.pipeline?.["researchSynthesized"], true);
137
+ assert.equal(graph.pipeline?.["draftContextIncluded"], true);
138
+ assert.equal(graph.pipeline?.["finalizedContextIncluded"], true);
139
+ assert.equal(Array.isArray(graph.nodes), true);
140
+ });
141
+
142
+ test("plan-v2 graph may compile during planning even without finalized context", () => {
143
+ const basePath = createBasePath();
144
+ seedGraphRows();
145
+
146
+ writeMilestoneFile(basePath, "CONTEXT-DRAFT", "Planning draft context.");
147
+ const compiled = ensurePlanV2Graph(basePath, buildState("planning"));
148
+ assert.equal(compiled.ok, true);
149
+ });
150
+
151
+ test("plan-v2 ensure rejects empty executable graph", () => {
152
+ const basePath = createBasePath();
153
+ writeMilestoneFile(basePath, "CONTEXT", "Finalized context.");
154
+
155
+ insertMilestone({ id: MILESTONE_ID, title: "Milestone", status: "active" });
156
+ insertSlice({
157
+ id: SLICE_ID,
158
+ milestoneId: MILESTONE_ID,
159
+ title: "Slice",
160
+ status: "pending",
161
+ sequence: 1,
162
+ });
163
+
164
+ const compiled = ensurePlanV2Graph(basePath, buildState("executing"));
165
+ assert.equal(compiled.ok, false);
166
+ assert.match(compiled.reason ?? "", /compiled graph is empty/i);
167
+ });
@@ -0,0 +1,42 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import { validatePreferences } from "../preferences-validation.ts";
5
+
6
+ test("uok preferences validate nested flags and turn_action", () => {
7
+ const input = {
8
+ uok: {
9
+ enabled: true,
10
+ legacy_fallback: { enabled: false },
11
+ gates: { enabled: true },
12
+ model_policy: { enabled: true },
13
+ execution_graph: { enabled: false },
14
+ gitops: {
15
+ enabled: true,
16
+ turn_action: "status-only",
17
+ turn_push: false,
18
+ },
19
+ audit_unified: { enabled: true },
20
+ plan_v2: { enabled: true },
21
+ },
22
+ };
23
+
24
+ const result = validatePreferences(input as never);
25
+ assert.equal(result.errors.length, 0);
26
+ assert.equal(result.preferences.uok?.enabled, true);
27
+ assert.equal(result.preferences.uok?.legacy_fallback?.enabled, false);
28
+ assert.equal(result.preferences.uok?.gitops?.turn_action, "status-only");
29
+ assert.equal(result.preferences.uok?.plan_v2?.enabled, true);
30
+ });
31
+
32
+ test("uok preferences reject invalid turn_action", () => {
33
+ const result = validatePreferences({
34
+ uok: {
35
+ gitops: {
36
+ turn_action: "push-everything",
37
+ },
38
+ },
39
+ } as never);
40
+
41
+ assert.ok(result.errors.some((e) => e.includes("uok.gitops.turn_action")));
42
+ });
@@ -112,4 +112,43 @@ describe("handleValidateMilestone write ordering (#2725)", () => {
112
112
  ).get();
113
113
  assert.equal(row, undefined, "assessment row should be deleted after disk-write rollback");
114
114
  });
115
+
116
+ it("persists milestone validation gate_runs rows when UOK gates are enabled", async () => {
117
+ base = makeTmpBase();
118
+ const dbPath = join(base, ".gsd", "gsd.db");
119
+ openDatabase(dbPath);
120
+ insertMilestone({ id: "M001" });
121
+ insertSlice({ id: "S01", milestoneId: "M001" });
122
+
123
+ const result = await handleValidateMilestone(VALID_PARAMS, base, {
124
+ uokGatesEnabled: true,
125
+ traceId: "trace-val-1",
126
+ turnId: "turn-val-1",
127
+ });
128
+ assert.ok(!("error" in result), `unexpected error: ${"error" in result ? result.error : ""}`);
129
+
130
+ const adapter = _getAdapter()!;
131
+ const row = adapter.prepare(
132
+ `SELECT gate_id, outcome, failure_class, trace_id, turn_id
133
+ FROM gate_runs
134
+ WHERE gate_id = 'milestone-validation-gates'
135
+ ORDER BY id DESC
136
+ LIMIT 1`,
137
+ ).get() as
138
+ | {
139
+ gate_id: string;
140
+ outcome: string;
141
+ failure_class: string;
142
+ trace_id: string;
143
+ turn_id: string;
144
+ }
145
+ | undefined;
146
+
147
+ assert.ok(row, "milestone validation gate row should be persisted");
148
+ assert.equal(row?.gate_id, "milestone-validation-gates");
149
+ assert.equal(row?.outcome, "pass");
150
+ assert.equal(row?.failure_class, "none");
151
+ assert.equal(row?.trace_id, "trace-val-1");
152
+ assert.equal(row?.turn_id, "turn-val-1");
153
+ });
115
154
  });
@@ -430,11 +430,18 @@ export async function handleCompleteSlice(
430
430
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
431
431
  (async () => {
432
432
  try {
433
- const graphMod = await import("@gsd-build/mcp-server") as {
433
+ const graphMod = await import("@gsd-build/mcp-server") as unknown as Partial<{
434
434
  buildGraph: (dir: string) => Promise<{ nodes: unknown[]; edges: unknown[]; builtAt: string }>;
435
435
  writeGraph: (gsdRoot: string, graph: unknown) => Promise<void>;
436
436
  resolveGsdRoot: (basePath: string) => string;
437
- };
437
+ }>;
438
+ if (
439
+ typeof graphMod.buildGraph !== "function"
440
+ || typeof graphMod.writeGraph !== "function"
441
+ || typeof graphMod.resolveGsdRoot !== "function"
442
+ ) {
443
+ throw new Error("graph helpers unavailable from @gsd-build/mcp-server");
444
+ }
438
445
  const g = await graphMod.buildGraph(basePath);
439
446
  await graphMod.writeGraph(graphMod.resolveGsdRoot(basePath), g);
440
447
  } catch (graphErr) {
@@ -23,6 +23,9 @@ import { invalidateStateCache } from "../state.js";
23
23
  import { VALIDATION_VERDICTS, isValidMilestoneVerdict } from "../verdict-parser.js";
24
24
  import { insertMilestoneValidationGates } from "../milestone-validation-gates.js";
25
25
  import { logWarning } from "../workflow-logger.js";
26
+ import { UokGateRunner } from "../uok/gate-runner.js";
27
+ import { loadEffectiveGSDPreferences } from "../preferences.js";
28
+ import { resolveUokFlags } from "../uok/flags.js";
26
29
 
27
30
  export interface ValidateMilestoneParams {
28
31
  milestoneId: string;
@@ -43,6 +46,12 @@ export interface ValidateMilestoneResult {
43
46
  validationPath: string;
44
47
  }
45
48
 
49
+ export interface ValidateMilestoneOptions {
50
+ uokGatesEnabled?: boolean;
51
+ traceId?: string;
52
+ turnId?: string;
53
+ }
54
+
46
55
  function renderValidationMarkdown(params: ValidateMilestoneParams): string {
47
56
  let md = `---
48
57
  verdict: ${params.verdict}
@@ -81,6 +90,7 @@ ${params.verdictRationale}
81
90
  export async function handleValidateMilestone(
82
91
  params: ValidateMilestoneParams,
83
92
  basePath: string,
93
+ opts?: ValidateMilestoneOptions,
84
94
  ): Promise<ValidateMilestoneResult | { error: string }> {
85
95
  if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
86
96
  return { error: "milestoneId is required and must be a non-empty string" };
@@ -108,6 +118,8 @@ export async function handleValidateMilestone(
108
118
  // rendering can regenerate. The inverse (file exists, no DB row) is
109
119
  // harder to detect and recover from (#2725).
110
120
  const validatedAt = new Date().toISOString();
121
+ const slices = getMilestoneSlices(params.milestoneId);
122
+ const gateSliceId = slices.length > 0 ? slices[0].id : "_milestone";
111
123
 
112
124
  transaction(() => {
113
125
  insertAssessment({
@@ -123,11 +135,9 @@ export async function handleValidateMilestone(
123
135
  // #2945 Bug 4: persist quality_gates records alongside the assessment.
124
136
  // Previously only the assessment was written, leaving M002+ milestones
125
137
  // with zero quality_gate records despite passing validation.
126
- const slices = getMilestoneSlices(params.milestoneId);
127
- const sliceId = slices.length > 0 ? slices[0].id : "_milestone";
128
138
  insertMilestoneValidationGates(
129
139
  params.milestoneId,
130
- sliceId,
140
+ gateSliceId,
131
141
  params.verdict,
132
142
  validatedAt,
133
143
  );
@@ -147,6 +157,41 @@ export async function handleValidateMilestone(
147
157
  clearPathCache();
148
158
  clearParseCache();
149
159
 
160
+ const prefs = loadEffectiveGSDPreferences()?.preferences;
161
+ const gatesEnabled = opts?.uokGatesEnabled ?? resolveUokFlags(prefs).gates;
162
+ if (gatesEnabled) {
163
+ try {
164
+ const gateRunner = new UokGateRunner();
165
+ const nonPassVerdict = params.verdict !== "pass";
166
+ gateRunner.register({
167
+ id: "milestone-validation-gates",
168
+ type: "verification",
169
+ execute: async () => ({
170
+ outcome: nonPassVerdict ? "manual-attention" : "pass",
171
+ failureClass: nonPassVerdict ? "manual-attention" : "none",
172
+ rationale: `milestone validation verdict: ${params.verdict}`,
173
+ findings: nonPassVerdict
174
+ ? [params.verdictRationale, params.remediationPlan ?? ""].filter(Boolean).join("\n")
175
+ : "",
176
+ }),
177
+ });
178
+ await gateRunner.run("milestone-validation-gates", {
179
+ basePath,
180
+ traceId: opts?.traceId ?? `validate-milestone:${params.milestoneId}`,
181
+ turnId: opts?.turnId ?? `${params.milestoneId}:validate`,
182
+ milestoneId: params.milestoneId,
183
+ sliceId: gateSliceId,
184
+ unitType: "validate-milestone",
185
+ unitId: params.milestoneId,
186
+ });
187
+ } catch (err) {
188
+ logWarning(
189
+ "tool",
190
+ `validate_milestone — failed to persist UOK gate result: ${(err as Error).message}`,
191
+ );
192
+ }
193
+ }
194
+
150
195
  return {
151
196
  milestoneId: params.milestoneId,
152
197
  verdict: params.verdict,
@@ -253,6 +253,19 @@ export interface GSDState {
253
253
  lastCompletedMilestone?: ActiveRef | null;
254
254
  }
255
255
 
256
+ // ─── GSD Ecosystem Extension API Types ────────────────────────────────────
257
+ // Pure data type — no runtime deps. The GSDExtensionAPI interface itself
258
+ // lives in ecosystem/gsd-extension-api.ts (it imports from pi).
259
+
260
+ export interface GSDActiveUnit {
261
+ milestoneId: string;
262
+ milestoneTitle: string;
263
+ sliceId: string;
264
+ sliceTitle: string;
265
+ taskId: string;
266
+ taskTitle: string;
267
+ }
268
+
256
269
  // ─── Post-Unit Hook Types ─────────────────────────────────────────────────
257
270
 
258
271
  export interface PostUnitHookConfig {
@@ -306,7 +319,7 @@ export interface HookDispatchResult {
306
319
 
307
320
  export type BudgetEnforcementMode = "warn" | "pause" | "halt";
308
321
 
309
- export type TokenProfile = "budget" | "balanced" | "quality";
322
+ export type TokenProfile = "budget" | "balanced" | "quality" | "burn-max";
310
323
 
311
324
  export type InlineLevel = "full" | "standard" | "minimal";
312
325