@united-workforce/cli 0.3.0 → 0.5.0

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 (319) hide show
  1. package/README.md +45 -11
  2. package/dist/.build-fingerprint +1 -0
  3. package/dist/__tests__/adapter-json-roundtrip.test.js +17 -7
  4. package/dist/__tests__/adapter-json-roundtrip.test.js.map +1 -1
  5. package/dist/__tests__/agent-resolution-llm-free.test.d.ts +2 -0
  6. package/dist/__tests__/agent-resolution-llm-free.test.d.ts.map +1 -0
  7. package/dist/__tests__/agent-resolution-llm-free.test.js +30 -0
  8. package/dist/__tests__/agent-resolution-llm-free.test.js.map +1 -0
  9. package/dist/__tests__/build-step-entry.test.d.ts +2 -0
  10. package/dist/__tests__/build-step-entry.test.d.ts.map +1 -0
  11. package/dist/__tests__/build-step-entry.test.js +173 -0
  12. package/dist/__tests__/build-step-entry.test.js.map +1 -0
  13. package/dist/__tests__/clear-thread-failed-attempts.test.d.ts +2 -0
  14. package/dist/__tests__/clear-thread-failed-attempts.test.d.ts.map +1 -0
  15. package/dist/__tests__/clear-thread-failed-attempts.test.js +93 -0
  16. package/dist/__tests__/clear-thread-failed-attempts.test.js.map +1 -0
  17. package/dist/__tests__/concurrency.test.d.ts +2 -0
  18. package/dist/__tests__/concurrency.test.d.ts.map +1 -0
  19. package/dist/__tests__/concurrency.test.js +196 -0
  20. package/dist/__tests__/concurrency.test.js.map +1 -0
  21. package/dist/__tests__/config.test.js +26 -302
  22. package/dist/__tests__/config.test.js.map +1 -1
  23. package/dist/__tests__/current-role.test.js +7 -6
  24. package/dist/__tests__/current-role.test.js.map +1 -1
  25. package/dist/__tests__/e2e-mock-agent.test.js +43 -30
  26. package/dist/__tests__/e2e-mock-agent.test.js.map +1 -1
  27. package/dist/__tests__/format-text-default.test.d.ts +2 -0
  28. package/dist/__tests__/format-text-default.test.d.ts.map +1 -0
  29. package/dist/__tests__/format-text-default.test.js +43 -0
  30. package/dist/__tests__/format-text-default.test.js.map +1 -0
  31. package/dist/__tests__/format-text-registry.test.d.ts +2 -0
  32. package/dist/__tests__/format-text-registry.test.d.ts.map +1 -0
  33. package/dist/__tests__/format-text-registry.test.js +158 -0
  34. package/dist/__tests__/format-text-registry.test.js.map +1 -0
  35. package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts +2 -0
  36. package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts.map +1 -0
  37. package/dist/__tests__/issue-180-workflow-ref-removed.test.js +40 -0
  38. package/dist/__tests__/issue-180-workflow-ref-removed.test.js.map +1 -0
  39. package/dist/__tests__/log-text-renderer.test.d.ts +2 -0
  40. package/dist/__tests__/log-text-renderer.test.d.ts.map +1 -0
  41. package/dist/__tests__/log-text-renderer.test.js +265 -0
  42. package/dist/__tests__/log-text-renderer.test.js.map +1 -0
  43. package/dist/__tests__/moderator-evaluate.test.js +9 -50
  44. package/dist/__tests__/moderator-evaluate.test.js.map +1 -1
  45. package/dist/__tests__/output-mapper-thread-list-startedat.test.d.ts +2 -0
  46. package/dist/__tests__/output-mapper-thread-list-startedat.test.d.ts.map +1 -0
  47. package/dist/__tests__/output-mapper-thread-list-startedat.test.js +102 -0
  48. package/dist/__tests__/output-mapper-thread-list-startedat.test.js.map +1 -0
  49. package/dist/__tests__/output-mapper-workflow-add.test.d.ts +2 -0
  50. package/dist/__tests__/output-mapper-workflow-add.test.d.ts.map +1 -0
  51. package/dist/__tests__/output-mapper-workflow-add.test.js +22 -0
  52. package/dist/__tests__/output-mapper-workflow-add.test.js.map +1 -0
  53. package/dist/__tests__/pid-recycling.test.d.ts +2 -0
  54. package/dist/__tests__/pid-recycling.test.d.ts.map +1 -0
  55. package/dist/__tests__/pid-recycling.test.js +273 -0
  56. package/dist/__tests__/pid-recycling.test.js.map +1 -0
  57. package/dist/__tests__/prompt.test.js +365 -2
  58. package/dist/__tests__/prompt.test.js.map +1 -1
  59. package/dist/__tests__/resolve-head-hash.test.js +12 -4
  60. package/dist/__tests__/resolve-head-hash.test.js.map +1 -1
  61. package/dist/__tests__/setup-agent-discovery.test.js +21 -30
  62. package/dist/__tests__/setup-agent-discovery.test.js.map +1 -1
  63. package/dist/__tests__/setup-complexity.test.js +2 -168
  64. package/dist/__tests__/setup-complexity.test.js.map +1 -1
  65. package/dist/__tests__/setup-no-llm.test.d.ts +2 -0
  66. package/dist/__tests__/setup-no-llm.test.d.ts.map +1 -0
  67. package/dist/__tests__/setup-no-llm.test.js +52 -0
  68. package/dist/__tests__/setup-no-llm.test.js.map +1 -0
  69. package/dist/__tests__/solve-issue-tea-worktree.test.js +27 -28
  70. package/dist/__tests__/solve-issue-tea-worktree.test.js.map +1 -1
  71. package/dist/__tests__/step-ask.test.d.ts +2 -0
  72. package/dist/__tests__/step-ask.test.d.ts.map +1 -0
  73. package/dist/__tests__/step-ask.test.js +507 -0
  74. package/dist/__tests__/step-ask.test.js.map +1 -0
  75. package/dist/__tests__/step-show-json.test.js +1 -0
  76. package/dist/__tests__/step-show-json.test.js.map +1 -1
  77. package/dist/__tests__/step-timing.test.js +2 -0
  78. package/dist/__tests__/step-timing.test.js.map +1 -1
  79. package/dist/__tests__/store-global-cas.test.js +2 -2
  80. package/dist/__tests__/store-global-cas.test.js.map +1 -1
  81. package/dist/__tests__/store-unified-threads.test.js +28 -26
  82. package/dist/__tests__/store-unified-threads.test.js.map +1 -1
  83. package/dist/__tests__/thread-cancel-status.test.js +25 -19
  84. package/dist/__tests__/thread-cancel-status.test.js.map +1 -1
  85. package/dist/__tests__/thread-cancel-text-renderer.test.d.ts +2 -0
  86. package/dist/__tests__/thread-cancel-text-renderer.test.d.ts.map +1 -0
  87. package/dist/__tests__/thread-cancel-text-renderer.test.js +110 -0
  88. package/dist/__tests__/thread-cancel-text-renderer.test.js.map +1 -0
  89. package/dist/__tests__/thread-list-filters.test.js +354 -17
  90. package/dist/__tests__/thread-list-filters.test.js.map +1 -1
  91. package/dist/__tests__/thread-list-template-ms-date.test.d.ts +2 -0
  92. package/dist/__tests__/thread-list-template-ms-date.test.d.ts.map +1 -0
  93. package/dist/__tests__/thread-list-template-ms-date.test.js +102 -0
  94. package/dist/__tests__/thread-list-template-ms-date.test.js.map +1 -0
  95. package/dist/__tests__/thread-list-workflow-corrupt.test.d.ts +2 -0
  96. package/dist/__tests__/thread-list-workflow-corrupt.test.d.ts.map +1 -0
  97. package/dist/__tests__/thread-list-workflow-corrupt.test.js +157 -0
  98. package/dist/__tests__/thread-list-workflow-corrupt.test.js.map +1 -0
  99. package/dist/__tests__/thread-poke.test.d.ts +2 -0
  100. package/dist/__tests__/thread-poke.test.d.ts.map +1 -0
  101. package/dist/__tests__/thread-poke.test.js +422 -0
  102. package/dist/__tests__/thread-poke.test.js.map +1 -0
  103. package/dist/__tests__/thread-read-xml-tags.test.js +10 -9
  104. package/dist/__tests__/thread-read-xml-tags.test.js.map +1 -1
  105. package/dist/__tests__/thread-resume.test.js +21 -15
  106. package/dist/__tests__/thread-resume.test.js.map +1 -1
  107. package/dist/__tests__/thread-show-status.test.js +17 -28
  108. package/dist/__tests__/thread-show-status.test.js.map +1 -1
  109. package/dist/__tests__/thread-start-cwd-cli.test.js +15 -3
  110. package/dist/__tests__/thread-start-cwd-cli.test.js.map +1 -1
  111. package/dist/__tests__/thread-stop-text-renderer.test.d.ts +2 -0
  112. package/dist/__tests__/thread-stop-text-renderer.test.d.ts.map +1 -0
  113. package/dist/__tests__/thread-stop-text-renderer.test.js +148 -0
  114. package/dist/__tests__/thread-stop-text-renderer.test.js.map +1 -0
  115. package/dist/__tests__/thread-suspend-step.test.js +13 -16
  116. package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
  117. package/dist/__tests__/thread-suspended-display.test.js +10 -22
  118. package/dist/__tests__/thread-suspended-display.test.js.map +1 -1
  119. package/dist/__tests__/thread-test-helpers.d.ts +7 -0
  120. package/dist/__tests__/thread-test-helpers.d.ts.map +1 -1
  121. package/dist/__tests__/thread-test-helpers.js +13 -0
  122. package/dist/__tests__/thread-test-helpers.js.map +1 -1
  123. package/dist/__tests__/thread.test.js +15 -13
  124. package/dist/__tests__/thread.test.js.map +1 -1
  125. package/dist/__tests__/validate-semantic.test.js +105 -23
  126. package/dist/__tests__/validate-semantic.test.js.map +1 -1
  127. package/dist/__tests__/workflow-list-recursive.test.d.ts +2 -0
  128. package/dist/__tests__/workflow-list-recursive.test.d.ts.map +1 -0
  129. package/dist/__tests__/workflow-list-recursive.test.js +286 -0
  130. package/dist/__tests__/workflow-list-recursive.test.js.map +1 -0
  131. package/dist/__tests__/workflow-resolution.test.js +46 -28
  132. package/dist/__tests__/workflow-resolution.test.js.map +1 -1
  133. package/dist/__tests__/workflow-show-resolution.test.d.ts +2 -0
  134. package/dist/__tests__/workflow-show-resolution.test.d.ts.map +1 -0
  135. package/dist/__tests__/workflow-show-resolution.test.js +213 -0
  136. package/dist/__tests__/workflow-show-resolution.test.js.map +1 -0
  137. package/dist/__tests__/workflow-validate.test.d.ts +2 -0
  138. package/dist/__tests__/workflow-validate.test.d.ts.map +1 -0
  139. package/dist/__tests__/workflow-validate.test.js +707 -0
  140. package/dist/__tests__/workflow-validate.test.js.map +1 -0
  141. package/dist/__tests__/write-envelope.test.d.ts +2 -0
  142. package/dist/__tests__/write-envelope.test.d.ts.map +1 -0
  143. package/dist/__tests__/write-envelope.test.js +201 -0
  144. package/dist/__tests__/write-envelope.test.js.map +1 -0
  145. package/dist/background/background.d.ts +22 -1
  146. package/dist/background/background.d.ts.map +1 -1
  147. package/dist/background/background.js +83 -6
  148. package/dist/background/background.js.map +1 -1
  149. package/dist/background/index.d.ts +1 -1
  150. package/dist/background/index.d.ts.map +1 -1
  151. package/dist/background/index.js +1 -1
  152. package/dist/background/index.js.map +1 -1
  153. package/dist/background/types.d.ts +1 -0
  154. package/dist/background/types.d.ts.map +1 -1
  155. package/dist/cli.js +120 -62
  156. package/dist/cli.js.map +1 -1
  157. package/dist/commands/config.d.ts +3 -1
  158. package/dist/commands/config.d.ts.map +1 -1
  159. package/dist/commands/config.js +17 -31
  160. package/dist/commands/config.js.map +1 -1
  161. package/dist/commands/prompt.d.ts.map +1 -1
  162. package/dist/commands/prompt.js +57 -31
  163. package/dist/commands/prompt.js.map +1 -1
  164. package/dist/commands/setup.d.ts +12 -39
  165. package/dist/commands/setup.d.ts.map +1 -1
  166. package/dist/commands/setup.js +72 -303
  167. package/dist/commands/setup.js.map +1 -1
  168. package/dist/commands/step.d.ts +44 -1
  169. package/dist/commands/step.d.ts.map +1 -1
  170. package/dist/commands/step.js +255 -11
  171. package/dist/commands/step.js.map +1 -1
  172. package/dist/commands/thread.d.ts +16 -3
  173. package/dist/commands/thread.d.ts.map +1 -1
  174. package/dist/commands/thread.js +423 -142
  175. package/dist/commands/thread.js.map +1 -1
  176. package/dist/commands/workflow.d.ts +9 -1
  177. package/dist/commands/workflow.d.ts.map +1 -1
  178. package/dist/commands/workflow.js +126 -6
  179. package/dist/commands/workflow.js.map +1 -1
  180. package/dist/concurrency/concurrency.d.ts +34 -0
  181. package/dist/concurrency/concurrency.d.ts.map +1 -0
  182. package/dist/concurrency/concurrency.js +216 -0
  183. package/dist/concurrency/concurrency.js.map +1 -0
  184. package/dist/concurrency/index.d.ts +3 -0
  185. package/dist/concurrency/index.d.ts.map +1 -0
  186. package/dist/concurrency/index.js +2 -0
  187. package/dist/concurrency/index.js.map +1 -0
  188. package/dist/concurrency/types.d.ts +19 -0
  189. package/dist/concurrency/types.d.ts.map +1 -0
  190. package/dist/concurrency/types.js +2 -0
  191. package/dist/concurrency/types.js.map +1 -0
  192. package/dist/format.d.ts +69 -2
  193. package/dist/format.d.ts.map +1 -1
  194. package/dist/format.js +198 -1
  195. package/dist/format.js.map +1 -1
  196. package/dist/moderator/__tests__/evaluate.test.js +31 -17
  197. package/dist/moderator/__tests__/evaluate.test.js.map +1 -1
  198. package/dist/moderator/evaluate.d.ts.map +1 -1
  199. package/dist/moderator/evaluate.js +4 -16
  200. package/dist/moderator/evaluate.js.map +1 -1
  201. package/dist/moderator/index.d.ts +1 -2
  202. package/dist/moderator/index.d.ts.map +1 -1
  203. package/dist/moderator/index.js +0 -1
  204. package/dist/moderator/index.js.map +1 -1
  205. package/dist/moderator/types.d.ts +6 -10
  206. package/dist/moderator/types.d.ts.map +1 -1
  207. package/dist/moderator/types.js +1 -3
  208. package/dist/moderator/types.js.map +1 -1
  209. package/dist/output-mappers.d.ts +122 -0
  210. package/dist/output-mappers.d.ts.map +1 -0
  211. package/dist/output-mappers.js +134 -0
  212. package/dist/output-mappers.js.map +1 -0
  213. package/dist/schemas.d.ts +6 -1
  214. package/dist/schemas.d.ts.map +1 -1
  215. package/dist/schemas.js +34 -5
  216. package/dist/schemas.js.map +1 -1
  217. package/dist/store.d.ts +28 -9
  218. package/dist/store.d.ts.map +1 -1
  219. package/dist/store.js +75 -16
  220. package/dist/store.js.map +1 -1
  221. package/dist/text-renderers.d.ts +30 -0
  222. package/dist/text-renderers.d.ts.map +1 -0
  223. package/dist/text-renderers.js +251 -0
  224. package/dist/text-renderers.js.map +1 -0
  225. package/dist/validate-semantic.d.ts.map +1 -1
  226. package/dist/validate-semantic.js +95 -61
  227. package/dist/validate-semantic.js.map +1 -1
  228. package/dist/validate.d.ts +6 -0
  229. package/dist/validate.d.ts.map +1 -1
  230. package/dist/validate.js +24 -0
  231. package/dist/validate.js.map +1 -1
  232. package/examples/brainstorm.yaml +130 -0
  233. package/examples/debate.yaml +169 -0
  234. package/examples/socratic-questioning.yaml +112 -0
  235. package/package.json +9 -10
  236. package/src/__tests__/adapter-json-roundtrip.test.ts +16 -7
  237. package/src/__tests__/agent-resolution-llm-free.test.ts +39 -0
  238. package/src/__tests__/build-step-entry.test.ts +203 -0
  239. package/src/__tests__/clear-thread-failed-attempts.test.ts +122 -0
  240. package/src/__tests__/concurrency.test.ts +266 -0
  241. package/src/__tests__/config.test.ts +33 -321
  242. package/src/__tests__/current-role.test.ts +7 -6
  243. package/src/__tests__/e2e-mock-agent.test.ts +65 -30
  244. package/src/__tests__/fixtures/e2e-count.workflow.yaml +1 -0
  245. package/src/__tests__/fixtures/e2e-linear.workflow.yaml +1 -0
  246. package/src/__tests__/fixtures/{e2e-mustache.workflow.yaml → e2e-liquid.workflow.yaml} +3 -2
  247. package/src/__tests__/fixtures/e2e-loop.workflow.yaml +1 -0
  248. package/src/__tests__/fixtures/e2e-suspend.mock.yaml +2 -2
  249. package/src/__tests__/fixtures/e2e-suspend.workflow.yaml +6 -10
  250. package/src/__tests__/format-text-default.test.ts +49 -0
  251. package/src/__tests__/format-text-registry.test.ts +173 -0
  252. package/src/__tests__/issue-180-workflow-ref-removed.test.ts +43 -0
  253. package/src/__tests__/log-text-renderer.test.ts +294 -0
  254. package/src/__tests__/moderator-evaluate.test.ts +9 -52
  255. package/src/__tests__/output-mapper-thread-list-startedat.test.ts +124 -0
  256. package/src/__tests__/output-mapper-workflow-add.test.ts +24 -0
  257. package/src/__tests__/pid-recycling.test.ts +329 -0
  258. package/src/__tests__/prompt.test.ts +443 -2
  259. package/src/__tests__/resolve-head-hash.test.ts +11 -4
  260. package/src/__tests__/setup-agent-discovery.test.ts +26 -51
  261. package/src/__tests__/setup-complexity.test.ts +1 -203
  262. package/src/__tests__/setup-no-llm.test.ts +68 -0
  263. package/src/__tests__/solve-issue-tea-worktree.test.ts +27 -31
  264. package/src/__tests__/step-ask.test.ts +677 -0
  265. package/src/__tests__/step-show-json.test.ts +1 -0
  266. package/src/__tests__/step-timing.test.ts +2 -0
  267. package/src/__tests__/store-global-cas.test.ts +2 -2
  268. package/src/__tests__/store-unified-threads.test.ts +30 -27
  269. package/src/__tests__/thread-cancel-status.test.ts +27 -20
  270. package/src/__tests__/thread-cancel-text-renderer.test.ts +125 -0
  271. package/src/__tests__/thread-list-filters.test.ts +443 -17
  272. package/src/__tests__/thread-list-template-ms-date.test.ts +110 -0
  273. package/src/__tests__/thread-list-workflow-corrupt.test.ts +198 -0
  274. package/src/__tests__/thread-poke.test.ts +554 -0
  275. package/src/__tests__/thread-read-xml-tags.test.ts +9 -11
  276. package/src/__tests__/thread-resume.test.ts +20 -15
  277. package/src/__tests__/thread-show-status.test.ts +17 -29
  278. package/src/__tests__/thread-start-cwd-cli.test.ts +15 -3
  279. package/src/__tests__/thread-stop-text-renderer.test.ts +168 -0
  280. package/src/__tests__/thread-suspend-step.test.ts +13 -16
  281. package/src/__tests__/thread-suspended-display.test.ts +10 -22
  282. package/src/__tests__/thread-test-helpers.ts +15 -1
  283. package/src/__tests__/thread.test.ts +14 -14
  284. package/src/__tests__/validate-semantic.test.ts +118 -33
  285. package/src/__tests__/workflow-list-recursive.test.ts +370 -0
  286. package/src/__tests__/workflow-resolution.test.ts +48 -29
  287. package/src/__tests__/workflow-show-resolution.test.ts +286 -0
  288. package/src/__tests__/workflow-validate.test.ts +828 -0
  289. package/src/__tests__/write-envelope.test.ts +257 -0
  290. package/src/background/background.ts +88 -6
  291. package/src/background/index.ts +2 -0
  292. package/src/background/types.ts +1 -0
  293. package/src/cli.ts +184 -77
  294. package/src/commands/config.ts +16 -33
  295. package/src/commands/prompt.ts +57 -31
  296. package/src/commands/setup.ts +80 -358
  297. package/src/commands/step.ts +339 -12
  298. package/src/commands/thread.ts +511 -171
  299. package/src/commands/workflow.ts +155 -4
  300. package/src/concurrency/concurrency.ts +245 -0
  301. package/src/concurrency/index.ts +10 -0
  302. package/src/concurrency/types.ts +19 -0
  303. package/src/format.ts +282 -2
  304. package/src/moderator/__tests__/evaluate.test.ts +34 -17
  305. package/src/moderator/evaluate.ts +5 -17
  306. package/src/moderator/index.ts +1 -6
  307. package/src/moderator/types.ts +6 -14
  308. package/src/output-mappers.ts +254 -0
  309. package/src/schemas.ts +51 -5
  310. package/src/store.ts +86 -20
  311. package/src/text-renderers.ts +355 -0
  312. package/src/validate-semantic.ts +125 -73
  313. package/src/validate.ts +27 -0
  314. package/dist/__tests__/setup-validate.test.d.ts +0 -2
  315. package/dist/__tests__/setup-validate.test.d.ts.map +0 -1
  316. package/dist/__tests__/setup-validate.test.js +0 -108
  317. package/dist/__tests__/setup-validate.test.js.map +0 -1
  318. package/src/__tests__/setup-validate.test.ts +0 -148
  319. /package/src/__tests__/fixtures/{e2e-mustache.mock.yaml → e2e-liquid.mock.yaml} +0 -0
@@ -1,17 +1,12 @@
1
1
  import { mkdirSync, writeFileSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
- import { afterEach, describe, expect, test, vi } from "vitest";
4
+ import { describe, expect, test } from "vitest";
5
5
  import {
6
6
  _discoverAgents,
7
7
  _isBackspace,
8
8
  _isTerminator,
9
9
  _parseWhichOutput,
10
- _printModelMenu,
11
- _printProviderMenu,
12
- _printValidationResult,
13
- _resolveModelChoice,
14
- _resolveProviderChoice,
15
10
  _searchPathDirs,
16
11
  } from "../commands/setup.js";
17
12
 
@@ -172,203 +167,6 @@ describe("_isBackspace", () => {
172
167
  });
173
168
  });
174
169
 
175
- // ──────────────────────────────────────────────────────────────────────────────
176
- // 3a. _printProviderMenu
177
- // ──────────────────────────────────────────────────────────────────────────────
178
-
179
- describe("_printProviderMenu", () => {
180
- afterEach(() => {
181
- vi.restoreAllMocks();
182
- });
183
-
184
- const providers = [
185
- { name: "openai", label: "OpenAI", baseUrl: "https://api.openai.com/v1" },
186
- { name: "xai", label: "xAI", baseUrl: "https://api.x.ai/v1" },
187
- ] as const;
188
-
189
- test("prints correct number of lines (one per provider + custom)", () => {
190
- const lines: string[] = [];
191
- vi.spyOn(console, "log").mockImplementation((msg: string) => {
192
- lines.push(msg);
193
- });
194
- _printProviderMenu(providers);
195
- // 2 providers + 1 custom = 3 lines
196
- expect(lines.length).toBe(3);
197
- });
198
-
199
- test("custom option number = providers.length + 1", () => {
200
- const lines: string[] = [];
201
- vi.spyOn(console, "log").mockImplementation((msg: string) => {
202
- lines.push(msg);
203
- });
204
- _printProviderMenu(providers);
205
- const lastLine = lines[lines.length - 1] ?? "";
206
- expect(lastLine).toMatch(/3\)/);
207
- });
208
-
209
- test("each provider line contains its label and baseUrl", () => {
210
- const lines: string[] = [];
211
- vi.spyOn(console, "log").mockImplementation((msg: string) => {
212
- lines.push(msg);
213
- });
214
- _printProviderMenu(providers);
215
- expect(lines[0]).toContain("OpenAI");
216
- expect(lines[0]).toContain("https://api.openai.com/v1");
217
- expect(lines[1]).toContain("xAI");
218
- expect(lines[1]).toContain("https://api.x.ai/v1");
219
- });
220
- });
221
-
222
- // ──────────────────────────────────────────────────────────────────────────────
223
- // 3b. _resolveProviderChoice
224
- // ──────────────────────────────────────────────────────────────────────────────
225
-
226
- describe("_resolveProviderChoice", () => {
227
- const providers = [
228
- { name: "openai", label: "OpenAI", baseUrl: "https://api.openai.com/v1" },
229
- { name: "xai", label: "xAI", baseUrl: "https://api.x.ai/v1" },
230
- { name: "deepseek", label: "DeepSeek", baseUrl: "https://api.deepseek.com/v1" },
231
- ] as const;
232
-
233
- test("valid index 1 returns first provider", () => {
234
- const result = _resolveProviderChoice("1", providers);
235
- expect(result).toEqual({ providerName: "openai", baseUrl: "https://api.openai.com/v1" });
236
- });
237
-
238
- test("valid index N (last preset) returns last provider", () => {
239
- const result = _resolveProviderChoice("3", providers);
240
- expect(result).toEqual({ providerName: "deepseek", baseUrl: "https://api.deepseek.com/v1" });
241
- });
242
-
243
- test("index providers.length+1 (custom) returns null", () => {
244
- const result = _resolveProviderChoice("4", providers);
245
- expect(result).toBeNull();
246
- });
247
-
248
- test("non-numeric string returns null", () => {
249
- expect(_resolveProviderChoice("abc", providers)).toBeNull();
250
- });
251
-
252
- test("0 returns null (out of range)", () => {
253
- expect(_resolveProviderChoice("0", providers)).toBeNull();
254
- });
255
-
256
- test("N+2 returns null (out of range)", () => {
257
- expect(_resolveProviderChoice("5", providers)).toBeNull();
258
- });
259
-
260
- test("negative number returns null", () => {
261
- expect(_resolveProviderChoice("-1", providers)).toBeNull();
262
- });
263
- });
264
-
265
- // ──────────────────────────────────────────────────────────────────────────────
266
- // 3c. _resolveModelChoice
267
- // ──────────────────────────────────────────────────────────────────────────────
268
-
269
- describe("_resolveModelChoice", () => {
270
- test("numeric input within range returns model at that index", () => {
271
- expect(_resolveModelChoice("2", ["a", "b", "c"])).toBe("b");
272
- });
273
-
274
- test("numeric input out of range returns input as-is", () => {
275
- expect(_resolveModelChoice("5", ["a"])).toBe("5");
276
- });
277
-
278
- test("non-numeric input returns input as-is", () => {
279
- expect(_resolveModelChoice("gpt-4o", ["a", "b"])).toBe("gpt-4o");
280
- });
281
-
282
- test("numeric input 1 returns first model", () => {
283
- expect(_resolveModelChoice("1", ["alpha", "beta"])).toBe("alpha");
284
- });
285
-
286
- test("empty models list with numeric input returns input as-is", () => {
287
- expect(_resolveModelChoice("1", [])).toBe("1");
288
- });
289
- });
290
-
291
- // ──────────────────────────────────────────────────────────────────────────────
292
- // 3d. _printModelMenu
293
- // ──────────────────────────────────────────────────────────────────────────────
294
-
295
- describe("_printModelMenu", () => {
296
- afterEach(() => {
297
- vi.restoreAllMocks();
298
- });
299
-
300
- test("prints all models — each model name appears in output", () => {
301
- const output: string[] = [];
302
- vi.spyOn(console, "log").mockImplementation((msg: string) => {
303
- output.push(msg);
304
- });
305
- const models = ["model-a", "model-b", "model-c"];
306
- _printModelMenu(models, 100);
307
- const combined = output.join("\n");
308
- for (const m of models) {
309
- expect(combined).toContain(m);
310
- }
311
- });
312
-
313
- test("single column when termCols is very small", () => {
314
- const output: string[] = [];
315
- vi.spyOn(console, "log").mockImplementation((msg: string) => {
316
- output.push(msg);
317
- });
318
- _printModelMenu(["a", "b", "c"], 1);
319
- // Each model on its own row → 3 lines
320
- expect(output.length).toBe(3);
321
- });
322
-
323
- test("wide terminal fits multiple columns", () => {
324
- const output: string[] = [];
325
- vi.spyOn(console, "log").mockImplementation((msg: string) => {
326
- output.push(msg);
327
- });
328
- const models = Array.from({ length: 6 }, (_, i) => `m${i}`);
329
- _printModelMenu(models, 200);
330
- // With wide terminal and short names, should fit in fewer than 6 rows
331
- expect(output.length).toBeLessThan(6);
332
- });
333
- });
334
-
335
- // ──────────────────────────────────────────────────────────────────────────────
336
- // 3e. _printValidationResult
337
- // ──────────────────────────────────────────────────────────────────────────────
338
-
339
- describe("_printValidationResult", () => {
340
- afterEach(() => {
341
- vi.restoreAllMocks();
342
- });
343
-
344
- test("ok=true prints success message containing '✓'", () => {
345
- const lines: string[] = [];
346
- vi.spyOn(console, "log").mockImplementation((msg: string) => {
347
- lines.push(msg);
348
- });
349
- _printValidationResult({ ok: true, error: null });
350
- expect(lines.join("\n")).toContain("✓");
351
- });
352
-
353
- test("ok=false prints warning message containing '⚠'", () => {
354
- const lines: string[] = [];
355
- vi.spyOn(console, "log").mockImplementation((msg: string) => {
356
- lines.push(msg);
357
- });
358
- _printValidationResult({ ok: false, error: "HTTP 401" });
359
- expect(lines.join("\n")).toContain("⚠");
360
- });
361
-
362
- test("ok=false includes the error string in output", () => {
363
- const lines: string[] = [];
364
- vi.spyOn(console, "log").mockImplementation((msg: string) => {
365
- lines.push(msg);
366
- });
367
- _printValidationResult({ ok: false, error: "HTTP 401" });
368
- expect(lines.join("\n")).toContain("HTTP 401");
369
- });
370
- });
371
-
372
170
  // ──────────────────────────────────────────────────────────────────────────────
373
171
  // 4. Regression
374
172
  // ──────────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,68 @@
1
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, describe, expect, test } from "vitest";
5
+ import { parse } from "yaml";
6
+ import { cmdSetup } from "../commands/setup.js";
7
+
8
+ describe("cmdSetup — non-interactive, no LLM args (issue #143)", () => {
9
+ let tempDir: string;
10
+ afterEach(() => {
11
+ if (tempDir) rmSync(tempDir, { recursive: true, force: true });
12
+ });
13
+
14
+ test("writes config.yaml with only agents + defaultAgent", async () => {
15
+ tempDir = mkdtempSync(join(tmpdir(), "uwf-setup-"));
16
+ await cmdSetup({ agent: "hermes", storageRoot: tempDir });
17
+ const cfg = parse(readFileSync(join(tempDir, "config.yaml"), "utf8")) as Record<
18
+ string,
19
+ unknown
20
+ >;
21
+ expect(cfg.defaultAgent).toBe("hermes");
22
+ expect(cfg.agents).toBeDefined();
23
+ expect(cfg.providers).toBeUndefined();
24
+ expect(cfg.models).toBeUndefined();
25
+ expect(cfg.defaultModel).toBeUndefined();
26
+ expect(cfg.modelOverrides).toBeUndefined();
27
+ });
28
+
29
+ test("preserves existing agentOverrides on rewrite", async () => {
30
+ tempDir = mkdtempSync(join(tmpdir(), "uwf-setup-"));
31
+ writeFileSync(
32
+ join(tempDir, "config.yaml"),
33
+ "agents:\n hermes: { command: uwf-hermes, args: [] }\ndefaultAgent: hermes\nagentOverrides:\n solve-issue:\n coder: claude-code\n",
34
+ "utf8",
35
+ );
36
+ await cmdSetup({ agent: "hermes", storageRoot: tempDir });
37
+ const cfg = parse(readFileSync(join(tempDir, "config.yaml"), "utf8")) as Record<
38
+ string,
39
+ unknown
40
+ >;
41
+ expect(cfg.agentOverrides).toEqual({ "solve-issue": { coder: "claude-code" } });
42
+ });
43
+
44
+ test("creates a default agent entry when missing", async () => {
45
+ tempDir = mkdtempSync(join(tmpdir(), "uwf-setup-"));
46
+ await cmdSetup({ agent: "claude-code", storageRoot: tempDir });
47
+ const cfg = parse(readFileSync(join(tempDir, "config.yaml"), "utf8")) as Record<
48
+ string,
49
+ unknown
50
+ >;
51
+ expect(cfg.defaultAgent).toBe("claude-code");
52
+ const agents = cfg.agents as Record<string, unknown>;
53
+ expect(agents["claude-code"]).toEqual({ command: "uwf-claude-code", args: [] });
54
+ });
55
+ });
56
+
57
+ describe("cmdSetup public surface — provider/model helpers removed (issue #143)", () => {
58
+ test("module does not export validateModel / provider menus / model menus", async () => {
59
+ const mod = (await import("../commands/setup.js")) as Record<string, unknown>;
60
+ expect(mod.validateModel).toBeUndefined();
61
+ expect(mod.resolvePresetBaseUrl).toBeUndefined();
62
+ expect(mod._printProviderMenu).toBeUndefined();
63
+ expect(mod._resolveProviderChoice).toBeUndefined();
64
+ expect(mod._printModelMenu).toBeUndefined();
65
+ expect(mod._resolveModelChoice).toBeUndefined();
66
+ expect(mod._printValidationResult).toBeUndefined();
67
+ });
68
+ });
@@ -13,7 +13,9 @@ import { parse } from "yaml";
13
13
  * which fixes the "path segment [0] is empty" error in worktree directories.
14
14
  */
15
15
 
16
- describe("solve-issue workflow: Gitea API PR creation", () => {
16
+ // Skip: pure workflow YAML prose content assertions — procedure text changes
17
+ // break these without indicating real bugs. See #299 discussion.
18
+ describe.skip("solve-issue workflow: Gitea API PR creation", () => {
17
19
  // Navigate up from packages/cli/src/__tests__ to repo root
18
20
  const workflowPath = join(
19
21
  dirname(fileURLToPath(import.meta.url)),
@@ -21,11 +23,11 @@ describe("solve-issue workflow: Gitea API PR creation", () => {
21
23
  "..",
22
24
  "..",
23
25
  "..",
24
- ".workflows",
26
+ "examples",
25
27
  "solve-issue.yaml",
26
28
  );
27
29
 
28
- test("committer procedure should use curl API instead of tea pr create", async () => {
30
+ test("committer procedure should create PR via tea pr create", async () => {
29
31
  const yamlContent = await readFile(workflowPath, "utf-8");
30
32
  const workflow = parse(yamlContent) as WorkflowPayload;
31
33
 
@@ -33,25 +35,22 @@ describe("solve-issue workflow: Gitea API PR creation", () => {
33
35
  const committerProcedure = workflow.roles.committer?.procedure;
34
36
  expect(committerProcedure).toBeDefined();
35
37
 
36
- // Verify the procedure uses curl API, not tea pr create
37
- expect(committerProcedure).toContain("curl");
38
- expect(committerProcedure).toContain("api/v1/repos");
39
- expect(committerProcedure).toContain("/pulls");
40
-
41
- // Verify it explicitly warns against tea pr create
42
- expect(committerProcedure).toMatch(/do NOT use.*tea pr create/i);
38
+ // Verify the procedure uses tea pr create for PR creation
39
+ expect(committerProcedure).toContain("tea pr create");
40
+ expect(committerProcedure).toContain("git push");
41
+ expect(committerProcedure).toContain("Fixes #N");
43
42
  });
44
43
 
45
- test("committer procedure should reference repoRemote from task prompt", async () => {
44
+ test("committer procedure should extract owner/repo from git remote", async () => {
46
45
  const yamlContent = await readFile(workflowPath, "utf-8");
47
46
  const workflow = parse(yamlContent) as WorkflowPayload;
48
47
 
49
48
  const committerProcedure = workflow.roles.committer?.procedure;
50
49
  expect(committerProcedure).toBeDefined();
51
50
 
52
- // Verify the procedure mentions repoRemote is provided in task prompt
53
- expect(committerProcedure).toMatch(/repo remote.*provided.*task prompt/i);
54
- expect(committerProcedure).toMatch(/owner\/repo/i);
51
+ // Verify the procedure extracts owner/repo from remote
52
+ expect(committerProcedure).toContain("git remote get-url origin");
53
+ expect(committerProcedure).toContain("hook_failed");
55
54
  });
56
55
 
57
56
  test("committer procedure should include error handling for curl failures", async () => {
@@ -100,45 +99,42 @@ describe("solve-issue workflow: Gitea API PR creation", () => {
100
99
  expect(committedVariant.required).toContain("$status");
101
100
  });
102
101
 
103
- test("developer procedure should include mandatory verification step", async () => {
102
+ test("developer procedure should include worktree setup", async () => {
104
103
  const yamlContent = await readFile(workflowPath, "utf-8");
105
104
  const workflow = parse(yamlContent) as WorkflowPayload;
106
105
 
107
106
  const developerProcedure = workflow.roles.developer?.procedure;
108
107
  expect(developerProcedure).toBeDefined();
109
108
 
110
- // Verify the procedure includes mandatory verification step
111
- expect(developerProcedure).toContain("MANDATORY VERIFICATION");
112
- expect(developerProcedure).toContain("git branch --show-current");
113
- expect(developerProcedure).toContain("git status");
114
- expect(developerProcedure).toMatch(/ls -la|verify.*exist/i);
109
+ // Verify the procedure includes worktree setup
110
+ expect(developerProcedure).toContain("IMPORTANT");
111
+ expect(developerProcedure).toContain("git worktree add");
112
+ expect(developerProcedure).toContain("pnpm install");
115
113
  });
116
114
 
117
- test("reviewer procedure should enforce worktree path verification", async () => {
115
+ test("reviewer procedure should verify branch and run checks", async () => {
118
116
  const yamlContent = await readFile(workflowPath, "utf-8");
119
117
  const workflow = parse(yamlContent) as WorkflowPayload;
120
118
 
121
119
  const reviewerProcedure = workflow.roles.reviewer?.procedure;
122
120
  expect(reviewerProcedure).toBeDefined();
123
121
 
124
- // Verify the procedure includes critical enforcement
125
- expect(reviewerProcedure).toContain("CRITICAL");
126
- expect(reviewerProcedure).toMatch(/cd.*pwd/);
127
- expect(reviewerProcedure).toContain(
128
- "Do NOT report results without running the actual commands",
129
- );
122
+ // Verify the procedure includes branch verification and build checks
123
+ expect(reviewerProcedure).toContain("git branch --show-current");
124
+ expect(reviewerProcedure).toContain("pnpm run build");
125
+ expect(reviewerProcedure).toContain("pnpm run check");
130
126
  });
131
127
 
132
- test("developer procedure should include test debugging escalation", async () => {
128
+ test("developer procedure should include changeset and failure handling", async () => {
133
129
  const yamlContent = await readFile(workflowPath, "utf-8");
134
130
  const workflow = parse(yamlContent) as WorkflowPayload;
135
131
 
136
132
  const developerProcedure = workflow.roles.developer?.procedure;
137
133
  expect(developerProcedure).toBeDefined();
138
134
 
139
- // Verify the procedure includes test failure guidance
140
- expect(developerProcedure).toMatch(/tests fail.*first run/i);
141
- expect(developerProcedure).toMatch(/3 test cycles|after 3 attempts/i);
135
+ // Verify the procedure includes changeset requirement and failure path
136
+ expect(developerProcedure).toContain(".changeset/");
142
137
  expect(developerProcedure).toContain("$status=failed");
138
+ expect(developerProcedure).toContain("pnpm test");
143
139
  });
144
140
  });