gsd-pi 2.73.1-dev.d987996 → 2.74.0-dev.14c45ac

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 (365) hide show
  1. package/dist/cli-web-branch.d.ts +4 -3
  2. package/dist/cli-web-branch.js +10 -7
  3. package/dist/cli.js +184 -206
  4. package/dist/headless-query.js +4 -1
  5. package/dist/help-text.js +23 -0
  6. package/dist/logo.d.ts +1 -1
  7. package/dist/logo.js +1 -1
  8. package/dist/onboarding.js +59 -53
  9. package/dist/resource-loader.js +2 -2
  10. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +68 -4
  11. package/dist/resources/extensions/gsd/activity-log.js +16 -0
  12. package/dist/resources/extensions/gsd/auto/detect-stuck.js +11 -4
  13. package/dist/resources/extensions/gsd/auto/loop.js +147 -10
  14. package/dist/resources/extensions/gsd/auto/phases.js +173 -13
  15. package/dist/resources/extensions/gsd/auto/session.js +10 -0
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +22 -4
  17. package/dist/resources/extensions/gsd/auto-model-selection.js +105 -16
  18. package/dist/resources/extensions/gsd/auto-post-unit.js +254 -15
  19. package/dist/resources/extensions/gsd/auto-prompts.js +12 -0
  20. package/dist/resources/extensions/gsd/auto-start.js +23 -6
  21. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +13 -0
  22. package/dist/resources/extensions/gsd/auto-unit-closeout.js +18 -0
  23. package/dist/resources/extensions/gsd/auto-verification.js +186 -3
  24. package/dist/resources/extensions/gsd/auto.js +65 -12
  25. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +21 -8
  26. package/dist/resources/extensions/gsd/commands/catalog.js +26 -1
  27. package/dist/resources/extensions/gsd/commands/handlers/ops.js +25 -0
  28. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +68 -9
  29. package/dist/resources/extensions/gsd/commands-add-tests.js +111 -0
  30. package/dist/resources/extensions/gsd/commands-backlog.js +140 -0
  31. package/dist/resources/extensions/gsd/commands-do.js +79 -0
  32. package/dist/resources/extensions/gsd/commands-extract-learnings.js +225 -0
  33. package/dist/resources/extensions/gsd/commands-handlers.js +8 -2
  34. package/dist/resources/extensions/gsd/commands-maintenance.js +6 -6
  35. package/dist/resources/extensions/gsd/commands-pr-branch.js +180 -0
  36. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  37. package/dist/resources/extensions/gsd/commands-session-report.js +82 -0
  38. package/dist/resources/extensions/gsd/commands-ship.js +187 -0
  39. package/dist/resources/extensions/gsd/db-writer.js +3 -5
  40. package/dist/resources/extensions/gsd/docs/preferences-reference.md +15 -2
  41. package/dist/resources/extensions/gsd/git-service.js +49 -1
  42. package/dist/resources/extensions/gsd/graph-context.js +157 -0
  43. package/dist/resources/extensions/gsd/gsd-db.js +581 -2
  44. package/dist/resources/extensions/gsd/guided-flow.js +23 -0
  45. package/dist/resources/extensions/gsd/index.js +15 -2
  46. package/dist/resources/extensions/gsd/init-wizard.js +1 -0
  47. package/dist/resources/extensions/gsd/journal.js +27 -0
  48. package/dist/resources/extensions/gsd/md-importer.js +3 -4
  49. package/dist/resources/extensions/gsd/memory-store.js +19 -51
  50. package/dist/resources/extensions/gsd/metrics.js +19 -0
  51. package/dist/resources/extensions/gsd/milestone-validation-gates.js +13 -12
  52. package/dist/resources/extensions/gsd/native-git-bridge.js +7 -4
  53. package/dist/resources/extensions/gsd/notification-widget.js +2 -2
  54. package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
  55. package/dist/resources/extensions/gsd/preferences-models.js +63 -3
  56. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  57. package/dist/resources/extensions/gsd/preferences-validation.js +130 -2
  58. package/dist/resources/extensions/gsd/preferences.js +26 -0
  59. package/dist/resources/extensions/gsd/prompts/add-tests.md +35 -0
  60. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
  61. package/dist/resources/extensions/gsd/state.js +66 -15
  62. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  63. package/dist/resources/extensions/gsd/tools/complete-slice.js +20 -0
  64. package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
  65. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +3 -14
  66. package/dist/resources/extensions/gsd/triage-resolution.js +2 -5
  67. package/dist/resources/extensions/gsd/unit-ownership.js +1 -1
  68. package/dist/resources/extensions/gsd/uok/audit-toggle.js +7 -0
  69. package/dist/resources/extensions/gsd/uok/audit.js +40 -0
  70. package/dist/resources/extensions/gsd/uok/contracts.js +1 -0
  71. package/dist/resources/extensions/gsd/uok/execution-graph.js +179 -0
  72. package/dist/resources/extensions/gsd/uok/flags.js +29 -0
  73. package/dist/resources/extensions/gsd/uok/gate-runner.js +109 -0
  74. package/dist/resources/extensions/gsd/uok/gitops.js +53 -0
  75. package/dist/resources/extensions/gsd/uok/kernel.js +80 -0
  76. package/dist/resources/extensions/gsd/uok/loop-adapter.js +133 -0
  77. package/dist/resources/extensions/gsd/uok/model-policy.js +66 -0
  78. package/dist/resources/extensions/gsd/uok/plan-v2.js +132 -0
  79. package/dist/resources/extensions/gsd/workflow-logger.js +22 -0
  80. package/dist/resources/extensions/gsd/workflow-manifest.js +8 -69
  81. package/dist/resources/extensions/gsd/workflow-migration.js +21 -22
  82. package/dist/resources/extensions/gsd/workflow-projections.js +4 -1
  83. package/dist/resources/extensions/gsd/workflow-reconcile.js +14 -11
  84. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  85. package/dist/tsconfig.extensions.tsbuildinfo +1 -0
  86. package/dist/update-check.d.ts +1 -0
  87. package/dist/update-check.js +13 -5
  88. package/dist/update-cmd.js +4 -3
  89. package/dist/web/standalone/.next/BUILD_ID +1 -1
  90. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  91. package/dist/web/standalone/.next/build-manifest.json +2 -2
  92. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  93. package/dist/web/standalone/.next/required-server-files.json +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.html +1 -1
  111. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  118. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  120. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  121. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  122. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  123. package/dist/web/standalone/server.js +1 -1
  124. package/package.json +3 -3
  125. package/packages/daemon/package.json +2 -2
  126. package/packages/mcp-server/dist/index.d.ts +3 -0
  127. package/packages/mcp-server/dist/index.d.ts.map +1 -1
  128. package/packages/mcp-server/dist/index.js +3 -0
  129. package/packages/mcp-server/dist/index.js.map +1 -1
  130. package/packages/mcp-server/dist/readers/graph.d.ts +87 -0
  131. package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -0
  132. package/packages/mcp-server/dist/readers/graph.js +655 -0
  133. package/packages/mcp-server/dist/readers/graph.js.map +1 -0
  134. package/packages/mcp-server/dist/readers/index.d.ts +2 -0
  135. package/packages/mcp-server/dist/readers/index.d.ts.map +1 -1
  136. package/packages/mcp-server/dist/readers/index.js +1 -0
  137. package/packages/mcp-server/dist/readers/index.js.map +1 -1
  138. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  139. package/packages/mcp-server/dist/server.js +65 -0
  140. package/packages/mcp-server/dist/server.js.map +1 -1
  141. package/packages/mcp-server/package.json +2 -2
  142. package/packages/mcp-server/src/index.ts +15 -0
  143. package/packages/mcp-server/src/readers/graph.test.ts +604 -0
  144. package/packages/mcp-server/src/readers/graph.ts +855 -0
  145. package/packages/mcp-server/src/readers/index.ts +12 -0
  146. package/packages/mcp-server/src/server.ts +83 -0
  147. package/packages/mcp-server/tsconfig.json +1 -0
  148. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -0
  149. package/packages/native/package.json +2 -2
  150. package/packages/native/tsconfig.tsbuildinfo +1 -0
  151. package/packages/pi-agent-core/package.json +1 -1
  152. package/packages/pi-agent-core/tsconfig.json +1 -0
  153. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -0
  154. package/packages/pi-ai/dist/index.d.ts +1 -0
  155. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  156. package/packages/pi-ai/dist/index.js +1 -0
  157. package/packages/pi-ai/dist/index.js.map +1 -1
  158. package/packages/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  159. package/packages/pi-ai/dist/utils/overflow.js +12 -0
  160. package/packages/pi-ai/dist/utils/overflow.js.map +1 -1
  161. package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts +2 -0
  162. package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts.map +1 -0
  163. package/packages/pi-ai/dist/utils/tests/overflow.test.js +50 -0
  164. package/packages/pi-ai/dist/utils/tests/overflow.test.js.map +1 -0
  165. package/packages/pi-ai/package.json +1 -1
  166. package/packages/pi-ai/src/index.ts +4 -0
  167. package/packages/pi-ai/src/utils/overflow.ts +14 -1
  168. package/packages/pi-ai/src/utils/tests/overflow.test.ts +58 -0
  169. package/packages/pi-ai/tsconfig.json +1 -0
  170. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -0
  171. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +511 -8
  172. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  173. package/packages/pi-coding-agent/dist/core/compaction/utils.js +5 -5
  174. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  175. package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts +2 -0
  176. package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts.map +1 -0
  177. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +45 -0
  178. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -0
  179. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts +2 -0
  180. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts.map +1 -0
  181. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js +52 -0
  182. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js.map +1 -0
  183. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  185. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +12 -2
  187. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  188. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +61 -28
  189. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  190. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +2 -1
  191. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +9 -3
  193. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts +2 -0
  195. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts.map +1 -0
  196. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +52 -0
  197. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -0
  198. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  199. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +165 -20
  200. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  201. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +11 -3
  203. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  204. package/packages/pi-coding-agent/package.json +1 -1
  205. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +620 -8
  206. package/packages/pi-coding-agent/src/core/compaction/utils.ts +5 -5
  207. package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +50 -0
  208. package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
  209. package/packages/pi-coding-agent/src/core/model-registry.ts +2 -1
  210. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +74 -32
  211. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +73 -0
  212. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +9 -3
  213. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +189 -25
  214. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +11 -3
  215. package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
  216. package/packages/pi-coding-agent/tsconfig.json +3 -2
  217. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -0
  218. package/packages/pi-tui/dist/__tests__/tui.test.js +60 -1
  219. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  220. package/packages/pi-tui/dist/tui.d.ts +8 -0
  221. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  222. package/packages/pi-tui/dist/tui.js +32 -3
  223. package/packages/pi-tui/dist/tui.js.map +1 -1
  224. package/packages/pi-tui/package.json +1 -1
  225. package/packages/pi-tui/src/__tests__/tui.test.ts +76 -1
  226. package/packages/pi-tui/src/tui.ts +31 -3
  227. package/packages/pi-tui/tsconfig.json +1 -0
  228. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -0
  229. package/packages/rpc-client/package.json +1 -1
  230. package/packages/rpc-client/tsconfig.json +1 -0
  231. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -0
  232. package/pkg/package.json +1 -1
  233. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +107 -5
  234. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +111 -2
  235. package/src/resources/extensions/gsd/activity-log.ts +21 -0
  236. package/src/resources/extensions/gsd/auto/detect-stuck.ts +12 -4
  237. package/src/resources/extensions/gsd/auto/loop-deps.ts +10 -0
  238. package/src/resources/extensions/gsd/auto/loop.ts +159 -10
  239. package/src/resources/extensions/gsd/auto/phases.ts +213 -13
  240. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  241. package/src/resources/extensions/gsd/auto-dispatch.ts +26 -10
  242. package/src/resources/extensions/gsd/auto-model-selection.ts +151 -16
  243. package/src/resources/extensions/gsd/auto-post-unit.ts +278 -16
  244. package/src/resources/extensions/gsd/auto-prompts.ts +13 -0
  245. package/src/resources/extensions/gsd/auto-start.ts +30 -6
  246. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +17 -0
  247. package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
  248. package/src/resources/extensions/gsd/auto-verification.ts +225 -3
  249. package/src/resources/extensions/gsd/auto.ts +72 -16
  250. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -8
  251. package/src/resources/extensions/gsd/commands/catalog.ts +26 -1
  252. package/src/resources/extensions/gsd/commands/handlers/ops.ts +25 -0
  253. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +74 -9
  254. package/src/resources/extensions/gsd/commands-add-tests.ts +137 -0
  255. package/src/resources/extensions/gsd/commands-backlog.ts +182 -0
  256. package/src/resources/extensions/gsd/commands-do.ts +109 -0
  257. package/src/resources/extensions/gsd/commands-extract-learnings.ts +304 -0
  258. package/src/resources/extensions/gsd/commands-handlers.ts +8 -2
  259. package/src/resources/extensions/gsd/commands-maintenance.ts +6 -6
  260. package/src/resources/extensions/gsd/commands-pr-branch.ts +234 -0
  261. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  262. package/src/resources/extensions/gsd/commands-session-report.ts +101 -0
  263. package/src/resources/extensions/gsd/commands-ship.ts +219 -0
  264. package/src/resources/extensions/gsd/db-writer.ts +3 -5
  265. package/src/resources/extensions/gsd/docs/preferences-reference.md +15 -2
  266. package/src/resources/extensions/gsd/git-service.ts +68 -0
  267. package/src/resources/extensions/gsd/graph-context.ts +212 -0
  268. package/src/resources/extensions/gsd/gsd-db.ts +788 -3
  269. package/src/resources/extensions/gsd/guided-flow.ts +32 -0
  270. package/src/resources/extensions/gsd/index.ts +18 -2
  271. package/src/resources/extensions/gsd/init-wizard.ts +3 -2
  272. package/src/resources/extensions/gsd/journal.ts +30 -0
  273. package/src/resources/extensions/gsd/md-importer.ts +3 -5
  274. package/src/resources/extensions/gsd/memory-store.ts +31 -62
  275. package/src/resources/extensions/gsd/metrics.ts +26 -0
  276. package/src/resources/extensions/gsd/milestone-validation-gates.ts +13 -14
  277. package/src/resources/extensions/gsd/native-git-bridge.ts +11 -12
  278. package/src/resources/extensions/gsd/notification-widget.ts +2 -2
  279. package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
  280. package/src/resources/extensions/gsd/preferences-models.ts +61 -3
  281. package/src/resources/extensions/gsd/preferences-types.ts +44 -0
  282. package/src/resources/extensions/gsd/preferences-validation.ts +130 -2
  283. package/src/resources/extensions/gsd/preferences.ts +28 -0
  284. package/src/resources/extensions/gsd/prompts/add-tests.md +35 -0
  285. package/src/resources/extensions/gsd/session-lock.ts +14 -2
  286. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +20 -1
  287. package/src/resources/extensions/gsd/state.ts +80 -17
  288. package/src/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  289. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +9 -5
  290. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
  291. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +53 -0
  292. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
  293. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +51 -2
  294. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
  295. package/src/resources/extensions/gsd/tests/commands-backlog.test.ts +158 -0
  296. package/src/resources/extensions/gsd/tests/commands-do.test.ts +127 -0
  297. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +340 -0
  298. package/src/resources/extensions/gsd/tests/commands-pr-branch.test.ts +68 -0
  299. package/src/resources/extensions/gsd/tests/commands-session-report.test.ts +82 -0
  300. package/src/resources/extensions/gsd/tests/commands-ship.test.ts +71 -0
  301. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +14 -0
  302. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +142 -0
  303. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  304. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  305. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +42 -0
  306. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -2
  307. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +3 -2
  308. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +68 -8
  309. package/src/resources/extensions/gsd/tests/derive-state.test.ts +3 -3
  310. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +154 -0
  311. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
  312. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +137 -1
  313. package/src/resources/extensions/gsd/tests/graph-context.test.ts +337 -0
  314. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  315. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  316. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +68 -1
  317. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -2
  318. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -3
  319. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +91 -2
  320. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +140 -0
  321. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  322. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +2 -1
  323. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +40 -1
  324. package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -0
  325. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +180 -0
  326. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +5 -7
  327. package/src/resources/extensions/gsd/tests/token-profile.test.ts +9 -6
  328. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
  329. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +85 -0
  330. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +69 -0
  331. package/src/resources/extensions/gsd/tests/uok-flags.test.ts +39 -0
  332. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +70 -0
  333. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +85 -0
  334. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +35 -0
  335. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
  336. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +167 -0
  337. package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
  338. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +179 -0
  339. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
  340. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +223 -0
  341. package/src/resources/extensions/gsd/tools/complete-slice.ts +26 -0
  342. package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
  343. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +3 -11
  344. package/src/resources/extensions/gsd/triage-resolution.ts +2 -7
  345. package/src/resources/extensions/gsd/types.ts +1 -1
  346. package/src/resources/extensions/gsd/unit-ownership.ts +2 -2
  347. package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
  348. package/src/resources/extensions/gsd/uok/audit.ts +51 -0
  349. package/src/resources/extensions/gsd/uok/contracts.ts +135 -0
  350. package/src/resources/extensions/gsd/uok/execution-graph.ts +241 -0
  351. package/src/resources/extensions/gsd/uok/flags.ts +45 -0
  352. package/src/resources/extensions/gsd/uok/gate-runner.ts +146 -0
  353. package/src/resources/extensions/gsd/uok/gitops.ts +75 -0
  354. package/src/resources/extensions/gsd/uok/kernel.ts +105 -0
  355. package/src/resources/extensions/gsd/uok/loop-adapter.ts +162 -0
  356. package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
  357. package/src/resources/extensions/gsd/uok/plan-v2.ts +156 -0
  358. package/src/resources/extensions/gsd/workflow-logger.ts +25 -0
  359. package/src/resources/extensions/gsd/workflow-manifest.ts +9 -104
  360. package/src/resources/extensions/gsd/workflow-migration.ts +21 -29
  361. package/src/resources/extensions/gsd/workflow-projections.ts +8 -1
  362. package/src/resources/extensions/gsd/workflow-reconcile.ts +15 -15
  363. package/src/resources/extensions/ttsr/ttsr-manager.ts +10 -5
  364. /package/dist/web/standalone/.next/static/{cGmbVq2su4f9tMpgIkG8u → ZMKM0OI0CrTgzKWbgfPOg}/_buildManifest.js +0 -0
  365. /package/dist/web/standalone/.next/static/{cGmbVq2su4f9tMpgIkG8u → ZMKM0OI0CrTgzKWbgfPOg}/_ssgManifest.js +0 -0
@@ -34,11 +34,12 @@ const typesSrc = readFileSync(join(__dirname, "..", "types.ts"), "utf-8");
34
34
  // Type Definitions
35
35
  // ═══════════════════════════════════════════════════════════════════════════
36
36
 
37
- test("types: TokenProfile type exported with budget/balanced/quality", () => {
37
+ test("types: TokenProfile type exported with budget/balanced/quality/burn-max", () => {
38
38
  assert.ok(typesSrc.includes("export type TokenProfile"), "TokenProfile should be exported");
39
39
  assert.match(typesSrc, /["']budget["']/, "should include budget");
40
40
  assert.match(typesSrc, /["']balanced["']/, "should include balanced");
41
41
  assert.match(typesSrc, /["']quality["']/, "should include quality");
42
+ assert.match(typesSrc, /["']burn-max["']/, "should include burn-max");
42
43
  });
43
44
 
44
45
  test("types: InlineLevel type exported with full/standard/minimal", () => {
@@ -91,7 +92,7 @@ test("preferences: KNOWN_PREFERENCE_KEYS includes token_profile and phases", ()
91
92
  // Profile Resolution
92
93
  // ═══════════════════════════════════════════════════════════════════════════
93
94
 
94
- test("profile: resolveProfileDefaults exists and handles all 3 tiers", () => {
95
+ test("profile: resolveProfileDefaults exists and handles all 4 tiers", () => {
95
96
  assert.ok(
96
97
  preferencesSrc.includes("export function resolveProfileDefaults"),
97
98
  "resolveProfileDefaults should be exported",
@@ -99,8 +100,9 @@ test("profile: resolveProfileDefaults exists and handles all 3 tiers", () => {
99
100
  assert.ok(
100
101
  preferencesSrc.includes('case "budget"') &&
101
102
  preferencesSrc.includes('case "balanced"') &&
102
- preferencesSrc.includes('case "quality"'),
103
- "resolveProfileDefaults should handle all 3 tiers",
103
+ preferencesSrc.includes('case "quality"') &&
104
+ preferencesSrc.includes('case "burn-max"'),
105
+ "resolveProfileDefaults should handle all 4 tiers",
104
106
  );
105
107
  });
106
108
 
@@ -158,6 +160,7 @@ test("profile: resolveInlineLevel maps profile to inline level", () => {
158
160
  assert.ok(preferencesSrc.includes('case "budget": return "minimal"'), "budget → minimal");
159
161
  assert.ok(preferencesSrc.includes('case "balanced": return "standard"'), "balanced → standard");
160
162
  assert.ok(preferencesSrc.includes('case "quality": return "full"'), "quality → full");
163
+ assert.ok(preferencesSrc.includes('case "burn-max": return "full"'), "burn-max → full");
161
164
  });
162
165
 
163
166
  // ═══════════════════════════════════════════════════════════════════════════
@@ -167,7 +170,7 @@ test("profile: resolveInlineLevel maps profile to inline level", () => {
167
170
  test("validate: validatePreferences handles token_profile", () => {
168
171
  assert.ok(
169
172
  preferencesSrc.includes("preferences.token_profile") &&
170
- preferencesSrc.includes("budget, balanced, quality"),
173
+ preferencesSrc.includes("budget, balanced, quality, burn-max"),
171
174
  "validatePreferences should validate token_profile enum values",
172
175
  );
173
176
  });
@@ -263,6 +266,6 @@ test("dispatch: phase skip guards return null (not stop)", () => {
263
266
  const researchGuard = dispatchSrc.match(/skip_research\).*?return null/s);
264
267
  assert.ok(researchGuard, "skip_research guard should return null (fall-through)");
265
268
 
266
- const reassessGuard = dispatchSrc.match(/reassess_after_slice\).*?return null/s);
269
+ const reassessGuard = dispatchSrc.match(/reassess_after_slice.*?return null/s);
267
270
  assert.ok(reassessGuard, "reassess_after_slice guard should return null (fall-through)");
268
271
  });
@@ -0,0 +1,101 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, readFileSync, rmSync, existsSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { emitJournalEvent } from "../journal.ts";
7
+ import { saveActivityLog } from "../activity-log.ts";
8
+ import { initMetrics, resetMetrics, snapshotUnitMetrics } from "../metrics.ts";
9
+ import { setLogBasePath, logWarning } from "../workflow-logger.ts";
10
+ import { setUnifiedAuditEnabled } from "../uok/audit-toggle.ts";
11
+
12
+ function readAuditEvents(basePath: string): Array<Record<string, unknown>> {
13
+ const file = join(basePath, ".gsd", "audit", "events.jsonl");
14
+ if (!existsSync(file)) return [];
15
+ const raw = readFileSync(file, "utf-8");
16
+ return raw
17
+ .split("\n")
18
+ .filter(Boolean)
19
+ .map((line) => JSON.parse(line) as Record<string, unknown>);
20
+ }
21
+
22
+ function makeMockContext(entries: unknown[]): any {
23
+ return {
24
+ sessionManager: {
25
+ getEntries: () => entries,
26
+ },
27
+ };
28
+ }
29
+
30
+ test("unified audit plane bridges journal/activity/metrics/workflow logger into audit envelope log", () => {
31
+ const basePath = mkdtempSync(join(tmpdir(), "gsd-uok-audit-"));
32
+ setUnifiedAuditEnabled(true);
33
+ try {
34
+ emitJournalEvent(basePath, {
35
+ ts: new Date().toISOString(),
36
+ flowId: "trace-123",
37
+ seq: 1,
38
+ eventType: "iteration-start",
39
+ data: { turnId: "turn-123", unitId: "M001/S01/T01" },
40
+ });
41
+
42
+ const activityCtx = makeMockContext([
43
+ { type: "message", message: { role: "assistant", content: [{ type: "text", text: "hello" }] } },
44
+ ]);
45
+ const activityPath = saveActivityLog(activityCtx, basePath, "execute-task", "M001/S01/T01");
46
+ assert.ok(activityPath);
47
+
48
+ initMetrics(basePath);
49
+ const metricsCtx = makeMockContext([
50
+ {
51
+ type: "message",
52
+ message: {
53
+ role: "assistant",
54
+ usage: { input: 10, output: 5, cacheRead: 0, cacheWrite: 0, totalTokens: 15, cost: 0.01 },
55
+ content: [],
56
+ },
57
+ },
58
+ ]);
59
+ const unit = snapshotUnitMetrics(
60
+ metricsCtx,
61
+ "execute-task",
62
+ "M001/S01/T01",
63
+ Date.now() - 1000,
64
+ "openai/gpt-5.4",
65
+ { traceId: "trace-123", turnId: "turn-123" },
66
+ );
67
+ assert.ok(unit);
68
+ resetMetrics();
69
+
70
+ setLogBasePath(basePath);
71
+ logWarning("engine", "audit bridge check", { id: "turn-123" });
72
+
73
+ const events = readAuditEvents(basePath);
74
+ const types = new Set(events.map((event) => String(event.type ?? "")));
75
+ assert.ok(types.has("journal-iteration-start"));
76
+ assert.ok(types.has("activity-log-saved"));
77
+ assert.ok(types.has("unit-metrics-snapshot"));
78
+ assert.ok(types.has("workflow-log-warn"));
79
+ } finally {
80
+ setUnifiedAuditEnabled(false);
81
+ resetMetrics();
82
+ rmSync(basePath, { recursive: true, force: true });
83
+ }
84
+ });
85
+
86
+ test("unified audit bridge is disabled when toggle is off", () => {
87
+ const basePath = mkdtempSync(join(tmpdir(), "gsd-uok-audit-off-"));
88
+ setUnifiedAuditEnabled(false);
89
+ try {
90
+ emitJournalEvent(basePath, {
91
+ ts: new Date().toISOString(),
92
+ flowId: "trace-off",
93
+ seq: 1,
94
+ eventType: "iteration-start",
95
+ });
96
+ const events = readAuditEvents(basePath);
97
+ assert.equal(events.length, 0);
98
+ } finally {
99
+ rmSync(basePath, { recursive: true, force: true });
100
+ }
101
+ });
@@ -0,0 +1,85 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import type {
5
+ AuditEventEnvelope,
6
+ GateResult,
7
+ TurnContract,
8
+ TurnResult,
9
+ UokNodeKind,
10
+ } from "../uok/contracts.ts";
11
+ import { buildAuditEnvelope } from "../uok/audit.ts";
12
+
13
+ test("uok contracts serialize/deserialize turn envelopes", () => {
14
+ const contract: TurnContract = {
15
+ traceId: "trace-1",
16
+ turnId: "turn-1",
17
+ iteration: 1,
18
+ basePath: "/tmp/project",
19
+ unitType: "execute-task",
20
+ unitId: "M001.S01.T01",
21
+ startedAt: new Date().toISOString(),
22
+ };
23
+
24
+ const gate: GateResult = {
25
+ gateId: "Q3",
26
+ gateType: "policy",
27
+ outcome: "pass",
28
+ failureClass: "none",
29
+ attempt: 1,
30
+ maxAttempts: 1,
31
+ retryable: false,
32
+ evaluatedAt: new Date().toISOString(),
33
+ };
34
+
35
+ const result: TurnResult = {
36
+ traceId: contract.traceId,
37
+ turnId: contract.turnId,
38
+ iteration: contract.iteration,
39
+ unitType: contract.unitType,
40
+ unitId: contract.unitId,
41
+ status: "completed",
42
+ failureClass: "none",
43
+ phaseResults: [
44
+ { phase: "dispatch", action: "next", ts: new Date().toISOString() },
45
+ { phase: "unit", action: "continue", ts: new Date().toISOString() },
46
+ { phase: "finalize", action: "next", ts: new Date().toISOString() },
47
+ ],
48
+ gateResults: [gate],
49
+ startedAt: contract.startedAt,
50
+ finishedAt: new Date().toISOString(),
51
+ };
52
+
53
+ const roundTrip = JSON.parse(JSON.stringify(result)) as TurnResult;
54
+ assert.equal(roundTrip.turnId, "turn-1");
55
+ assert.equal(roundTrip.gateResults?.[0]?.gateId, "Q3");
56
+ assert.equal(roundTrip.phaseResults.length, 3);
57
+ });
58
+
59
+ test("uok contracts include required DAG node kinds", () => {
60
+ const required: UokNodeKind[] = [
61
+ "unit",
62
+ "hook",
63
+ "subagent",
64
+ "team-worker",
65
+ "verification",
66
+ "reprocess",
67
+ ];
68
+ assert.deepEqual(required.length, 6);
69
+ });
70
+
71
+ test("uok audit envelope includes trace/turn/causality fields", () => {
72
+ const event: AuditEventEnvelope = buildAuditEnvelope({
73
+ traceId: "trace-xyz",
74
+ turnId: "turn-xyz",
75
+ causedBy: "turn-start",
76
+ category: "orchestration",
77
+ type: "turn-result",
78
+ payload: { status: "completed" },
79
+ });
80
+
81
+ assert.equal(event.traceId, "trace-xyz");
82
+ assert.equal(event.turnId, "turn-xyz");
83
+ assert.equal(event.causedBy, "turn-start");
84
+ assert.equal(event.payload.status, "completed");
85
+ });
@@ -0,0 +1,69 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import type { SidecarItem } from "../auto/session.ts";
4
+ import {
5
+ selectConflictFreeBatch,
6
+ selectReactiveDispatchBatch,
7
+ buildSidecarQueueNodes,
8
+ scheduleSidecarQueue,
9
+ } from "../uok/execution-graph.ts";
10
+
11
+ test("uok execution graph selects deterministic conflict-free IDs", () => {
12
+ const selected = selectConflictFreeBatch({
13
+ orderedIds: ["S01", "S02", "S03", "S04"],
14
+ maxParallel: 4,
15
+ hasConflict: (candidate, existing) =>
16
+ (candidate === "S02" && existing === "S01") ||
17
+ (candidate === "S01" && existing === "S02"),
18
+ });
19
+
20
+ assert.deepEqual(selected, ["S01", "S03", "S04"]);
21
+ });
22
+
23
+ test("uok execution graph reactive batch honors file conflicts and in-flight writes", () => {
24
+ const result = selectReactiveDispatchBatch({
25
+ graph: [
26
+ { id: "T01", dependsOn: [], outputFiles: ["src/a.ts"] },
27
+ { id: "T02", dependsOn: [], outputFiles: ["src/a.ts"] },
28
+ { id: "T03", dependsOn: [], outputFiles: ["src/b.ts"] },
29
+ { id: "T04", dependsOn: ["T03"], outputFiles: ["src/c.ts"] },
30
+ ],
31
+ readyIds: ["T01", "T02", "T03", "T04"],
32
+ maxParallel: 3,
33
+ inFlightOutputs: new Set(["src/c.ts"]),
34
+ });
35
+
36
+ assert.deepEqual(result.selected, ["T01", "T03"]);
37
+ assert.ok(
38
+ result.conflicts.some((c) => c.nodeA === "T01" && c.nodeB === "T02" && c.file === "src/a.ts"),
39
+ "conflict list should include overlapping outputs",
40
+ );
41
+ });
42
+
43
+ test("uok execution graph sidecar nodes map queue kinds to supported DAG kinds", () => {
44
+ const queue: SidecarItem[] = [
45
+ { kind: "hook", unitType: "execute-task", unitId: "M001/S01/T01", prompt: "hook" },
46
+ { kind: "triage", unitType: "triage", unitId: "M001/S01", prompt: "triage" },
47
+ { kind: "quick-task", unitType: "quick-task", unitId: "M001/S01/Q01", prompt: "quick" },
48
+ ];
49
+
50
+ const nodes = buildSidecarQueueNodes(queue);
51
+ assert.equal(nodes[0]?.kind, "hook");
52
+ assert.equal(nodes[1]?.kind, "verification");
53
+ assert.equal(nodes[2]?.kind, "team-worker");
54
+ assert.equal(nodes[1]?.dependsOn.length, 1);
55
+ });
56
+
57
+ test("uok execution graph sidecar scheduler preserves deterministic queue order", async () => {
58
+ const queue: SidecarItem[] = [
59
+ { kind: "quick-task", unitType: "quick-task", unitId: "M001/S01/Q01", prompt: "q1" },
60
+ { kind: "hook", unitType: "hook", unitId: "M001/S01/H01", prompt: "h1" },
61
+ { kind: "triage", unitType: "triage", unitId: "M001/S01/TR1", prompt: "t1" },
62
+ ];
63
+
64
+ const scheduled = await scheduleSidecarQueue(queue);
65
+ assert.deepEqual(
66
+ scheduled.map((item) => item.unitId),
67
+ queue.map((item) => item.unitId),
68
+ );
69
+ });
@@ -0,0 +1,39 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import { resolveUokFlags } from "../uok/flags.ts";
5
+
6
+ test("uok flags default to enabled when preference is unset", () => {
7
+ const flags = resolveUokFlags(undefined);
8
+ assert.equal(flags.enabled, true);
9
+ assert.equal(flags.legacyFallback, false);
10
+ });
11
+
12
+ test("uok legacy fallback preference forces legacy path", () => {
13
+ const flags = resolveUokFlags({
14
+ uok: {
15
+ enabled: true,
16
+ legacy_fallback: { enabled: true },
17
+ },
18
+ });
19
+ assert.equal(flags.enabled, false);
20
+ assert.equal(flags.legacyFallback, true);
21
+ });
22
+
23
+ test("uok legacy fallback env var forces legacy path", () => {
24
+ const previous = process.env.GSD_UOK_FORCE_LEGACY;
25
+ process.env.GSD_UOK_FORCE_LEGACY = "1";
26
+ try {
27
+ const flags = resolveUokFlags({
28
+ uok: {
29
+ enabled: true,
30
+ },
31
+ });
32
+ assert.equal(flags.enabled, false);
33
+ assert.equal(flags.legacyFallback, true);
34
+ } finally {
35
+ if (previous === undefined) delete process.env.GSD_UOK_FORCE_LEGACY;
36
+ else process.env.GSD_UOK_FORCE_LEGACY = previous;
37
+ }
38
+ });
39
+
@@ -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
+ });