gsd-pi 2.74.0-dev.2b524c3 → 2.74.0-dev.6e23363

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 (275) hide show
  1. package/dist/cli.js +85 -0
  2. package/dist/headless-query.js +4 -1
  3. package/dist/help-text.js +23 -0
  4. package/dist/resources/extensions/gsd/activity-log.js +16 -0
  5. package/dist/resources/extensions/gsd/auto/detect-stuck.js +11 -4
  6. package/dist/resources/extensions/gsd/auto/loop.js +147 -10
  7. package/dist/resources/extensions/gsd/auto/phases.js +158 -4
  8. package/dist/resources/extensions/gsd/auto/session.js +10 -0
  9. package/dist/resources/extensions/gsd/auto-dispatch.js +11 -1
  10. package/dist/resources/extensions/gsd/auto-model-selection.js +51 -5
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +213 -14
  12. package/dist/resources/extensions/gsd/auto-prompts.js +12 -0
  13. package/dist/resources/extensions/gsd/auto-unit-closeout.js +18 -0
  14. package/dist/resources/extensions/gsd/auto-verification.js +100 -2
  15. package/dist/resources/extensions/gsd/auto.js +36 -4
  16. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +21 -8
  17. package/dist/resources/extensions/gsd/commands/catalog.js +26 -1
  18. package/dist/resources/extensions/gsd/commands/handlers/ops.js +20 -0
  19. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +68 -9
  20. package/dist/resources/extensions/gsd/commands-add-tests.js +111 -0
  21. package/dist/resources/extensions/gsd/commands-backlog.js +140 -0
  22. package/dist/resources/extensions/gsd/commands-do.js +79 -0
  23. package/dist/resources/extensions/gsd/commands-maintenance.js +6 -6
  24. package/dist/resources/extensions/gsd/commands-pr-branch.js +180 -0
  25. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  26. package/dist/resources/extensions/gsd/commands-session-report.js +82 -0
  27. package/dist/resources/extensions/gsd/commands-ship.js +187 -0
  28. package/dist/resources/extensions/gsd/db-writer.js +3 -5
  29. package/dist/resources/extensions/gsd/docs/preferences-reference.md +14 -1
  30. package/dist/resources/extensions/gsd/git-service.js +49 -1
  31. package/dist/resources/extensions/gsd/graph-context.js +157 -0
  32. package/dist/resources/extensions/gsd/gsd-db.js +581 -2
  33. package/dist/resources/extensions/gsd/guided-flow.js +23 -0
  34. package/dist/resources/extensions/gsd/index.js +15 -2
  35. package/dist/resources/extensions/gsd/init-wizard.js +1 -0
  36. package/dist/resources/extensions/gsd/journal.js +27 -0
  37. package/dist/resources/extensions/gsd/md-importer.js +3 -4
  38. package/dist/resources/extensions/gsd/memory-store.js +19 -51
  39. package/dist/resources/extensions/gsd/metrics.js +19 -0
  40. package/dist/resources/extensions/gsd/milestone-validation-gates.js +13 -12
  41. package/dist/resources/extensions/gsd/native-git-bridge.js +7 -4
  42. package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
  43. package/dist/resources/extensions/gsd/preferences-models.js +20 -3
  44. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  45. package/dist/resources/extensions/gsd/preferences-validation.js +108 -2
  46. package/dist/resources/extensions/gsd/preferences.js +26 -0
  47. package/dist/resources/extensions/gsd/prompts/add-tests.md +35 -0
  48. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
  49. package/dist/resources/extensions/gsd/state.js +5 -1
  50. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  51. package/dist/resources/extensions/gsd/tools/complete-slice.js +20 -0
  52. package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
  53. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +3 -14
  54. package/dist/resources/extensions/gsd/triage-resolution.js +2 -5
  55. package/dist/resources/extensions/gsd/unit-ownership.js +1 -1
  56. package/dist/resources/extensions/gsd/uok/audit-toggle.js +7 -0
  57. package/dist/resources/extensions/gsd/uok/audit.js +40 -0
  58. package/dist/resources/extensions/gsd/uok/contracts.js +1 -0
  59. package/dist/resources/extensions/gsd/uok/execution-graph.js +179 -0
  60. package/dist/resources/extensions/gsd/uok/flags.js +29 -0
  61. package/dist/resources/extensions/gsd/uok/gate-runner.js +109 -0
  62. package/dist/resources/extensions/gsd/uok/gitops.js +53 -0
  63. package/dist/resources/extensions/gsd/uok/kernel.js +80 -0
  64. package/dist/resources/extensions/gsd/uok/loop-adapter.js +133 -0
  65. package/dist/resources/extensions/gsd/uok/model-policy.js +66 -0
  66. package/dist/resources/extensions/gsd/uok/plan-v2.js +132 -0
  67. package/dist/resources/extensions/gsd/workflow-logger.js +22 -0
  68. package/dist/resources/extensions/gsd/workflow-manifest.js +8 -69
  69. package/dist/resources/extensions/gsd/workflow-migration.js +21 -22
  70. package/dist/resources/extensions/gsd/workflow-projections.js +4 -1
  71. package/dist/resources/extensions/gsd/workflow-reconcile.js +14 -11
  72. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  73. package/dist/tsconfig.extensions.tsbuildinfo +1 -0
  74. package/dist/web/standalone/.next/BUILD_ID +1 -1
  75. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  76. package/dist/web/standalone/.next/build-manifest.json +2 -2
  77. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  78. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  79. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  87. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/index.html +1 -1
  95. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  102. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  104. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  105. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  106. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  107. package/package.json +3 -2
  108. package/packages/daemon/package.json +2 -2
  109. package/packages/mcp-server/dist/index.d.ts +3 -0
  110. package/packages/mcp-server/dist/index.d.ts.map +1 -1
  111. package/packages/mcp-server/dist/index.js +3 -0
  112. package/packages/mcp-server/dist/index.js.map +1 -1
  113. package/packages/mcp-server/dist/readers/graph.d.ts +87 -0
  114. package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -0
  115. package/packages/mcp-server/dist/readers/graph.js +548 -0
  116. package/packages/mcp-server/dist/readers/graph.js.map +1 -0
  117. package/packages/mcp-server/dist/readers/index.d.ts +2 -0
  118. package/packages/mcp-server/dist/readers/index.d.ts.map +1 -1
  119. package/packages/mcp-server/dist/readers/index.js +1 -0
  120. package/packages/mcp-server/dist/readers/index.js.map +1 -1
  121. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  122. package/packages/mcp-server/dist/server.js +65 -0
  123. package/packages/mcp-server/dist/server.js.map +1 -1
  124. package/packages/mcp-server/package.json +2 -2
  125. package/packages/mcp-server/src/index.ts +15 -0
  126. package/packages/mcp-server/src/readers/graph.test.ts +426 -0
  127. package/packages/mcp-server/src/readers/graph.ts +708 -0
  128. package/packages/mcp-server/src/readers/index.ts +12 -0
  129. package/packages/mcp-server/src/server.ts +83 -0
  130. package/packages/mcp-server/tsconfig.json +1 -0
  131. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -0
  132. package/packages/native/package.json +2 -2
  133. package/packages/native/tsconfig.tsbuildinfo +1 -0
  134. package/packages/pi-agent-core/package.json +1 -1
  135. package/packages/pi-agent-core/tsconfig.json +1 -0
  136. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -0
  137. package/packages/pi-ai/package.json +1 -1
  138. package/packages/pi-ai/tsconfig.json +1 -0
  139. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -0
  140. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +120 -0
  141. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  142. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts +2 -0
  143. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts.map +1 -0
  144. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js +52 -0
  145. package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js.map +1 -0
  146. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  147. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  148. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  149. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  150. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +48 -4
  151. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  152. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +166 -0
  153. package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
  154. package/packages/pi-coding-agent/src/core/model-registry.ts +2 -1
  155. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +53 -4
  156. package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
  157. package/packages/pi-coding-agent/tsconfig.json +3 -2
  158. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -0
  159. package/packages/pi-tui/package.json +1 -1
  160. package/packages/pi-tui/tsconfig.json +1 -0
  161. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -0
  162. package/packages/rpc-client/package.json +1 -1
  163. package/packages/rpc-client/tsconfig.json +1 -0
  164. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -0
  165. package/src/resources/extensions/gsd/activity-log.ts +21 -0
  166. package/src/resources/extensions/gsd/auto/detect-stuck.ts +12 -4
  167. package/src/resources/extensions/gsd/auto/loop-deps.ts +10 -0
  168. package/src/resources/extensions/gsd/auto/loop.ts +159 -10
  169. package/src/resources/extensions/gsd/auto/phases.ts +191 -4
  170. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  171. package/src/resources/extensions/gsd/auto-dispatch.ts +16 -6
  172. package/src/resources/extensions/gsd/auto-model-selection.ts +66 -5
  173. package/src/resources/extensions/gsd/auto-post-unit.ts +231 -15
  174. package/src/resources/extensions/gsd/auto-prompts.ts +13 -0
  175. package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
  176. package/src/resources/extensions/gsd/auto-verification.ts +129 -2
  177. package/src/resources/extensions/gsd/auto.ts +41 -2
  178. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -8
  179. package/src/resources/extensions/gsd/commands/catalog.ts +26 -1
  180. package/src/resources/extensions/gsd/commands/handlers/ops.ts +20 -0
  181. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +74 -9
  182. package/src/resources/extensions/gsd/commands-add-tests.ts +137 -0
  183. package/src/resources/extensions/gsd/commands-backlog.ts +182 -0
  184. package/src/resources/extensions/gsd/commands-do.ts +109 -0
  185. package/src/resources/extensions/gsd/commands-maintenance.ts +6 -6
  186. package/src/resources/extensions/gsd/commands-pr-branch.ts +234 -0
  187. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  188. package/src/resources/extensions/gsd/commands-session-report.ts +101 -0
  189. package/src/resources/extensions/gsd/commands-ship.ts +219 -0
  190. package/src/resources/extensions/gsd/db-writer.ts +3 -5
  191. package/src/resources/extensions/gsd/docs/preferences-reference.md +14 -1
  192. package/src/resources/extensions/gsd/git-service.ts +68 -0
  193. package/src/resources/extensions/gsd/graph-context.ts +212 -0
  194. package/src/resources/extensions/gsd/gsd-db.ts +788 -3
  195. package/src/resources/extensions/gsd/guided-flow.ts +32 -0
  196. package/src/resources/extensions/gsd/index.ts +18 -2
  197. package/src/resources/extensions/gsd/init-wizard.ts +3 -2
  198. package/src/resources/extensions/gsd/journal.ts +30 -0
  199. package/src/resources/extensions/gsd/md-importer.ts +3 -5
  200. package/src/resources/extensions/gsd/memory-store.ts +31 -62
  201. package/src/resources/extensions/gsd/metrics.ts +26 -0
  202. package/src/resources/extensions/gsd/milestone-validation-gates.ts +13 -14
  203. package/src/resources/extensions/gsd/native-git-bridge.ts +11 -12
  204. package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
  205. package/src/resources/extensions/gsd/preferences-models.ts +20 -3
  206. package/src/resources/extensions/gsd/preferences-types.ts +32 -0
  207. package/src/resources/extensions/gsd/preferences-validation.ts +107 -2
  208. package/src/resources/extensions/gsd/preferences.ts +28 -0
  209. package/src/resources/extensions/gsd/prompts/add-tests.md +35 -0
  210. package/src/resources/extensions/gsd/session-lock.ts +14 -2
  211. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +20 -1
  212. package/src/resources/extensions/gsd/state.ts +9 -2
  213. package/src/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
  214. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +7 -3
  215. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
  216. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
  217. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
  218. package/src/resources/extensions/gsd/tests/commands-backlog.test.ts +158 -0
  219. package/src/resources/extensions/gsd/tests/commands-do.test.ts +127 -0
  220. package/src/resources/extensions/gsd/tests/commands-pr-branch.test.ts +68 -0
  221. package/src/resources/extensions/gsd/tests/commands-session-report.test.ts +82 -0
  222. package/src/resources/extensions/gsd/tests/commands-ship.test.ts +71 -0
  223. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +14 -0
  224. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  225. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  226. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +154 -0
  227. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
  228. package/src/resources/extensions/gsd/tests/graph-context.test.ts +337 -0
  229. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  230. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +68 -1
  231. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -2
  232. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -3
  233. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +140 -0
  234. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  235. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +2 -1
  236. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +40 -1
  237. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +180 -0
  238. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -5
  239. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
  240. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +85 -0
  241. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +69 -0
  242. package/src/resources/extensions/gsd/tests/uok-flags.test.ts +39 -0
  243. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +70 -0
  244. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +85 -0
  245. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +35 -0
  246. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
  247. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +167 -0
  248. package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
  249. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
  250. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +223 -0
  251. package/src/resources/extensions/gsd/tools/complete-slice.ts +26 -0
  252. package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
  253. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +3 -11
  254. package/src/resources/extensions/gsd/triage-resolution.ts +2 -7
  255. package/src/resources/extensions/gsd/types.ts +1 -1
  256. package/src/resources/extensions/gsd/unit-ownership.ts +2 -2
  257. package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
  258. package/src/resources/extensions/gsd/uok/audit.ts +51 -0
  259. package/src/resources/extensions/gsd/uok/contracts.ts +135 -0
  260. package/src/resources/extensions/gsd/uok/execution-graph.ts +241 -0
  261. package/src/resources/extensions/gsd/uok/flags.ts +45 -0
  262. package/src/resources/extensions/gsd/uok/gate-runner.ts +146 -0
  263. package/src/resources/extensions/gsd/uok/gitops.ts +75 -0
  264. package/src/resources/extensions/gsd/uok/kernel.ts +105 -0
  265. package/src/resources/extensions/gsd/uok/loop-adapter.ts +162 -0
  266. package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
  267. package/src/resources/extensions/gsd/uok/plan-v2.ts +156 -0
  268. package/src/resources/extensions/gsd/workflow-logger.ts +25 -0
  269. package/src/resources/extensions/gsd/workflow-manifest.ts +9 -104
  270. package/src/resources/extensions/gsd/workflow-migration.ts +21 -29
  271. package/src/resources/extensions/gsd/workflow-projections.ts +8 -1
  272. package/src/resources/extensions/gsd/workflow-reconcile.ts +15 -15
  273. package/src/resources/extensions/ttsr/ttsr-manager.ts +10 -5
  274. /package/dist/web/standalone/.next/static/{YzIEI9sxJy4t5xgClF08g → bc2gRVFTgD7j--BsJE7vP}/_buildManifest.js +0 -0
  275. /package/dist/web/standalone/.next/static/{YzIEI9sxJy4t5xgClF08g → bc2gRVFTgD7j--BsJE7vP}/_ssgManifest.js +0 -0
@@ -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
+ });
@@ -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
  });