@united-workforce/cli 0.1.1 → 0.2.1-rc.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 (71) hide show
  1. package/dist/__tests__/adapter-json-roundtrip.test.js +4 -1
  2. package/dist/__tests__/adapter-json-roundtrip.test.js.map +1 -1
  3. package/dist/__tests__/current-role.test.js +15 -3
  4. package/dist/__tests__/current-role.test.js.map +1 -1
  5. package/dist/__tests__/moderator-evaluate.test.js +20 -4
  6. package/dist/__tests__/moderator-evaluate.test.js.map +1 -1
  7. package/dist/__tests__/prompt.test.js +30 -42
  8. package/dist/__tests__/prompt.test.js.map +1 -1
  9. package/dist/__tests__/step-timing.test.js +8 -2
  10. package/dist/__tests__/step-timing.test.js.map +1 -1
  11. package/dist/__tests__/thread-location.test.js +15 -3
  12. package/dist/__tests__/thread-location.test.js.map +1 -1
  13. package/dist/__tests__/thread-resume.test.js +21 -6
  14. package/dist/__tests__/thread-resume.test.js.map +1 -1
  15. package/dist/__tests__/thread-show-status.test.js +10 -2
  16. package/dist/__tests__/thread-show-status.test.js.map +1 -1
  17. package/dist/__tests__/thread-start-cwd-cli.test.js +5 -1
  18. package/dist/__tests__/thread-start-cwd-cli.test.js.map +1 -1
  19. package/dist/__tests__/thread-suspend-step.test.js +4 -1
  20. package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
  21. package/dist/__tests__/thread-suspended-display.test.js +12 -3
  22. package/dist/__tests__/thread-suspended-display.test.js.map +1 -1
  23. package/dist/__tests__/validate-semantic.test.js +29 -12
  24. package/dist/__tests__/validate-semantic.test.js.map +1 -1
  25. package/dist/__tests__/workflow-resolution.test.js +4 -1
  26. package/dist/__tests__/workflow-resolution.test.js.map +1 -1
  27. package/dist/cli.js +5 -17
  28. package/dist/cli.js.map +1 -1
  29. package/dist/commands/prompt.d.ts +3 -4
  30. package/dist/commands/prompt.d.ts.map +1 -1
  31. package/dist/commands/prompt.js +120 -43
  32. package/dist/commands/prompt.js.map +1 -1
  33. package/dist/commands/thread.d.ts.map +1 -1
  34. package/dist/commands/thread.js +3 -7
  35. package/dist/commands/thread.js.map +1 -1
  36. package/dist/moderator/__tests__/evaluate.test.js +12 -12
  37. package/dist/moderator/__tests__/evaluate.test.js.map +1 -1
  38. package/dist/moderator/evaluate.d.ts.map +1 -1
  39. package/dist/moderator/evaluate.js +1 -7
  40. package/dist/moderator/evaluate.js.map +1 -1
  41. package/dist/validate-semantic.d.ts.map +1 -1
  42. package/dist/validate-semantic.js +4 -12
  43. package/dist/validate-semantic.js.map +1 -1
  44. package/dist/validate.js +3 -3
  45. package/dist/validate.js.map +1 -1
  46. package/package.json +3 -3
  47. package/src/__tests__/adapter-json-roundtrip.test.ts +4 -1
  48. package/src/__tests__/current-role.test.ts +15 -3
  49. package/src/__tests__/fixtures/e2e-count.workflow.yaml +2 -1
  50. package/src/__tests__/fixtures/e2e-linear.workflow.yaml +2 -1
  51. package/src/__tests__/fixtures/e2e-loop.workflow.yaml +2 -1
  52. package/src/__tests__/fixtures/e2e-mustache.workflow.yaml +2 -1
  53. package/src/__tests__/fixtures/e2e-suspend.workflow.yaml +2 -1
  54. package/src/__tests__/moderator-evaluate.test.ts +21 -4
  55. package/src/__tests__/prompt.test.ts +29 -46
  56. package/src/__tests__/step-timing.test.ts +8 -2
  57. package/src/__tests__/thread-location.test.ts +15 -3
  58. package/src/__tests__/thread-resume.test.ts +21 -6
  59. package/src/__tests__/thread-show-status.test.ts +10 -2
  60. package/src/__tests__/thread-start-cwd-cli.test.ts +5 -1
  61. package/src/__tests__/thread-suspend-step.test.ts +4 -1
  62. package/src/__tests__/thread-suspended-display.test.ts +12 -3
  63. package/src/__tests__/validate-semantic.test.ts +36 -16
  64. package/src/__tests__/workflow-resolution.test.ts +4 -1
  65. package/src/cli.ts +4 -20
  66. package/src/commands/prompt.ts +119 -44
  67. package/src/commands/thread.ts +3 -8
  68. package/src/moderator/__tests__/evaluate.test.ts +12 -12
  69. package/src/moderator/evaluate.ts +1 -6
  70. package/src/validate-semantic.ts +4 -13
  71. package/src/validate.ts +3 -3
@@ -6,11 +6,11 @@ describe("Edge prompt template variable resolution", () => {
6
6
  test("returns error when rendered prompt is empty string", () => {
7
7
  const graph = {
8
8
  $START: {
9
- _: { role: "classifier", prompt: "{{{userPrompt}}}", location: null },
9
+ new: { role: "classifier", prompt: "{{{userPrompt}}}", location: null },
10
10
  },
11
11
  };
12
12
 
13
- const result = evaluate(graph, "$START", {});
13
+ const result = evaluate(graph, "$START", { $status: "new" });
14
14
 
15
15
  expect(result.ok).toBe(false);
16
16
  if (!result.ok) {
@@ -22,11 +22,11 @@ describe("Edge prompt template variable resolution", () => {
22
22
  test("returns error when rendered prompt is whitespace-only", () => {
23
23
  const graph = {
24
24
  $START: {
25
- _: { role: "classifier", prompt: " {{{userPrompt}}} ", location: null },
25
+ new: { role: "classifier", prompt: " {{{userPrompt}}} ", location: null },
26
26
  },
27
27
  };
28
28
 
29
- const result = evaluate(graph, "$START", {});
29
+ const result = evaluate(graph, "$START", { $status: "new" });
30
30
 
31
31
  expect(result.ok).toBe(false);
32
32
  if (!result.ok) {
@@ -38,11 +38,11 @@ describe("Edge prompt template variable resolution", () => {
38
38
  test("succeeds when all template variables resolve to non-empty values", () => {
39
39
  const graph = {
40
40
  $START: {
41
- _: { role: "classifier", prompt: "{{{userPrompt}}}", location: null },
41
+ new: { role: "classifier", prompt: "{{{userPrompt}}}", location: null },
42
42
  },
43
43
  };
44
44
 
45
- const result = evaluate(graph, "$START", { userPrompt: "Fix the bug" });
45
+ const result = evaluate(graph, "$START", { $status: "new", userPrompt: "Fix the bug" });
46
46
 
47
47
  expect(result.ok).toBe(true);
48
48
  if (result.ok) {
@@ -53,11 +53,11 @@ describe("Edge prompt template variable resolution", () => {
53
53
  test("succeeds with static (no-variable) prompt", () => {
54
54
  const graph = {
55
55
  $START: {
56
- _: { role: "classifier", prompt: "Classify this input", location: null },
56
+ new: { role: "classifier", prompt: "Classify this input", location: null },
57
57
  },
58
58
  };
59
59
 
60
- const result = evaluate(graph, "$START", {});
60
+ const result = evaluate(graph, "$START", { $status: "new" });
61
61
 
62
62
  expect(result.ok).toBe(true);
63
63
  if (result.ok) {
@@ -68,11 +68,11 @@ describe("Edge prompt template variable resolution", () => {
68
68
  test("succeeds when prompt has mix of static text and unresolved variables", () => {
69
69
  const graph = {
70
70
  $START: {
71
- _: { role: "classifier", prompt: "Please handle: {{{userPrompt}}}", location: null },
71
+ new: { role: "classifier", prompt: "Please handle: {{{userPrompt}}}", location: null },
72
72
  },
73
73
  };
74
74
 
75
- const result = evaluate(graph, "$START", {});
75
+ const result = evaluate(graph, "$START", { $status: "new" });
76
76
 
77
77
  expect(result.ok).toBe(true);
78
78
  if (result.ok) {
@@ -83,11 +83,11 @@ describe("Edge prompt template variable resolution", () => {
83
83
  test("returns error when ALL variables missing and no static text remains", () => {
84
84
  const graph = {
85
85
  $START: {
86
- _: { role: "classifier", prompt: "{{{a}}}{{{b}}}", location: null },
86
+ new: { role: "classifier", prompt: "{{{a}}}{{{b}}}", location: null },
87
87
  },
88
88
  };
89
89
 
90
- const result = evaluate(graph, "$START", {});
90
+ const result = evaluate(graph, "$START", { $status: "new" });
91
91
 
92
92
  expect(result.ok).toBe(false);
93
93
  });
@@ -6,10 +6,7 @@ import type { EvaluateResult, Result } from "./types.js";
6
6
  // Disable HTML escaping — prompts are plain text, not HTML.
7
7
  mustache.escape = (text: string) => text;
8
8
 
9
- const START_ROLE = "$START";
10
9
  const SUSPEND_ROLE = "$SUSPEND";
11
- // $START is a special entry node with no agent output — it always uses this key.
12
- const START_STATUS = "_";
13
10
 
14
11
  type LastOutput = Record<string, unknown>;
15
12
 
@@ -21,9 +18,7 @@ export function evaluate(
21
18
  lastOutput: LastOutput,
22
19
  ): Result<EvaluateResult, Error> {
23
20
  let status: string;
24
- if (lastRole === START_ROLE) {
25
- status = START_STATUS;
26
- } else if (typeof lastOutput[STATUS_KEY] === "string") {
21
+ if (typeof lastOutput[STATUS_KEY] === "string") {
27
22
  status = lastOutput[STATUS_KEY] as string;
28
23
  } else {
29
24
  return {
@@ -97,9 +97,9 @@ function checkGraphStructure(payload: WorkflowPayload, errors: string[]): void {
97
97
  if (!graphNodes.has("$START")) {
98
98
  errors.push("$START must be defined in graph");
99
99
  } else {
100
- const startKeys = Object.keys(payload.graph.$START);
101
- if (startKeys.length !== 1 || startKeys[0] !== "_") {
102
- errors.push('$START must have exactly one edge with status "_"');
100
+ const startKeys = new Set(Object.keys(payload.graph.$START));
101
+ if (!startKeys.has("new") || !startKeys.has("resume")) {
102
+ errors.push('$START must have edges with statuses "new" and "resume"');
103
103
  }
104
104
  }
105
105
 
@@ -190,22 +190,13 @@ function checkOneOfDiscriminant(
190
190
  }
191
191
  }
192
192
 
193
- /** Check status-edge consistency for a user role. "_" is reserved for $START and rejected here. */
193
+ /** Check status-edge consistency for a user role. */
194
194
  function checkStatusEdges(
195
195
  roleName: string,
196
196
  graphKeys: Set<string>,
197
197
  statusSet: Set<string>,
198
198
  errors: string[],
199
199
  ): void {
200
- if (graphKeys.has("_")) {
201
- errors.push(`role "${roleName}" must use explicit $status keys in graph, not "_"`);
202
- return;
203
- }
204
- if (statusSet.has("_")) {
205
- errors.push(`role "${roleName}" $status enum must use explicit values, not "_"`);
206
- return;
207
- }
208
-
209
200
  const extraKeys = [...graphKeys].filter((k) => !statusSet.has(k));
210
201
  const missingKeys = [...statusSet].filter((k) => !graphKeys.has(k));
211
202
  if (extraKeys.length > 0) {
package/src/validate.ts CHANGED
@@ -57,13 +57,13 @@ function isGraph(value: unknown): boolean {
57
57
  if (!isRecord(value)) {
58
58
  return false;
59
59
  }
60
- return Object.entries(value).every(([node, statusMap]) => {
60
+ return Object.values(value).every((statusMap) => {
61
61
  if (!isRecord(statusMap)) {
62
62
  return false;
63
63
  }
64
64
  return Object.entries(statusMap).every(([status, target]) => {
65
- // "_" is only valid as a status key for the $START entry node.
66
- if (status === "_" && node !== "$START") {
65
+ // "_" is no longer a valid status key anywhere $START uses "new"/"resume".
66
+ if (status === "_") {
67
67
  return false;
68
68
  }
69
69
  return isTarget(target);