@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.
- package/README.md +45 -11
- package/dist/.build-fingerprint +1 -0
- package/dist/__tests__/adapter-json-roundtrip.test.js +17 -7
- package/dist/__tests__/adapter-json-roundtrip.test.js.map +1 -1
- package/dist/__tests__/agent-resolution-llm-free.test.d.ts +2 -0
- package/dist/__tests__/agent-resolution-llm-free.test.d.ts.map +1 -0
- package/dist/__tests__/agent-resolution-llm-free.test.js +30 -0
- package/dist/__tests__/agent-resolution-llm-free.test.js.map +1 -0
- package/dist/__tests__/build-step-entry.test.d.ts +2 -0
- package/dist/__tests__/build-step-entry.test.d.ts.map +1 -0
- package/dist/__tests__/build-step-entry.test.js +173 -0
- package/dist/__tests__/build-step-entry.test.js.map +1 -0
- package/dist/__tests__/clear-thread-failed-attempts.test.d.ts +2 -0
- package/dist/__tests__/clear-thread-failed-attempts.test.d.ts.map +1 -0
- package/dist/__tests__/clear-thread-failed-attempts.test.js +93 -0
- package/dist/__tests__/clear-thread-failed-attempts.test.js.map +1 -0
- package/dist/__tests__/concurrency.test.d.ts +2 -0
- package/dist/__tests__/concurrency.test.d.ts.map +1 -0
- package/dist/__tests__/concurrency.test.js +196 -0
- package/dist/__tests__/concurrency.test.js.map +1 -0
- package/dist/__tests__/config.test.js +26 -302
- package/dist/__tests__/config.test.js.map +1 -1
- package/dist/__tests__/current-role.test.js +7 -6
- package/dist/__tests__/current-role.test.js.map +1 -1
- package/dist/__tests__/e2e-mock-agent.test.js +43 -30
- package/dist/__tests__/e2e-mock-agent.test.js.map +1 -1
- package/dist/__tests__/format-text-default.test.d.ts +2 -0
- package/dist/__tests__/format-text-default.test.d.ts.map +1 -0
- package/dist/__tests__/format-text-default.test.js +43 -0
- package/dist/__tests__/format-text-default.test.js.map +1 -0
- package/dist/__tests__/format-text-registry.test.d.ts +2 -0
- package/dist/__tests__/format-text-registry.test.d.ts.map +1 -0
- package/dist/__tests__/format-text-registry.test.js +158 -0
- package/dist/__tests__/format-text-registry.test.js.map +1 -0
- package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts +2 -0
- package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts.map +1 -0
- package/dist/__tests__/issue-180-workflow-ref-removed.test.js +40 -0
- package/dist/__tests__/issue-180-workflow-ref-removed.test.js.map +1 -0
- package/dist/__tests__/log-text-renderer.test.d.ts +2 -0
- package/dist/__tests__/log-text-renderer.test.d.ts.map +1 -0
- package/dist/__tests__/log-text-renderer.test.js +265 -0
- package/dist/__tests__/log-text-renderer.test.js.map +1 -0
- package/dist/__tests__/moderator-evaluate.test.js +9 -50
- package/dist/__tests__/moderator-evaluate.test.js.map +1 -1
- package/dist/__tests__/output-mapper-thread-list-startedat.test.d.ts +2 -0
- package/dist/__tests__/output-mapper-thread-list-startedat.test.d.ts.map +1 -0
- package/dist/__tests__/output-mapper-thread-list-startedat.test.js +102 -0
- package/dist/__tests__/output-mapper-thread-list-startedat.test.js.map +1 -0
- package/dist/__tests__/output-mapper-workflow-add.test.d.ts +2 -0
- package/dist/__tests__/output-mapper-workflow-add.test.d.ts.map +1 -0
- package/dist/__tests__/output-mapper-workflow-add.test.js +22 -0
- package/dist/__tests__/output-mapper-workflow-add.test.js.map +1 -0
- package/dist/__tests__/pid-recycling.test.d.ts +2 -0
- package/dist/__tests__/pid-recycling.test.d.ts.map +1 -0
- package/dist/__tests__/pid-recycling.test.js +273 -0
- package/dist/__tests__/pid-recycling.test.js.map +1 -0
- package/dist/__tests__/prompt.test.js +365 -2
- package/dist/__tests__/prompt.test.js.map +1 -1
- package/dist/__tests__/resolve-head-hash.test.js +12 -4
- package/dist/__tests__/resolve-head-hash.test.js.map +1 -1
- package/dist/__tests__/setup-agent-discovery.test.js +21 -30
- package/dist/__tests__/setup-agent-discovery.test.js.map +1 -1
- package/dist/__tests__/setup-complexity.test.js +2 -168
- package/dist/__tests__/setup-complexity.test.js.map +1 -1
- package/dist/__tests__/setup-no-llm.test.d.ts +2 -0
- package/dist/__tests__/setup-no-llm.test.d.ts.map +1 -0
- package/dist/__tests__/setup-no-llm.test.js +52 -0
- package/dist/__tests__/setup-no-llm.test.js.map +1 -0
- package/dist/__tests__/solve-issue-tea-worktree.test.js +27 -28
- package/dist/__tests__/solve-issue-tea-worktree.test.js.map +1 -1
- package/dist/__tests__/step-ask.test.d.ts +2 -0
- package/dist/__tests__/step-ask.test.d.ts.map +1 -0
- package/dist/__tests__/step-ask.test.js +507 -0
- package/dist/__tests__/step-ask.test.js.map +1 -0
- package/dist/__tests__/step-show-json.test.js +1 -0
- package/dist/__tests__/step-show-json.test.js.map +1 -1
- package/dist/__tests__/step-timing.test.js +2 -0
- package/dist/__tests__/step-timing.test.js.map +1 -1
- package/dist/__tests__/store-global-cas.test.js +2 -2
- package/dist/__tests__/store-global-cas.test.js.map +1 -1
- package/dist/__tests__/store-unified-threads.test.js +28 -26
- package/dist/__tests__/store-unified-threads.test.js.map +1 -1
- package/dist/__tests__/thread-cancel-status.test.js +25 -19
- package/dist/__tests__/thread-cancel-status.test.js.map +1 -1
- package/dist/__tests__/thread-cancel-text-renderer.test.d.ts +2 -0
- package/dist/__tests__/thread-cancel-text-renderer.test.d.ts.map +1 -0
- package/dist/__tests__/thread-cancel-text-renderer.test.js +110 -0
- package/dist/__tests__/thread-cancel-text-renderer.test.js.map +1 -0
- package/dist/__tests__/thread-list-filters.test.js +354 -17
- package/dist/__tests__/thread-list-filters.test.js.map +1 -1
- package/dist/__tests__/thread-list-template-ms-date.test.d.ts +2 -0
- package/dist/__tests__/thread-list-template-ms-date.test.d.ts.map +1 -0
- package/dist/__tests__/thread-list-template-ms-date.test.js +102 -0
- package/dist/__tests__/thread-list-template-ms-date.test.js.map +1 -0
- package/dist/__tests__/thread-list-workflow-corrupt.test.d.ts +2 -0
- package/dist/__tests__/thread-list-workflow-corrupt.test.d.ts.map +1 -0
- package/dist/__tests__/thread-list-workflow-corrupt.test.js +157 -0
- package/dist/__tests__/thread-list-workflow-corrupt.test.js.map +1 -0
- package/dist/__tests__/thread-poke.test.d.ts +2 -0
- package/dist/__tests__/thread-poke.test.d.ts.map +1 -0
- package/dist/__tests__/thread-poke.test.js +422 -0
- package/dist/__tests__/thread-poke.test.js.map +1 -0
- package/dist/__tests__/thread-read-xml-tags.test.js +10 -9
- package/dist/__tests__/thread-read-xml-tags.test.js.map +1 -1
- package/dist/__tests__/thread-resume.test.js +21 -15
- package/dist/__tests__/thread-resume.test.js.map +1 -1
- package/dist/__tests__/thread-show-status.test.js +17 -28
- package/dist/__tests__/thread-show-status.test.js.map +1 -1
- package/dist/__tests__/thread-start-cwd-cli.test.js +15 -3
- package/dist/__tests__/thread-start-cwd-cli.test.js.map +1 -1
- package/dist/__tests__/thread-stop-text-renderer.test.d.ts +2 -0
- package/dist/__tests__/thread-stop-text-renderer.test.d.ts.map +1 -0
- package/dist/__tests__/thread-stop-text-renderer.test.js +148 -0
- package/dist/__tests__/thread-stop-text-renderer.test.js.map +1 -0
- package/dist/__tests__/thread-suspend-step.test.js +13 -16
- package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
- package/dist/__tests__/thread-suspended-display.test.js +10 -22
- package/dist/__tests__/thread-suspended-display.test.js.map +1 -1
- package/dist/__tests__/thread-test-helpers.d.ts +7 -0
- package/dist/__tests__/thread-test-helpers.d.ts.map +1 -1
- package/dist/__tests__/thread-test-helpers.js +13 -0
- package/dist/__tests__/thread-test-helpers.js.map +1 -1
- package/dist/__tests__/thread.test.js +15 -13
- package/dist/__tests__/thread.test.js.map +1 -1
- package/dist/__tests__/validate-semantic.test.js +105 -23
- package/dist/__tests__/validate-semantic.test.js.map +1 -1
- package/dist/__tests__/workflow-list-recursive.test.d.ts +2 -0
- package/dist/__tests__/workflow-list-recursive.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-list-recursive.test.js +286 -0
- package/dist/__tests__/workflow-list-recursive.test.js.map +1 -0
- package/dist/__tests__/workflow-resolution.test.js +46 -28
- package/dist/__tests__/workflow-resolution.test.js.map +1 -1
- package/dist/__tests__/workflow-show-resolution.test.d.ts +2 -0
- package/dist/__tests__/workflow-show-resolution.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-show-resolution.test.js +213 -0
- package/dist/__tests__/workflow-show-resolution.test.js.map +1 -0
- package/dist/__tests__/workflow-validate.test.d.ts +2 -0
- package/dist/__tests__/workflow-validate.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-validate.test.js +707 -0
- package/dist/__tests__/workflow-validate.test.js.map +1 -0
- package/dist/__tests__/write-envelope.test.d.ts +2 -0
- package/dist/__tests__/write-envelope.test.d.ts.map +1 -0
- package/dist/__tests__/write-envelope.test.js +201 -0
- package/dist/__tests__/write-envelope.test.js.map +1 -0
- package/dist/background/background.d.ts +22 -1
- package/dist/background/background.d.ts.map +1 -1
- package/dist/background/background.js +83 -6
- package/dist/background/background.js.map +1 -1
- package/dist/background/index.d.ts +1 -1
- package/dist/background/index.d.ts.map +1 -1
- package/dist/background/index.js +1 -1
- package/dist/background/index.js.map +1 -1
- package/dist/background/types.d.ts +1 -0
- package/dist/background/types.d.ts.map +1 -1
- package/dist/cli.js +120 -62
- package/dist/cli.js.map +1 -1
- package/dist/commands/config.d.ts +3 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +17 -31
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/prompt.d.ts.map +1 -1
- package/dist/commands/prompt.js +57 -31
- package/dist/commands/prompt.js.map +1 -1
- package/dist/commands/setup.d.ts +12 -39
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +72 -303
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/step.d.ts +44 -1
- package/dist/commands/step.d.ts.map +1 -1
- package/dist/commands/step.js +255 -11
- package/dist/commands/step.js.map +1 -1
- package/dist/commands/thread.d.ts +16 -3
- package/dist/commands/thread.d.ts.map +1 -1
- package/dist/commands/thread.js +423 -142
- package/dist/commands/thread.js.map +1 -1
- package/dist/commands/workflow.d.ts +9 -1
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +126 -6
- package/dist/commands/workflow.js.map +1 -1
- package/dist/concurrency/concurrency.d.ts +34 -0
- package/dist/concurrency/concurrency.d.ts.map +1 -0
- package/dist/concurrency/concurrency.js +216 -0
- package/dist/concurrency/concurrency.js.map +1 -0
- package/dist/concurrency/index.d.ts +3 -0
- package/dist/concurrency/index.d.ts.map +1 -0
- package/dist/concurrency/index.js +2 -0
- package/dist/concurrency/index.js.map +1 -0
- package/dist/concurrency/types.d.ts +19 -0
- package/dist/concurrency/types.d.ts.map +1 -0
- package/dist/concurrency/types.js +2 -0
- package/dist/concurrency/types.js.map +1 -0
- package/dist/format.d.ts +69 -2
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +198 -1
- package/dist/format.js.map +1 -1
- package/dist/moderator/__tests__/evaluate.test.js +31 -17
- package/dist/moderator/__tests__/evaluate.test.js.map +1 -1
- package/dist/moderator/evaluate.d.ts.map +1 -1
- package/dist/moderator/evaluate.js +4 -16
- package/dist/moderator/evaluate.js.map +1 -1
- package/dist/moderator/index.d.ts +1 -2
- package/dist/moderator/index.d.ts.map +1 -1
- package/dist/moderator/index.js +0 -1
- package/dist/moderator/index.js.map +1 -1
- package/dist/moderator/types.d.ts +6 -10
- package/dist/moderator/types.d.ts.map +1 -1
- package/dist/moderator/types.js +1 -3
- package/dist/moderator/types.js.map +1 -1
- package/dist/output-mappers.d.ts +122 -0
- package/dist/output-mappers.d.ts.map +1 -0
- package/dist/output-mappers.js +134 -0
- package/dist/output-mappers.js.map +1 -0
- package/dist/schemas.d.ts +6 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +34 -5
- package/dist/schemas.js.map +1 -1
- package/dist/store.d.ts +28 -9
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +75 -16
- package/dist/store.js.map +1 -1
- package/dist/text-renderers.d.ts +30 -0
- package/dist/text-renderers.d.ts.map +1 -0
- package/dist/text-renderers.js +251 -0
- package/dist/text-renderers.js.map +1 -0
- package/dist/validate-semantic.d.ts.map +1 -1
- package/dist/validate-semantic.js +95 -61
- package/dist/validate-semantic.js.map +1 -1
- package/dist/validate.d.ts +6 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +24 -0
- package/dist/validate.js.map +1 -1
- package/examples/brainstorm.yaml +130 -0
- package/examples/debate.yaml +169 -0
- package/examples/socratic-questioning.yaml +112 -0
- package/package.json +9 -10
- package/src/__tests__/adapter-json-roundtrip.test.ts +16 -7
- package/src/__tests__/agent-resolution-llm-free.test.ts +39 -0
- package/src/__tests__/build-step-entry.test.ts +203 -0
- package/src/__tests__/clear-thread-failed-attempts.test.ts +122 -0
- package/src/__tests__/concurrency.test.ts +266 -0
- package/src/__tests__/config.test.ts +33 -321
- package/src/__tests__/current-role.test.ts +7 -6
- package/src/__tests__/e2e-mock-agent.test.ts +65 -30
- package/src/__tests__/fixtures/e2e-count.workflow.yaml +1 -0
- package/src/__tests__/fixtures/e2e-linear.workflow.yaml +1 -0
- package/src/__tests__/fixtures/{e2e-mustache.workflow.yaml → e2e-liquid.workflow.yaml} +3 -2
- package/src/__tests__/fixtures/e2e-loop.workflow.yaml +1 -0
- package/src/__tests__/fixtures/e2e-suspend.mock.yaml +2 -2
- package/src/__tests__/fixtures/e2e-suspend.workflow.yaml +6 -10
- package/src/__tests__/format-text-default.test.ts +49 -0
- package/src/__tests__/format-text-registry.test.ts +173 -0
- package/src/__tests__/issue-180-workflow-ref-removed.test.ts +43 -0
- package/src/__tests__/log-text-renderer.test.ts +294 -0
- package/src/__tests__/moderator-evaluate.test.ts +9 -52
- package/src/__tests__/output-mapper-thread-list-startedat.test.ts +124 -0
- package/src/__tests__/output-mapper-workflow-add.test.ts +24 -0
- package/src/__tests__/pid-recycling.test.ts +329 -0
- package/src/__tests__/prompt.test.ts +443 -2
- package/src/__tests__/resolve-head-hash.test.ts +11 -4
- package/src/__tests__/setup-agent-discovery.test.ts +26 -51
- package/src/__tests__/setup-complexity.test.ts +1 -203
- package/src/__tests__/setup-no-llm.test.ts +68 -0
- package/src/__tests__/solve-issue-tea-worktree.test.ts +27 -31
- package/src/__tests__/step-ask.test.ts +677 -0
- package/src/__tests__/step-show-json.test.ts +1 -0
- package/src/__tests__/step-timing.test.ts +2 -0
- package/src/__tests__/store-global-cas.test.ts +2 -2
- package/src/__tests__/store-unified-threads.test.ts +30 -27
- package/src/__tests__/thread-cancel-status.test.ts +27 -20
- package/src/__tests__/thread-cancel-text-renderer.test.ts +125 -0
- package/src/__tests__/thread-list-filters.test.ts +443 -17
- package/src/__tests__/thread-list-template-ms-date.test.ts +110 -0
- package/src/__tests__/thread-list-workflow-corrupt.test.ts +198 -0
- package/src/__tests__/thread-poke.test.ts +554 -0
- package/src/__tests__/thread-read-xml-tags.test.ts +9 -11
- package/src/__tests__/thread-resume.test.ts +20 -15
- package/src/__tests__/thread-show-status.test.ts +17 -29
- package/src/__tests__/thread-start-cwd-cli.test.ts +15 -3
- package/src/__tests__/thread-stop-text-renderer.test.ts +168 -0
- package/src/__tests__/thread-suspend-step.test.ts +13 -16
- package/src/__tests__/thread-suspended-display.test.ts +10 -22
- package/src/__tests__/thread-test-helpers.ts +15 -1
- package/src/__tests__/thread.test.ts +14 -14
- package/src/__tests__/validate-semantic.test.ts +118 -33
- package/src/__tests__/workflow-list-recursive.test.ts +370 -0
- package/src/__tests__/workflow-resolution.test.ts +48 -29
- package/src/__tests__/workflow-show-resolution.test.ts +286 -0
- package/src/__tests__/workflow-validate.test.ts +828 -0
- package/src/__tests__/write-envelope.test.ts +257 -0
- package/src/background/background.ts +88 -6
- package/src/background/index.ts +2 -0
- package/src/background/types.ts +1 -0
- package/src/cli.ts +184 -77
- package/src/commands/config.ts +16 -33
- package/src/commands/prompt.ts +57 -31
- package/src/commands/setup.ts +80 -358
- package/src/commands/step.ts +339 -12
- package/src/commands/thread.ts +511 -171
- package/src/commands/workflow.ts +155 -4
- package/src/concurrency/concurrency.ts +245 -0
- package/src/concurrency/index.ts +10 -0
- package/src/concurrency/types.ts +19 -0
- package/src/format.ts +282 -2
- package/src/moderator/__tests__/evaluate.test.ts +34 -17
- package/src/moderator/evaluate.ts +5 -17
- package/src/moderator/index.ts +1 -6
- package/src/moderator/types.ts +6 -14
- package/src/output-mappers.ts +254 -0
- package/src/schemas.ts +51 -5
- package/src/store.ts +86 -20
- package/src/text-renderers.ts +355 -0
- package/src/validate-semantic.ts +125 -73
- package/src/validate.ts +27 -0
- package/dist/__tests__/setup-validate.test.d.ts +0 -2
- package/dist/__tests__/setup-validate.test.d.ts.map +0 -1
- package/dist/__tests__/setup-validate.test.js +0 -108
- package/dist/__tests__/setup-validate.test.js.map +0 -1
- package/src/__tests__/setup-validate.test.ts +0 -148
- /package/src/__tests__/fixtures/{e2e-mustache.mock.yaml → e2e-liquid.mock.yaml} +0 -0
|
@@ -6,19 +6,14 @@ import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
|
6
6
|
import { stringify } from "yaml";
|
|
7
7
|
import { cmdThreadStart } from "../commands/thread.js";
|
|
8
8
|
import type { UwfStore } from "../store.js";
|
|
9
|
-
import {
|
|
9
|
+
import { saveWorkflowRegistry } from "../store.js";
|
|
10
|
+
import { makeUwfStore } from "./thread-test-helpers.js";
|
|
10
11
|
|
|
11
12
|
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
12
13
|
|
|
13
|
-
async function makeUwfStore(storageRoot: string): Promise<UwfStore> {
|
|
14
|
-
const casDir = join(storageRoot, "cas");
|
|
15
|
-
await mkdir(casDir, { recursive: true });
|
|
16
|
-
process.env.OCAS_HOME = casDir;
|
|
17
|
-
return createUwfStore(storageRoot);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
14
|
function makeMinimalPayload(name: string, description: string): WorkflowPayload {
|
|
21
15
|
return {
|
|
16
|
+
version: 1,
|
|
22
17
|
name,
|
|
23
18
|
description,
|
|
24
19
|
roles: {
|
|
@@ -66,8 +61,10 @@ async function createWorkflowYaml(name: string, version: string | null = null):
|
|
|
66
61
|
let tmpDir: string;
|
|
67
62
|
let storageRoot: string;
|
|
68
63
|
let projectRoot: string;
|
|
64
|
+
let savedOcasHome: string | undefined;
|
|
69
65
|
|
|
70
66
|
beforeEach(async () => {
|
|
67
|
+
savedOcasHome = process.env.OCAS_HOME;
|
|
71
68
|
tmpDir = await mkdtemp(join(tmpdir(), "cli-uwf-wf-resolve-test-"));
|
|
72
69
|
storageRoot = join(tmpDir, "storage");
|
|
73
70
|
projectRoot = join(tmpDir, "project");
|
|
@@ -76,6 +73,11 @@ beforeEach(async () => {
|
|
|
76
73
|
});
|
|
77
74
|
|
|
78
75
|
afterEach(async () => {
|
|
76
|
+
if (savedOcasHome === undefined) {
|
|
77
|
+
delete process.env.OCAS_HOME;
|
|
78
|
+
} else {
|
|
79
|
+
process.env.OCAS_HOME = savedOcasHome;
|
|
80
|
+
}
|
|
79
81
|
await rm(tmpDir, { recursive: true, force: true });
|
|
80
82
|
});
|
|
81
83
|
|
|
@@ -180,9 +182,9 @@ describe("Strategy 2: File Path Resolution", () => {
|
|
|
180
182
|
// ── Strategy 3: Local Discovery (Parent Traversal) ────────────────────────────
|
|
181
183
|
|
|
182
184
|
describe("Strategy 3: Local Discovery", () => {
|
|
183
|
-
test("should find workflow in current directory .
|
|
185
|
+
test("should find workflow in current directory .workflows/", async () => {
|
|
184
186
|
await makeUwfStore(storageRoot);
|
|
185
|
-
const workflowDir = join(projectRoot, ".
|
|
187
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
186
188
|
await mkdir(workflowDir, { recursive: true });
|
|
187
189
|
await writeFile(join(workflowDir, "solve-issue.yaml"), await createWorkflowYaml("solve-issue"));
|
|
188
190
|
|
|
@@ -197,9 +199,9 @@ describe("Strategy 3: Local Discovery", () => {
|
|
|
197
199
|
}
|
|
198
200
|
});
|
|
199
201
|
|
|
200
|
-
test("should find workflow in parent directory .
|
|
202
|
+
test("should find workflow in parent directory .workflows/", async () => {
|
|
201
203
|
await makeUwfStore(storageRoot);
|
|
202
|
-
const workflowDir = join(projectRoot, ".
|
|
204
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
203
205
|
await mkdir(workflowDir, { recursive: true });
|
|
204
206
|
await writeFile(join(workflowDir, "solve-issue.yaml"), await createWorkflowYaml("solve-issue"));
|
|
205
207
|
|
|
@@ -219,19 +221,19 @@ describe("Strategy 3: Local Discovery", () => {
|
|
|
219
221
|
await expect(cmdThreadStart(storageRoot, "nonexistent", "prompt", deepPath)).rejects.toThrow();
|
|
220
222
|
});
|
|
221
223
|
|
|
222
|
-
test("should prefer .
|
|
224
|
+
test("should prefer .workflows/ over .workflow/ directory", async () => {
|
|
223
225
|
await makeUwfStore(storageRoot);
|
|
224
|
-
const
|
|
225
|
-
const
|
|
226
|
-
await mkdir(
|
|
227
|
-
await mkdir(
|
|
226
|
+
const primaryDir = join(projectRoot, ".workflows");
|
|
227
|
+
const legacyDir = join(projectRoot, ".workflow");
|
|
228
|
+
await mkdir(primaryDir, { recursive: true });
|
|
229
|
+
await mkdir(legacyDir, { recursive: true });
|
|
228
230
|
|
|
229
231
|
await writeFile(
|
|
230
|
-
join(
|
|
232
|
+
join(primaryDir, "solve-issue.yaml"),
|
|
231
233
|
await createWorkflowYaml("solve-issue", "1"),
|
|
232
234
|
);
|
|
233
235
|
await writeFile(
|
|
234
|
-
join(
|
|
236
|
+
join(legacyDir, "solve-issue.yaml"),
|
|
235
237
|
await createWorkflowYaml("solve-issue", "2"),
|
|
236
238
|
);
|
|
237
239
|
|
|
@@ -245,9 +247,9 @@ describe("Strategy 3: Local Discovery", () => {
|
|
|
245
247
|
}
|
|
246
248
|
});
|
|
247
249
|
|
|
248
|
-
test("should support .yml extension in local discovery", async () => {
|
|
250
|
+
test("should support .yml extension in local discovery under .workflows/", async () => {
|
|
249
251
|
await makeUwfStore(storageRoot);
|
|
250
|
-
const workflowDir = join(projectRoot, ".
|
|
252
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
251
253
|
await mkdir(workflowDir, { recursive: true });
|
|
252
254
|
await writeFile(join(workflowDir, "solve-issue.yml"), await createWorkflowYaml("solve-issue"));
|
|
253
255
|
|
|
@@ -256,9 +258,9 @@ describe("Strategy 3: Local Discovery", () => {
|
|
|
256
258
|
expect(result.workflow).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
|
257
259
|
});
|
|
258
260
|
|
|
259
|
-
test("should find workflow in folder-based layout (name
|
|
261
|
+
test("should find workflow in folder-based layout (.workflows/<name>/index.yaml)", async () => {
|
|
260
262
|
await makeUwfStore(storageRoot);
|
|
261
|
-
const workflowDir = join(projectRoot, ".
|
|
263
|
+
const workflowDir = join(projectRoot, ".workflows", "solve-issue");
|
|
262
264
|
await mkdir(workflowDir, { recursive: true });
|
|
263
265
|
await writeFile(join(workflowDir, "index.yaml"), await createWorkflowYaml("solve-issue"));
|
|
264
266
|
|
|
@@ -273,9 +275,9 @@ describe("Strategy 3: Local Discovery", () => {
|
|
|
273
275
|
}
|
|
274
276
|
});
|
|
275
277
|
|
|
276
|
-
test("should prefer flat file over folder-based layout", async () => {
|
|
278
|
+
test("should prefer flat file over folder-based layout under .workflows/", async () => {
|
|
277
279
|
await makeUwfStore(storageRoot);
|
|
278
|
-
const workflowDir = join(projectRoot, ".
|
|
280
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
279
281
|
await mkdir(workflowDir, { recursive: true });
|
|
280
282
|
await writeFile(
|
|
281
283
|
join(workflowDir, "solve-issue.yaml"),
|
|
@@ -298,6 +300,23 @@ describe("Strategy 3: Local Discovery", () => {
|
|
|
298
300
|
expect((node.payload as WorkflowPayload).description).toBe("Test workflow (flat)");
|
|
299
301
|
}
|
|
300
302
|
});
|
|
303
|
+
|
|
304
|
+
test("should resolve from legacy .workflow/ when .workflows/ is absent", async () => {
|
|
305
|
+
await makeUwfStore(storageRoot);
|
|
306
|
+
const legacyDir = join(projectRoot, ".workflow");
|
|
307
|
+
await mkdir(legacyDir, { recursive: true });
|
|
308
|
+
await writeFile(join(legacyDir, "solve-issue.yaml"), await createWorkflowYaml("solve-issue"));
|
|
309
|
+
|
|
310
|
+
const result = await cmdThreadStart(storageRoot, "solve-issue", "prompt", projectRoot);
|
|
311
|
+
|
|
312
|
+
expect(result.workflow).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
|
313
|
+
const uwf = await makeUwfStore(storageRoot);
|
|
314
|
+
const node = uwf.store.cas.get(result.workflow);
|
|
315
|
+
expect(node).not.toBeNull();
|
|
316
|
+
if (node !== null) {
|
|
317
|
+
expect((node.payload as WorkflowPayload).name).toBe("solve-issue");
|
|
318
|
+
}
|
|
319
|
+
});
|
|
301
320
|
});
|
|
302
321
|
|
|
303
322
|
// ── Strategy 4: Global Registry Fallback ──────────────────────────────────────
|
|
@@ -329,8 +348,8 @@ describe("Resolution Priority", () => {
|
|
|
329
348
|
test("should use explicit file path over local discovery", async () => {
|
|
330
349
|
await makeUwfStore(storageRoot);
|
|
331
350
|
|
|
332
|
-
// Setup: Create workflow in .
|
|
333
|
-
const workflowDir = join(projectRoot, ".
|
|
351
|
+
// Setup: Create workflow in .workflows/ AND as explicit file
|
|
352
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
334
353
|
await mkdir(workflowDir, { recursive: true });
|
|
335
354
|
await writeFile(
|
|
336
355
|
join(workflowDir, "solve-issue.yaml"),
|
|
@@ -358,8 +377,8 @@ describe("Resolution Priority", () => {
|
|
|
358
377
|
const globalHash = await storeWorkflow(uwf, "solve-issue");
|
|
359
378
|
saveWorkflowRegistry(uwf.varStore, "solve-issue", globalHash);
|
|
360
379
|
|
|
361
|
-
// Setup: Create local .
|
|
362
|
-
const workflowDir = join(projectRoot, ".
|
|
380
|
+
// Setup: Create local .workflows/
|
|
381
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
363
382
|
await mkdir(workflowDir, { recursive: true });
|
|
364
383
|
const localYaml = await createWorkflowYaml("solve-issue", "local");
|
|
365
384
|
await writeFile(join(workflowDir, "solve-issue.yaml"), localYaml);
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import type { CasRef, WorkflowPayload } from "@united-workforce/protocol";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
6
|
+
import { stringify } from "yaml";
|
|
7
|
+
import { cmdWorkflowShow } from "../commands/workflow.js";
|
|
8
|
+
import type { UwfStore } from "../store.js";
|
|
9
|
+
import { saveWorkflowRegistry } from "../store.js";
|
|
10
|
+
import { makeUwfStore } from "./thread-test-helpers.js";
|
|
11
|
+
|
|
12
|
+
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
function makeMinimalPayload(name: string, description: string): WorkflowPayload {
|
|
15
|
+
return {
|
|
16
|
+
version: 1,
|
|
17
|
+
name,
|
|
18
|
+
description,
|
|
19
|
+
roles: {
|
|
20
|
+
worker: {
|
|
21
|
+
description: "worker role",
|
|
22
|
+
goal: "do work",
|
|
23
|
+
capabilities: [],
|
|
24
|
+
procedure: "",
|
|
25
|
+
output: "",
|
|
26
|
+
frontmatter: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
$status: { const: "done" },
|
|
30
|
+
},
|
|
31
|
+
required: ["$status"],
|
|
32
|
+
} as unknown as CasRef,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
graph: {
|
|
36
|
+
$START: {
|
|
37
|
+
new: { role: "worker", prompt: "start working", location: null },
|
|
38
|
+
resume: { role: "worker", prompt: "resume working", location: null },
|
|
39
|
+
},
|
|
40
|
+
worker: { done: { role: "$END", prompt: "done", location: null } },
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function storeWorkflow(uwf: UwfStore, name: string): Promise<CasRef> {
|
|
46
|
+
const payload = makeMinimalPayload(name, "Test workflow");
|
|
47
|
+
return await uwf.store.cas.put(uwf.schemas.workflow, payload);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function createWorkflowYaml(name: string, version: string | null = null): Promise<string> {
|
|
51
|
+
const payload = makeMinimalPayload(
|
|
52
|
+
name,
|
|
53
|
+
version !== null ? `Test workflow (${version})` : "Test workflow",
|
|
54
|
+
);
|
|
55
|
+
const yaml = stringify(payload);
|
|
56
|
+
return yaml;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ── fixture ───────────────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
let tmpDir: string;
|
|
62
|
+
let storageRoot: string;
|
|
63
|
+
let projectRoot: string;
|
|
64
|
+
let savedOcasHome: string | undefined;
|
|
65
|
+
|
|
66
|
+
beforeEach(async () => {
|
|
67
|
+
savedOcasHome = process.env.OCAS_HOME;
|
|
68
|
+
tmpDir = await mkdtemp(join(tmpdir(), "cli-uwf-wf-show-test-"));
|
|
69
|
+
storageRoot = join(tmpDir, "storage");
|
|
70
|
+
projectRoot = join(tmpDir, "project");
|
|
71
|
+
await mkdir(storageRoot, { recursive: true });
|
|
72
|
+
await mkdir(projectRoot, { recursive: true });
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
afterEach(async () => {
|
|
76
|
+
if (savedOcasHome === undefined) {
|
|
77
|
+
delete process.env.OCAS_HOME;
|
|
78
|
+
} else {
|
|
79
|
+
process.env.OCAS_HOME = savedOcasHome;
|
|
80
|
+
}
|
|
81
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// ── Strategy 1: CAS Hash Resolution ───────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
describe("Strategy 1: CAS Hash Resolution", () => {
|
|
87
|
+
test("should resolve valid 13-char Crockford Base32 hash", async () => {
|
|
88
|
+
const uwf = await makeUwfStore(storageRoot);
|
|
89
|
+
const hash = await storeWorkflow(uwf, "test-workflow");
|
|
90
|
+
|
|
91
|
+
const result = await cmdWorkflowShow(storageRoot, hash, projectRoot);
|
|
92
|
+
|
|
93
|
+
expect(result.hash).toBe(hash);
|
|
94
|
+
expect(result.payload.name).toBe("test-workflow");
|
|
95
|
+
expect(result.name).toBeNull(); // not in registry
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("should fail on invalid hash format (non-Crockford characters)", async () => {
|
|
99
|
+
await makeUwfStore(storageRoot);
|
|
100
|
+
|
|
101
|
+
await expect(cmdWorkflowShow(storageRoot, "123456789ABCD", projectRoot)).rejects.toThrow();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("should fail on valid-format hash not present in CAS", async () => {
|
|
105
|
+
await makeUwfStore(storageRoot);
|
|
106
|
+
const fakeHash = "0000000000000"; // valid format, doesn't exist
|
|
107
|
+
|
|
108
|
+
await expect(cmdWorkflowShow(storageRoot, fakeHash, projectRoot)).rejects.toThrow();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// ── Strategy 2: File Path Resolution ──────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
describe("Strategy 2: File Path Resolution", () => {
|
|
115
|
+
test("should load workflow from absolute file path", async () => {
|
|
116
|
+
await makeUwfStore(storageRoot);
|
|
117
|
+
const yamlPath = join(tmpDir, "test-workflow.yaml");
|
|
118
|
+
await writeFile(yamlPath, await createWorkflowYaml("test-workflow"));
|
|
119
|
+
|
|
120
|
+
const result = await cmdWorkflowShow(storageRoot, yamlPath, projectRoot);
|
|
121
|
+
|
|
122
|
+
expect(result.hash).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
|
123
|
+
expect(result.payload.name).toBe("test-workflow");
|
|
124
|
+
expect(result.payload.description).toBe("Test workflow");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("should load workflow from relative file path", async () => {
|
|
128
|
+
await makeUwfStore(storageRoot);
|
|
129
|
+
const yamlPath = "test-workflow.yaml";
|
|
130
|
+
await writeFile(join(projectRoot, yamlPath), await createWorkflowYaml("test-workflow"));
|
|
131
|
+
|
|
132
|
+
const result = await cmdWorkflowShow(storageRoot, yamlPath, projectRoot);
|
|
133
|
+
|
|
134
|
+
expect(result.hash).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
|
135
|
+
expect(result.payload.name).toBe("test-workflow");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("should fail when file path does not exist", async () => {
|
|
139
|
+
await makeUwfStore(storageRoot);
|
|
140
|
+
|
|
141
|
+
await expect(cmdWorkflowShow(storageRoot, "./nonexistent.yaml", projectRoot)).rejects.toThrow();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// ── Strategy 3: Local Discovery (Parent Traversal) ────────────────────────────
|
|
146
|
+
|
|
147
|
+
describe("Strategy 3: Local Discovery", () => {
|
|
148
|
+
test("should find workflow in current directory .workflows/", async () => {
|
|
149
|
+
await makeUwfStore(storageRoot);
|
|
150
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
151
|
+
await mkdir(workflowDir, { recursive: true });
|
|
152
|
+
await writeFile(join(workflowDir, "solve-issue.yaml"), await createWorkflowYaml("solve-issue"));
|
|
153
|
+
|
|
154
|
+
const result = await cmdWorkflowShow(storageRoot, "solve-issue", projectRoot);
|
|
155
|
+
|
|
156
|
+
expect(result.hash).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
|
157
|
+
expect(result.payload.name).toBe("solve-issue");
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test("should find workflow in parent directory .workflows/", async () => {
|
|
161
|
+
await makeUwfStore(storageRoot);
|
|
162
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
163
|
+
await mkdir(workflowDir, { recursive: true });
|
|
164
|
+
await writeFile(join(workflowDir, "solve-issue.yaml"), await createWorkflowYaml("solve-issue"));
|
|
165
|
+
|
|
166
|
+
const subdir = join(projectRoot, "packages", "cli", "src");
|
|
167
|
+
await mkdir(subdir, { recursive: true });
|
|
168
|
+
|
|
169
|
+
const result = await cmdWorkflowShow(storageRoot, "solve-issue", subdir);
|
|
170
|
+
|
|
171
|
+
expect(result.hash).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
|
172
|
+
expect(result.payload.name).toBe("solve-issue");
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("should prefer .workflows/ over .workflow/ directory", async () => {
|
|
176
|
+
await makeUwfStore(storageRoot);
|
|
177
|
+
const primaryDir = join(projectRoot, ".workflows");
|
|
178
|
+
const legacyDir = join(projectRoot, ".workflow");
|
|
179
|
+
await mkdir(primaryDir, { recursive: true });
|
|
180
|
+
await mkdir(legacyDir, { recursive: true });
|
|
181
|
+
|
|
182
|
+
await writeFile(
|
|
183
|
+
join(primaryDir, "solve-issue.yaml"),
|
|
184
|
+
await createWorkflowYaml("solve-issue", "primary"),
|
|
185
|
+
);
|
|
186
|
+
await writeFile(
|
|
187
|
+
join(legacyDir, "solve-issue.yaml"),
|
|
188
|
+
await createWorkflowYaml("solve-issue", "legacy"),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const result = await cmdWorkflowShow(storageRoot, "solve-issue", projectRoot);
|
|
192
|
+
|
|
193
|
+
expect(result.payload.description).toBe("Test workflow (primary)");
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test("should find workflow in folder-based layout (.workflows/<name>/index.yaml)", async () => {
|
|
197
|
+
await makeUwfStore(storageRoot);
|
|
198
|
+
const workflowDir = join(projectRoot, ".workflows", "solve-issue");
|
|
199
|
+
await mkdir(workflowDir, { recursive: true });
|
|
200
|
+
await writeFile(join(workflowDir, "index.yaml"), await createWorkflowYaml("solve-issue"));
|
|
201
|
+
|
|
202
|
+
const result = await cmdWorkflowShow(storageRoot, "solve-issue", projectRoot);
|
|
203
|
+
|
|
204
|
+
expect(result.hash).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
|
205
|
+
expect(result.payload.name).toBe("solve-issue");
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test("should resolve from legacy .workflow/ when .workflows/ is absent", async () => {
|
|
209
|
+
await makeUwfStore(storageRoot);
|
|
210
|
+
const legacyDir = join(projectRoot, ".workflow");
|
|
211
|
+
await mkdir(legacyDir, { recursive: true });
|
|
212
|
+
await writeFile(join(legacyDir, "solve-issue.yaml"), await createWorkflowYaml("solve-issue"));
|
|
213
|
+
|
|
214
|
+
const result = await cmdWorkflowShow(storageRoot, "solve-issue", projectRoot);
|
|
215
|
+
|
|
216
|
+
expect(result.hash).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
|
217
|
+
expect(result.payload.name).toBe("solve-issue");
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// ── Strategy 4: Global Registry Fallback ──────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
describe("Strategy 4: Global Registry Resolution", () => {
|
|
224
|
+
test("should resolve workflow from global registry when not found locally", async () => {
|
|
225
|
+
const uwf = await makeUwfStore(storageRoot);
|
|
226
|
+
const hash = await storeWorkflow(uwf, "deploy-pipeline");
|
|
227
|
+
saveWorkflowRegistry(uwf.varStore, "deploy-pipeline", hash);
|
|
228
|
+
|
|
229
|
+
const isolatedRoot = join(tmpDir, "isolated");
|
|
230
|
+
await mkdir(isolatedRoot, { recursive: true });
|
|
231
|
+
|
|
232
|
+
const result = await cmdWorkflowShow(storageRoot, "deploy-pipeline", isolatedRoot);
|
|
233
|
+
|
|
234
|
+
expect(result.hash).toBe(hash);
|
|
235
|
+
expect(result.name).toBe("deploy-pipeline"); // found in registry
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test("should fail when workflow not found in any strategy", async () => {
|
|
239
|
+
await makeUwfStore(storageRoot);
|
|
240
|
+
|
|
241
|
+
await expect(cmdWorkflowShow(storageRoot, "nonexistent", tmpDir)).rejects.toThrow();
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// ── Strategy Priority Order ───────────────────────────────────────────────────
|
|
246
|
+
|
|
247
|
+
describe("Resolution Priority", () => {
|
|
248
|
+
test("should use explicit file path over local discovery", async () => {
|
|
249
|
+
await makeUwfStore(storageRoot);
|
|
250
|
+
|
|
251
|
+
// Setup: Create workflow in .workflows/ AND as explicit file
|
|
252
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
253
|
+
await mkdir(workflowDir, { recursive: true });
|
|
254
|
+
await writeFile(
|
|
255
|
+
join(workflowDir, "solve-issue.yaml"),
|
|
256
|
+
await createWorkflowYaml("solve-issue", "discovery"),
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
const explicitPath = join(projectRoot, "custom-solve-issue.yaml");
|
|
260
|
+
await writeFile(explicitPath, await createWorkflowYaml("custom-solve-issue", "explicit"));
|
|
261
|
+
|
|
262
|
+
// Execute with explicit path
|
|
263
|
+
const result = await cmdWorkflowShow(storageRoot, explicitPath, projectRoot);
|
|
264
|
+
|
|
265
|
+
expect(result.payload.description).toBe("Test workflow (explicit)");
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("should use local discovery over global registry", async () => {
|
|
269
|
+
const uwf = await makeUwfStore(storageRoot);
|
|
270
|
+
|
|
271
|
+
// Setup: Register globally
|
|
272
|
+
const payload = makeMinimalPayload("solve-issue", "Test workflow (global)");
|
|
273
|
+
const globalHash = await uwf.store.cas.put(uwf.schemas.workflow, payload);
|
|
274
|
+
saveWorkflowRegistry(uwf.varStore, "solve-issue", globalHash);
|
|
275
|
+
|
|
276
|
+
// Setup: Create local .workflows/
|
|
277
|
+
const workflowDir = join(projectRoot, ".workflows");
|
|
278
|
+
await mkdir(workflowDir, { recursive: true });
|
|
279
|
+
const localYaml = await createWorkflowYaml("solve-issue", "local");
|
|
280
|
+
await writeFile(join(workflowDir, "solve-issue.yaml"), localYaml);
|
|
281
|
+
|
|
282
|
+
const result = await cmdWorkflowShow(storageRoot, "solve-issue", projectRoot);
|
|
283
|
+
|
|
284
|
+
expect(result.payload.description).toBe("Test workflow (local)");
|
|
285
|
+
});
|
|
286
|
+
});
|