@united-workforce/cli 0.2.1-rc.9 → 0.4.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 (219) hide show
  1. package/README.md +15 -8
  2. package/dist/__tests__/adapter-json-roundtrip.test.js +1 -1
  3. package/dist/__tests__/adapter-json-roundtrip.test.js.map +1 -1
  4. package/dist/__tests__/agent-resolution-llm-free.test.d.ts +2 -0
  5. package/dist/__tests__/agent-resolution-llm-free.test.d.ts.map +1 -0
  6. package/dist/__tests__/agent-resolution-llm-free.test.js +30 -0
  7. package/dist/__tests__/agent-resolution-llm-free.test.js.map +1 -0
  8. package/dist/__tests__/build-step-entry.test.d.ts +2 -0
  9. package/dist/__tests__/build-step-entry.test.d.ts.map +1 -0
  10. package/dist/__tests__/build-step-entry.test.js +173 -0
  11. package/dist/__tests__/build-step-entry.test.js.map +1 -0
  12. package/dist/__tests__/clear-thread-failed-attempts.test.d.ts +2 -0
  13. package/dist/__tests__/clear-thread-failed-attempts.test.d.ts.map +1 -0
  14. package/dist/__tests__/clear-thread-failed-attempts.test.js +93 -0
  15. package/dist/__tests__/clear-thread-failed-attempts.test.js.map +1 -0
  16. package/dist/__tests__/config.test.js +26 -302
  17. package/dist/__tests__/config.test.js.map +1 -1
  18. package/dist/__tests__/current-role.test.js +7 -6
  19. package/dist/__tests__/current-role.test.js.map +1 -1
  20. package/dist/__tests__/e2e-mock-agent.test.js +20 -23
  21. package/dist/__tests__/e2e-mock-agent.test.js.map +1 -1
  22. package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts +2 -0
  23. package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts.map +1 -0
  24. package/dist/__tests__/issue-180-workflow-ref-removed.test.js +40 -0
  25. package/dist/__tests__/issue-180-workflow-ref-removed.test.js.map +1 -0
  26. package/dist/__tests__/moderator-evaluate.test.js +9 -50
  27. package/dist/__tests__/moderator-evaluate.test.js.map +1 -1
  28. package/dist/__tests__/pid-recycling.test.d.ts +2 -0
  29. package/dist/__tests__/pid-recycling.test.d.ts.map +1 -0
  30. package/dist/__tests__/pid-recycling.test.js +271 -0
  31. package/dist/__tests__/pid-recycling.test.js.map +1 -0
  32. package/dist/__tests__/prompt.test.js +321 -0
  33. package/dist/__tests__/prompt.test.js.map +1 -1
  34. package/dist/__tests__/resolve-head-hash.test.js +4 -4
  35. package/dist/__tests__/resolve-head-hash.test.js.map +1 -1
  36. package/dist/__tests__/setup-agent-discovery.test.js +21 -30
  37. package/dist/__tests__/setup-agent-discovery.test.js.map +1 -1
  38. package/dist/__tests__/setup-complexity.test.js +2 -168
  39. package/dist/__tests__/setup-complexity.test.js.map +1 -1
  40. package/dist/__tests__/setup-no-llm.test.d.ts +2 -0
  41. package/dist/__tests__/setup-no-llm.test.d.ts.map +1 -0
  42. package/dist/__tests__/setup-no-llm.test.js +52 -0
  43. package/dist/__tests__/setup-no-llm.test.js.map +1 -0
  44. package/dist/__tests__/solve-issue-tea-worktree.test.js +24 -27
  45. package/dist/__tests__/solve-issue-tea-worktree.test.js.map +1 -1
  46. package/dist/__tests__/step-ask.test.d.ts +2 -0
  47. package/dist/__tests__/step-ask.test.d.ts.map +1 -0
  48. package/dist/__tests__/step-ask.test.js +499 -0
  49. package/dist/__tests__/step-ask.test.js.map +1 -0
  50. package/dist/__tests__/step-show-json.test.js +1 -0
  51. package/dist/__tests__/step-show-json.test.js.map +1 -1
  52. package/dist/__tests__/step-timing.test.js +2 -0
  53. package/dist/__tests__/step-timing.test.js.map +1 -1
  54. package/dist/__tests__/store-global-cas.test.js +2 -2
  55. package/dist/__tests__/store-global-cas.test.js.map +1 -1
  56. package/dist/__tests__/store-unified-threads.test.js +9 -9
  57. package/dist/__tests__/store-unified-threads.test.js.map +1 -1
  58. package/dist/__tests__/thread-cancel-status.test.js +6 -6
  59. package/dist/__tests__/thread-cancel-status.test.js.map +1 -1
  60. package/dist/__tests__/thread-list-filters.test.js +344 -9
  61. package/dist/__tests__/thread-list-filters.test.js.map +1 -1
  62. package/dist/__tests__/thread-poke.test.d.ts +2 -0
  63. package/dist/__tests__/thread-poke.test.d.ts.map +1 -0
  64. package/dist/__tests__/thread-poke.test.js +412 -0
  65. package/dist/__tests__/thread-poke.test.js.map +1 -0
  66. package/dist/__tests__/thread-resume.test.js +10 -14
  67. package/dist/__tests__/thread-resume.test.js.map +1 -1
  68. package/dist/__tests__/thread-show-status.test.js +17 -28
  69. package/dist/__tests__/thread-show-status.test.js.map +1 -1
  70. package/dist/__tests__/thread-suspend-step.test.js +8 -14
  71. package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
  72. package/dist/__tests__/thread-suspended-display.test.js +10 -22
  73. package/dist/__tests__/thread-suspended-display.test.js.map +1 -1
  74. package/dist/__tests__/thread.test.js +4 -4
  75. package/dist/__tests__/thread.test.js.map +1 -1
  76. package/dist/__tests__/validate-semantic.test.js +49 -21
  77. package/dist/__tests__/validate-semantic.test.js.map +1 -1
  78. package/dist/__tests__/workflow-list-recursive.test.d.ts +2 -0
  79. package/dist/__tests__/workflow-list-recursive.test.d.ts.map +1 -0
  80. package/dist/__tests__/workflow-list-recursive.test.js +283 -0
  81. package/dist/__tests__/workflow-list-recursive.test.js.map +1 -0
  82. package/dist/__tests__/workflow-resolution.test.js +36 -21
  83. package/dist/__tests__/workflow-resolution.test.js.map +1 -1
  84. package/dist/__tests__/workflow-show-resolution.test.d.ts +2 -0
  85. package/dist/__tests__/workflow-show-resolution.test.d.ts.map +1 -0
  86. package/dist/__tests__/workflow-show-resolution.test.js +210 -0
  87. package/dist/__tests__/workflow-show-resolution.test.js.map +1 -0
  88. package/dist/__tests__/workflow-validate.test.d.ts +2 -0
  89. package/dist/__tests__/workflow-validate.test.d.ts.map +1 -0
  90. package/dist/__tests__/workflow-validate.test.js +687 -0
  91. package/dist/__tests__/workflow-validate.test.js.map +1 -0
  92. package/dist/background/background.d.ts +22 -1
  93. package/dist/background/background.d.ts.map +1 -1
  94. package/dist/background/background.js +83 -6
  95. package/dist/background/background.js.map +1 -1
  96. package/dist/background/index.d.ts +1 -1
  97. package/dist/background/index.d.ts.map +1 -1
  98. package/dist/background/index.js +1 -1
  99. package/dist/background/index.js.map +1 -1
  100. package/dist/background/types.d.ts +1 -0
  101. package/dist/background/types.d.ts.map +1 -1
  102. package/dist/cli.js +66 -31
  103. package/dist/cli.js.map +1 -1
  104. package/dist/commands/config.d.ts +3 -1
  105. package/dist/commands/config.d.ts.map +1 -1
  106. package/dist/commands/config.js +7 -33
  107. package/dist/commands/config.js.map +1 -1
  108. package/dist/commands/prompt.d.ts.map +1 -1
  109. package/dist/commands/prompt.js +15 -2
  110. package/dist/commands/prompt.js.map +1 -1
  111. package/dist/commands/setup.d.ts +7 -39
  112. package/dist/commands/setup.d.ts.map +1 -1
  113. package/dist/commands/setup.js +27 -302
  114. package/dist/commands/setup.js.map +1 -1
  115. package/dist/commands/step.d.ts +44 -1
  116. package/dist/commands/step.d.ts.map +1 -1
  117. package/dist/commands/step.js +255 -11
  118. package/dist/commands/step.js.map +1 -1
  119. package/dist/commands/thread.d.ts +16 -3
  120. package/dist/commands/thread.d.ts.map +1 -1
  121. package/dist/commands/thread.js +379 -140
  122. package/dist/commands/thread.js.map +1 -1
  123. package/dist/commands/workflow.d.ts +9 -1
  124. package/dist/commands/workflow.d.ts.map +1 -1
  125. package/dist/commands/workflow.js +130 -6
  126. package/dist/commands/workflow.js.map +1 -1
  127. package/dist/moderator/__tests__/evaluate.test.js +31 -17
  128. package/dist/moderator/__tests__/evaluate.test.js.map +1 -1
  129. package/dist/moderator/evaluate.d.ts.map +1 -1
  130. package/dist/moderator/evaluate.js +4 -16
  131. package/dist/moderator/evaluate.js.map +1 -1
  132. package/dist/moderator/index.d.ts +1 -2
  133. package/dist/moderator/index.d.ts.map +1 -1
  134. package/dist/moderator/index.js +0 -1
  135. package/dist/moderator/index.js.map +1 -1
  136. package/dist/moderator/types.d.ts +6 -10
  137. package/dist/moderator/types.d.ts.map +1 -1
  138. package/dist/moderator/types.js +1 -3
  139. package/dist/moderator/types.js.map +1 -1
  140. package/dist/schemas.d.ts +2 -0
  141. package/dist/schemas.d.ts.map +1 -1
  142. package/dist/schemas.js +5 -3
  143. package/dist/schemas.js.map +1 -1
  144. package/dist/store.d.ts +28 -9
  145. package/dist/store.d.ts.map +1 -1
  146. package/dist/store.js +75 -16
  147. package/dist/store.js.map +1 -1
  148. package/dist/validate-semantic.d.ts.map +1 -1
  149. package/dist/validate-semantic.js +83 -66
  150. package/dist/validate-semantic.js.map +1 -1
  151. package/dist/validate.d.ts +6 -0
  152. package/dist/validate.d.ts.map +1 -1
  153. package/dist/validate.js +24 -0
  154. package/dist/validate.js.map +1 -1
  155. package/package.json +8 -10
  156. package/src/__tests__/adapter-json-roundtrip.test.ts +1 -1
  157. package/src/__tests__/agent-resolution-llm-free.test.ts +39 -0
  158. package/src/__tests__/build-step-entry.test.ts +203 -0
  159. package/src/__tests__/clear-thread-failed-attempts.test.ts +122 -0
  160. package/src/__tests__/config.test.ts +33 -321
  161. package/src/__tests__/current-role.test.ts +7 -6
  162. package/src/__tests__/e2e-mock-agent.test.ts +20 -23
  163. package/src/__tests__/fixtures/e2e-count.workflow.yaml +1 -0
  164. package/src/__tests__/fixtures/e2e-linear.workflow.yaml +1 -0
  165. package/src/__tests__/fixtures/{e2e-mustache.workflow.yaml → e2e-liquid.workflow.yaml} +3 -2
  166. package/src/__tests__/fixtures/e2e-loop.workflow.yaml +1 -0
  167. package/src/__tests__/fixtures/e2e-suspend.mock.yaml +2 -2
  168. package/src/__tests__/fixtures/e2e-suspend.workflow.yaml +6 -10
  169. package/src/__tests__/issue-180-workflow-ref-removed.test.ts +43 -0
  170. package/src/__tests__/moderator-evaluate.test.ts +9 -52
  171. package/src/__tests__/pid-recycling.test.ts +328 -0
  172. package/src/__tests__/prompt.test.ts +397 -0
  173. package/src/__tests__/resolve-head-hash.test.ts +4 -4
  174. package/src/__tests__/setup-agent-discovery.test.ts +26 -51
  175. package/src/__tests__/setup-complexity.test.ts +1 -203
  176. package/src/__tests__/setup-no-llm.test.ts +68 -0
  177. package/src/__tests__/solve-issue-tea-worktree.test.ts +24 -30
  178. package/src/__tests__/step-ask.test.ts +670 -0
  179. package/src/__tests__/step-show-json.test.ts +1 -0
  180. package/src/__tests__/step-timing.test.ts +2 -0
  181. package/src/__tests__/store-global-cas.test.ts +2 -2
  182. package/src/__tests__/store-unified-threads.test.ts +9 -9
  183. package/src/__tests__/thread-cancel-status.test.ts +6 -6
  184. package/src/__tests__/thread-list-filters.test.ts +434 -8
  185. package/src/__tests__/thread-poke.test.ts +545 -0
  186. package/src/__tests__/thread-resume.test.ts +10 -14
  187. package/src/__tests__/thread-show-status.test.ts +17 -29
  188. package/src/__tests__/thread-suspend-step.test.ts +8 -14
  189. package/src/__tests__/thread-suspended-display.test.ts +10 -22
  190. package/src/__tests__/thread.test.ts +4 -4
  191. package/src/__tests__/validate-semantic.test.ts +59 -31
  192. package/src/__tests__/workflow-list-recursive.test.ts +370 -0
  193. package/src/__tests__/workflow-resolution.test.ts +39 -21
  194. package/src/__tests__/workflow-show-resolution.test.ts +285 -0
  195. package/src/__tests__/workflow-validate.test.ts +806 -0
  196. package/src/background/background.ts +88 -6
  197. package/src/background/index.ts +2 -0
  198. package/src/background/types.ts +1 -0
  199. package/src/cli.ts +97 -47
  200. package/src/commands/config.ts +7 -35
  201. package/src/commands/prompt.ts +15 -2
  202. package/src/commands/setup.ts +29 -357
  203. package/src/commands/step.ts +339 -12
  204. package/src/commands/thread.ts +463 -169
  205. package/src/commands/workflow.ts +159 -4
  206. package/src/moderator/__tests__/evaluate.test.ts +34 -17
  207. package/src/moderator/evaluate.ts +5 -17
  208. package/src/moderator/index.ts +1 -6
  209. package/src/moderator/types.ts +6 -14
  210. package/src/schemas.ts +13 -3
  211. package/src/store.ts +86 -20
  212. package/src/validate-semantic.ts +109 -78
  213. package/src/validate.ts +27 -0
  214. package/dist/__tests__/setup-validate.test.d.ts +0 -2
  215. package/dist/__tests__/setup-validate.test.d.ts.map +0 -1
  216. package/dist/__tests__/setup-validate.test.js +0 -108
  217. package/dist/__tests__/setup-validate.test.js.map +0 -1
  218. package/src/__tests__/setup-validate.test.ts +0 -148
  219. /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
+ });
@@ -21,11 +21,11 @@ describe("solve-issue workflow: Gitea API PR creation", () => {
21
21
  "..",
22
22
  "..",
23
23
  "..",
24
- ".workflows",
24
+ "examples",
25
25
  "solve-issue.yaml",
26
26
  );
27
27
 
28
- test("committer procedure should use curl API instead of tea pr create", async () => {
28
+ test("committer procedure should create PR via tea pr create", async () => {
29
29
  const yamlContent = await readFile(workflowPath, "utf-8");
30
30
  const workflow = parse(yamlContent) as WorkflowPayload;
31
31
 
@@ -33,25 +33,22 @@ describe("solve-issue workflow: Gitea API PR creation", () => {
33
33
  const committerProcedure = workflow.roles.committer?.procedure;
34
34
  expect(committerProcedure).toBeDefined();
35
35
 
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);
36
+ // Verify the procedure uses tea pr create for PR creation
37
+ expect(committerProcedure).toContain("tea pr create");
38
+ expect(committerProcedure).toContain("git push");
39
+ expect(committerProcedure).toContain("Fixes #N");
43
40
  });
44
41
 
45
- test("committer procedure should reference repoRemote from task prompt", async () => {
42
+ test("committer procedure should extract owner/repo from git remote", async () => {
46
43
  const yamlContent = await readFile(workflowPath, "utf-8");
47
44
  const workflow = parse(yamlContent) as WorkflowPayload;
48
45
 
49
46
  const committerProcedure = workflow.roles.committer?.procedure;
50
47
  expect(committerProcedure).toBeDefined();
51
48
 
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);
49
+ // Verify the procedure extracts owner/repo from remote
50
+ expect(committerProcedure).toContain("git remote get-url origin");
51
+ expect(committerProcedure).toContain("hook_failed");
55
52
  });
56
53
 
57
54
  test("committer procedure should include error handling for curl failures", async () => {
@@ -100,45 +97,42 @@ describe("solve-issue workflow: Gitea API PR creation", () => {
100
97
  expect(committedVariant.required).toContain("$status");
101
98
  });
102
99
 
103
- test("developer procedure should include mandatory verification step", async () => {
100
+ test("developer procedure should include worktree setup", async () => {
104
101
  const yamlContent = await readFile(workflowPath, "utf-8");
105
102
  const workflow = parse(yamlContent) as WorkflowPayload;
106
103
 
107
104
  const developerProcedure = workflow.roles.developer?.procedure;
108
105
  expect(developerProcedure).toBeDefined();
109
106
 
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);
107
+ // Verify the procedure includes worktree setup
108
+ expect(developerProcedure).toContain("IMPORTANT");
109
+ expect(developerProcedure).toContain("git worktree add");
110
+ expect(developerProcedure).toContain("pnpm install");
115
111
  });
116
112
 
117
- test("reviewer procedure should enforce worktree path verification", async () => {
113
+ test("reviewer procedure should verify branch and run checks", async () => {
118
114
  const yamlContent = await readFile(workflowPath, "utf-8");
119
115
  const workflow = parse(yamlContent) as WorkflowPayload;
120
116
 
121
117
  const reviewerProcedure = workflow.roles.reviewer?.procedure;
122
118
  expect(reviewerProcedure).toBeDefined();
123
119
 
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
- );
120
+ // Verify the procedure includes branch verification and build checks
121
+ expect(reviewerProcedure).toContain("git branch --show-current");
122
+ expect(reviewerProcedure).toContain("pnpm run build");
123
+ expect(reviewerProcedure).toContain("pnpm run check");
130
124
  });
131
125
 
132
- test("developer procedure should include test debugging escalation", async () => {
126
+ test("developer procedure should include changeset and failure handling", async () => {
133
127
  const yamlContent = await readFile(workflowPath, "utf-8");
134
128
  const workflow = parse(yamlContent) as WorkflowPayload;
135
129
 
136
130
  const developerProcedure = workflow.roles.developer?.procedure;
137
131
  expect(developerProcedure).toBeDefined();
138
132
 
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);
133
+ // Verify the procedure includes changeset requirement and failure path
134
+ expect(developerProcedure).toContain(".changeset/");
142
135
  expect(developerProcedure).toContain("$status=failed");
136
+ expect(developerProcedure).toContain("pnpm test");
143
137
  });
144
138
  });