@renseiai/agentfactory 0.8.6 → 0.8.8

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 (175) hide show
  1. package/README.md +2 -2
  2. package/dist/src/config/repository-config.d.ts +14 -0
  3. package/dist/src/config/repository-config.d.ts.map +1 -1
  4. package/dist/src/config/repository-config.js +20 -0
  5. package/dist/src/governor/decision-engine.d.ts +7 -0
  6. package/dist/src/governor/decision-engine.d.ts.map +1 -1
  7. package/dist/src/governor/decision-engine.js +59 -1
  8. package/dist/src/governor/event-types.d.ts +18 -1
  9. package/dist/src/governor/event-types.d.ts.map +1 -1
  10. package/dist/src/governor/event-types.js +4 -0
  11. package/dist/src/governor/governor.d.ts +5 -1
  12. package/dist/src/governor/governor.d.ts.map +1 -1
  13. package/dist/src/governor/governor.js +6 -1
  14. package/dist/src/index.d.ts +1 -0
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/src/index.js +1 -0
  17. package/dist/src/merge-queue/adapters/github-native.d.ts +22 -0
  18. package/dist/src/merge-queue/adapters/github-native.d.ts.map +1 -0
  19. package/dist/src/merge-queue/adapters/github-native.js +243 -0
  20. package/dist/src/merge-queue/adapters/github-native.test.d.ts +2 -0
  21. package/dist/src/merge-queue/adapters/github-native.test.d.ts.map +1 -0
  22. package/dist/src/merge-queue/adapters/github-native.test.js +384 -0
  23. package/dist/src/merge-queue/index.d.ts +18 -0
  24. package/dist/src/merge-queue/index.d.ts.map +1 -0
  25. package/dist/src/merge-queue/index.js +28 -0
  26. package/dist/src/merge-queue/merge-queue.integration.test.d.ts +2 -0
  27. package/dist/src/merge-queue/merge-queue.integration.test.d.ts.map +1 -0
  28. package/dist/src/merge-queue/merge-queue.integration.test.js +128 -0
  29. package/dist/src/merge-queue/types.d.ts +48 -0
  30. package/dist/src/merge-queue/types.d.ts.map +1 -0
  31. package/dist/src/merge-queue/types.js +8 -0
  32. package/dist/src/orchestrator/activity-emitter.d.ts +3 -3
  33. package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -1
  34. package/dist/src/orchestrator/activity-emitter.js +1 -1
  35. package/dist/src/orchestrator/artifact-tracker.d.ts +93 -0
  36. package/dist/src/orchestrator/artifact-tracker.d.ts.map +1 -0
  37. package/dist/src/orchestrator/artifact-tracker.js +235 -0
  38. package/dist/src/orchestrator/artifact-tracker.test.d.ts +2 -0
  39. package/dist/src/orchestrator/artifact-tracker.test.d.ts.map +1 -0
  40. package/dist/src/orchestrator/artifact-tracker.test.js +189 -0
  41. package/dist/src/orchestrator/context-manager.d.ts +72 -0
  42. package/dist/src/orchestrator/context-manager.d.ts.map +1 -0
  43. package/dist/src/orchestrator/context-manager.js +120 -0
  44. package/dist/src/orchestrator/context-manager.test.d.ts +2 -0
  45. package/dist/src/orchestrator/context-manager.test.d.ts.map +1 -0
  46. package/dist/src/orchestrator/context-manager.test.js +137 -0
  47. package/dist/src/orchestrator/detect-work-type.test.js +25 -16
  48. package/dist/src/orchestrator/index.d.ts +12 -2
  49. package/dist/src/orchestrator/index.d.ts.map +1 -1
  50. package/dist/src/orchestrator/index.js +9 -1
  51. package/dist/src/orchestrator/issue-tracker-client.d.ts +103 -0
  52. package/dist/src/orchestrator/issue-tracker-client.d.ts.map +1 -0
  53. package/dist/src/orchestrator/issue-tracker-client.js +8 -0
  54. package/dist/src/orchestrator/log-analyzer.d.ts +19 -4
  55. package/dist/src/orchestrator/log-analyzer.d.ts.map +1 -1
  56. package/dist/src/orchestrator/log-analyzer.js +26 -50
  57. package/dist/src/orchestrator/orchestrator-utils.test.js +3 -0
  58. package/dist/src/orchestrator/orchestrator.d.ts +16 -2
  59. package/dist/src/orchestrator/orchestrator.d.ts.map +1 -1
  60. package/dist/src/orchestrator/orchestrator.js +449 -115
  61. package/dist/src/orchestrator/parse-work-result.d.ts +1 -1
  62. package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -1
  63. package/dist/src/orchestrator/parse-work-result.js +1 -1
  64. package/dist/src/orchestrator/session-logger.d.ts +1 -1
  65. package/dist/src/orchestrator/session-logger.d.ts.map +1 -1
  66. package/dist/src/orchestrator/state-recovery.d.ts +22 -3
  67. package/dist/src/orchestrator/state-recovery.d.ts.map +1 -1
  68. package/dist/src/orchestrator/state-recovery.js +55 -2
  69. package/dist/src/orchestrator/state-recovery.test.js +106 -2
  70. package/dist/src/orchestrator/state-types.d.ts +63 -1
  71. package/dist/src/orchestrator/state-types.d.ts.map +1 -1
  72. package/dist/src/orchestrator/state-types.js +5 -1
  73. package/dist/src/orchestrator/summary-builder.d.ts +47 -0
  74. package/dist/src/orchestrator/summary-builder.d.ts.map +1 -0
  75. package/dist/src/orchestrator/summary-builder.js +240 -0
  76. package/dist/src/orchestrator/summary-builder.test.d.ts +2 -0
  77. package/dist/src/orchestrator/summary-builder.test.d.ts.map +1 -0
  78. package/dist/src/orchestrator/summary-builder.test.js +236 -0
  79. package/dist/src/orchestrator/types.d.ts +24 -2
  80. package/dist/src/orchestrator/types.d.ts.map +1 -1
  81. package/dist/src/orchestrator/work-types.d.ts +50 -0
  82. package/dist/src/orchestrator/work-types.d.ts.map +1 -0
  83. package/dist/src/orchestrator/work-types.js +20 -0
  84. package/dist/src/templates/registry.d.ts +1 -1
  85. package/dist/src/templates/registry.test.js +2 -2
  86. package/dist/src/templates/renderer.d.ts +1 -1
  87. package/dist/src/templates/types.d.ts +6 -2
  88. package/dist/src/templates/types.d.ts.map +1 -1
  89. package/dist/src/templates/types.js +2 -0
  90. package/dist/src/templates/types.test.js +4 -3
  91. package/dist/src/tools/index.d.ts +0 -3
  92. package/dist/src/tools/index.d.ts.map +1 -1
  93. package/dist/src/tools/index.js +0 -2
  94. package/dist/src/workflow/branching-router.d.ts +38 -0
  95. package/dist/src/workflow/branching-router.d.ts.map +1 -0
  96. package/dist/src/workflow/branching-router.js +52 -0
  97. package/dist/src/workflow/branching-router.test.d.ts +2 -0
  98. package/dist/src/workflow/branching-router.test.d.ts.map +1 -0
  99. package/dist/src/workflow/branching-router.test.js +209 -0
  100. package/dist/src/workflow/duration.d.ts +28 -0
  101. package/dist/src/workflow/duration.d.ts.map +1 -0
  102. package/dist/src/workflow/duration.js +57 -0
  103. package/dist/src/workflow/duration.test.d.ts +2 -0
  104. package/dist/src/workflow/duration.test.d.ts.map +1 -0
  105. package/dist/src/workflow/duration.test.js +74 -0
  106. package/dist/src/workflow/expression/ast.d.ts +53 -0
  107. package/dist/src/workflow/expression/ast.d.ts.map +1 -0
  108. package/dist/src/workflow/expression/ast.js +8 -0
  109. package/dist/src/workflow/expression/context.d.ts +40 -0
  110. package/dist/src/workflow/expression/context.d.ts.map +1 -0
  111. package/dist/src/workflow/expression/context.js +37 -0
  112. package/dist/src/workflow/expression/evaluator.d.ts +28 -0
  113. package/dist/src/workflow/expression/evaluator.d.ts.map +1 -0
  114. package/dist/src/workflow/expression/evaluator.js +165 -0
  115. package/dist/src/workflow/expression/evaluator.test.d.ts +2 -0
  116. package/dist/src/workflow/expression/evaluator.test.d.ts.map +1 -0
  117. package/dist/src/workflow/expression/evaluator.test.js +792 -0
  118. package/dist/src/workflow/expression/expression.test.d.ts +2 -0
  119. package/dist/src/workflow/expression/expression.test.d.ts.map +1 -0
  120. package/dist/src/workflow/expression/expression.test.js +516 -0
  121. package/dist/src/workflow/expression/helpers.d.ts +21 -0
  122. package/dist/src/workflow/expression/helpers.d.ts.map +1 -0
  123. package/dist/src/workflow/expression/helpers.js +56 -0
  124. package/dist/src/workflow/expression/index.d.ts +55 -0
  125. package/dist/src/workflow/expression/index.d.ts.map +1 -0
  126. package/dist/src/workflow/expression/index.js +71 -0
  127. package/dist/src/workflow/expression/lexer.d.ts +37 -0
  128. package/dist/src/workflow/expression/lexer.d.ts.map +1 -0
  129. package/dist/src/workflow/expression/lexer.js +166 -0
  130. package/dist/src/workflow/expression/parser.d.ts +23 -0
  131. package/dist/src/workflow/expression/parser.d.ts.map +1 -0
  132. package/dist/src/workflow/expression/parser.js +181 -0
  133. package/dist/src/workflow/index.d.ts +21 -0
  134. package/dist/src/workflow/index.d.ts.map +1 -0
  135. package/dist/src/workflow/index.js +15 -0
  136. package/dist/src/workflow/retry-resolver.d.ts +51 -0
  137. package/dist/src/workflow/retry-resolver.d.ts.map +1 -0
  138. package/dist/src/workflow/retry-resolver.js +70 -0
  139. package/dist/src/workflow/retry-resolver.test.d.ts +2 -0
  140. package/dist/src/workflow/retry-resolver.test.d.ts.map +1 -0
  141. package/dist/src/workflow/retry-resolver.test.js +149 -0
  142. package/dist/src/workflow/transition-engine.d.ts +46 -0
  143. package/dist/src/workflow/transition-engine.d.ts.map +1 -0
  144. package/dist/src/workflow/transition-engine.js +113 -0
  145. package/dist/src/workflow/transition-engine.test.d.ts +2 -0
  146. package/dist/src/workflow/transition-engine.test.d.ts.map +1 -0
  147. package/dist/src/workflow/transition-engine.test.js +425 -0
  148. package/dist/src/workflow/workflow-loader.d.ts +21 -0
  149. package/dist/src/workflow/workflow-loader.d.ts.map +1 -0
  150. package/dist/src/workflow/workflow-loader.js +40 -0
  151. package/dist/src/workflow/workflow-loader.test.d.ts +2 -0
  152. package/dist/src/workflow/workflow-loader.test.d.ts.map +1 -0
  153. package/dist/src/workflow/workflow-loader.test.js +134 -0
  154. package/dist/src/workflow/workflow-registry.d.ts +97 -0
  155. package/dist/src/workflow/workflow-registry.d.ts.map +1 -0
  156. package/dist/src/workflow/workflow-registry.js +173 -0
  157. package/dist/src/workflow/workflow-registry.test.d.ts +2 -0
  158. package/dist/src/workflow/workflow-registry.test.d.ts.map +1 -0
  159. package/dist/src/workflow/workflow-registry.test.js +201 -0
  160. package/dist/src/workflow/workflow-types.d.ts +442 -0
  161. package/dist/src/workflow/workflow-types.d.ts.map +1 -0
  162. package/dist/src/workflow/workflow-types.js +113 -0
  163. package/dist/src/workflow/workflow-types.test.d.ts +2 -0
  164. package/dist/src/workflow/workflow-types.test.d.ts.map +1 -0
  165. package/dist/src/workflow/workflow-types.test.js +440 -0
  166. package/package.json +3 -4
  167. package/dist/src/linear-cli.d.ts +0 -38
  168. package/dist/src/linear-cli.d.ts.map +0 -1
  169. package/dist/src/linear-cli.js +0 -674
  170. package/dist/src/tools/linear-runner.d.ts +0 -34
  171. package/dist/src/tools/linear-runner.d.ts.map +0 -1
  172. package/dist/src/tools/linear-runner.js +0 -700
  173. package/dist/src/tools/plugins/linear.d.ts +0 -9
  174. package/dist/src/tools/plugins/linear.d.ts.map +0 -1
  175. package/dist/src/tools/plugins/linear.js +0 -138
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Expression AST Node Definitions
3
+ *
4
+ * Typed AST nodes for parsed condition expressions from WorkflowDefinition
5
+ * `branching[].condition` fields. Uses discriminated unions with a literal
6
+ * `type` field for exhaustive pattern matching.
7
+ */
8
+ export {};
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Evaluation Context
3
+ *
4
+ * Defines the sandboxed context in which expression ASTs are evaluated.
5
+ * The context provides variable bindings and registered helper functions,
6
+ * with no access to globals, prototypes, or dynamic code execution.
7
+ */
8
+ import type { GovernorIssue } from '../../governor/governor-types.js';
9
+ /**
10
+ * The sandboxed evaluation context passed to the expression evaluator.
11
+ *
12
+ * - `variables` holds named values that `VariableRef` nodes resolve against.
13
+ * - `functions` holds callable helpers that `FunctionCall` nodes invoke.
14
+ */
15
+ export interface EvaluationContext {
16
+ /** Variable bindings — e.g., { isParentIssue: true, priority: 3 } */
17
+ readonly variables: Record<string, unknown>;
18
+ /** Registered helper functions */
19
+ readonly functions: Record<string, (...args: unknown[]) => unknown>;
20
+ }
21
+ export interface BuildContextOptions {
22
+ /** Whether the issue has sub-issues (i.e., it is a parent issue) */
23
+ hasSubIssues?: boolean;
24
+ }
25
+ /**
26
+ * Build an EvaluationContext from a GovernorIssue and optional phase state.
27
+ *
28
+ * This is the primary way to create contexts for condition evaluation
29
+ * during workflow transitions. It:
30
+ * 1. Extracts well-known variables from the issue (status, labels, etc.)
31
+ * 2. Merges in phase-state booleans (researchCompleted, etc.)
32
+ * 3. Registers all built-in helper functions
33
+ *
34
+ * @param issue - The issue being evaluated.
35
+ * @param phaseState - Optional map of phase completion flags.
36
+ * @param opts - Additional context not on the issue itself.
37
+ * @returns A fully populated EvaluationContext.
38
+ */
39
+ export declare function buildEvaluationContext(issue: GovernorIssue, phaseState?: Record<string, boolean>, opts?: BuildContextOptions): EvaluationContext;
40
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAOrE;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC3C,kCAAkC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAA;CACpE;AAMD,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,aAAa,EACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,IAAI,CAAC,EAAE,mBAAmB,GACzB,iBAAiB,CAkBnB"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Evaluation Context
3
+ *
4
+ * Defines the sandboxed context in which expression ASTs are evaluated.
5
+ * The context provides variable bindings and registered helper functions,
6
+ * with no access to globals, prototypes, or dynamic code execution.
7
+ */
8
+ import { createBuiltinHelpers } from './helpers.js';
9
+ /**
10
+ * Build an EvaluationContext from a GovernorIssue and optional phase state.
11
+ *
12
+ * This is the primary way to create contexts for condition evaluation
13
+ * during workflow transitions. It:
14
+ * 1. Extracts well-known variables from the issue (status, labels, etc.)
15
+ * 2. Merges in phase-state booleans (researchCompleted, etc.)
16
+ * 3. Registers all built-in helper functions
17
+ *
18
+ * @param issue - The issue being evaluated.
19
+ * @param phaseState - Optional map of phase completion flags.
20
+ * @param opts - Additional context not on the issue itself.
21
+ * @returns A fully populated EvaluationContext.
22
+ */
23
+ export function buildEvaluationContext(issue, phaseState, opts) {
24
+ const hasSubIssues = opts?.hasSubIssues ?? false;
25
+ const variables = {
26
+ // Issue-derived variables
27
+ isParentIssue: hasSubIssues,
28
+ labels: issue.labels,
29
+ status: issue.status,
30
+ priority: 0, // GovernorIssue doesn't carry priority; default to 0
31
+ // Spread phase-state booleans so expressions like
32
+ // `researchCompleted and not backlogCreationCompleted` work directly.
33
+ ...phaseState,
34
+ };
35
+ const functions = createBuiltinHelpers(issue, { hasSubIssues });
36
+ return { variables, functions };
37
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Expression Evaluator (Tree-Walking)
3
+ *
4
+ * Walks a parsed AST and produces a result value within a sandboxed
5
+ * EvaluationContext. No `eval()`, `new Function()`, or dynamic code
6
+ * execution is used — evaluation is a pure recursive descent over the
7
+ * typed AST nodes.
8
+ */
9
+ import type { ASTNode } from './ast.js';
10
+ import type { EvaluationContext } from './context.js';
11
+ /**
12
+ * Error thrown when expression evaluation fails at runtime.
13
+ *
14
+ * Examples: unknown function name, type mismatch in numeric comparison.
15
+ */
16
+ export declare class EvaluationError extends Error {
17
+ constructor(message: string);
18
+ }
19
+ /**
20
+ * Evaluate an AST node within the given context.
21
+ *
22
+ * @param ast - The AST node to evaluate.
23
+ * @param context - The sandboxed evaluation context.
24
+ * @returns The result of evaluating the node.
25
+ * @throws {EvaluationError} on unknown functions or type mismatches.
26
+ */
27
+ export declare function evaluate(ast: ASTNode, context: EvaluationContext): unknown;
28
+ //# sourceMappingURL=evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAMrD;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAiBD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CA6D1E"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Expression Evaluator (Tree-Walking)
3
+ *
4
+ * Walks a parsed AST and produces a result value within a sandboxed
5
+ * EvaluationContext. No `eval()`, `new Function()`, or dynamic code
6
+ * execution is used — evaluation is a pure recursive descent over the
7
+ * typed AST nodes.
8
+ */
9
+ // ---------------------------------------------------------------------------
10
+ // EvaluationError
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Error thrown when expression evaluation fails at runtime.
14
+ *
15
+ * Examples: unknown function name, type mismatch in numeric comparison.
16
+ */
17
+ export class EvaluationError extends Error {
18
+ constructor(message) {
19
+ super(message);
20
+ this.name = 'EvaluationError';
21
+ }
22
+ }
23
+ // ---------------------------------------------------------------------------
24
+ // Helpers
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * Coerce an arbitrary value to a boolean using JavaScript truthiness rules.
28
+ */
29
+ function toBool(value) {
30
+ return Boolean(value);
31
+ }
32
+ // ---------------------------------------------------------------------------
33
+ // Evaluator
34
+ // ---------------------------------------------------------------------------
35
+ /**
36
+ * Evaluate an AST node within the given context.
37
+ *
38
+ * @param ast - The AST node to evaluate.
39
+ * @param context - The sandboxed evaluation context.
40
+ * @returns The result of evaluating the node.
41
+ * @throws {EvaluationError} on unknown functions or type mismatches.
42
+ */
43
+ export function evaluate(ast, context) {
44
+ switch (ast.type) {
45
+ // -------------------------------------------------------------------
46
+ // Literals — return value directly
47
+ // -------------------------------------------------------------------
48
+ case 'BooleanLiteral':
49
+ return ast.value;
50
+ case 'StringLiteral':
51
+ return ast.value;
52
+ case 'NumberLiteral':
53
+ return ast.value;
54
+ // -------------------------------------------------------------------
55
+ // Variable reference — look up in context, default to false
56
+ // -------------------------------------------------------------------
57
+ case 'VariableRef': {
58
+ const value = context.variables[ast.name];
59
+ // Undefined variables resolve to `false` (no crash)
60
+ if (value === undefined) {
61
+ return false;
62
+ }
63
+ return value;
64
+ }
65
+ // -------------------------------------------------------------------
66
+ // Unary operator
67
+ // -------------------------------------------------------------------
68
+ case 'UnaryOp': {
69
+ // Currently only 'not' is supported
70
+ const operand = evaluate(ast.operand, context);
71
+ return !toBool(operand);
72
+ }
73
+ // -------------------------------------------------------------------
74
+ // Binary operator
75
+ // -------------------------------------------------------------------
76
+ case 'BinaryOp':
77
+ return evaluateBinaryOp(ast.operator, ast.left, ast.right, context);
78
+ // -------------------------------------------------------------------
79
+ // Function call
80
+ // -------------------------------------------------------------------
81
+ case 'FunctionCall': {
82
+ const fn = context.functions[ast.name];
83
+ if (!fn) {
84
+ throw new EvaluationError(`Unknown function '${ast.name}'. Available functions: ${Object.keys(context.functions).join(', ') || '(none)'}`);
85
+ }
86
+ const args = ast.args.map((arg) => evaluate(arg, context));
87
+ return fn(...args);
88
+ }
89
+ default: {
90
+ // Exhaustive check — should never reach here with a well-typed AST
91
+ const _exhaustive = ast;
92
+ throw new EvaluationError(`Unknown AST node type: ${_exhaustive.type}`);
93
+ }
94
+ }
95
+ }
96
+ // ---------------------------------------------------------------------------
97
+ // Binary operator evaluation
98
+ // ---------------------------------------------------------------------------
99
+ function evaluateBinaryOp(operator, left, right, context) {
100
+ switch (operator) {
101
+ // Short-circuit logical operators
102
+ case 'and': {
103
+ const leftVal = evaluate(left, context);
104
+ if (!toBool(leftVal))
105
+ return leftVal;
106
+ return evaluate(right, context);
107
+ }
108
+ case 'or': {
109
+ const leftVal = evaluate(left, context);
110
+ if (toBool(leftVal))
111
+ return leftVal;
112
+ return evaluate(right, context);
113
+ }
114
+ // Equality — works across all types
115
+ case 'eq': {
116
+ const leftVal = evaluate(left, context);
117
+ const rightVal = evaluate(right, context);
118
+ return leftVal === rightVal;
119
+ }
120
+ case 'neq': {
121
+ const leftVal = evaluate(left, context);
122
+ const rightVal = evaluate(right, context);
123
+ return leftVal !== rightVal;
124
+ }
125
+ // Ordering comparisons — require matching numeric types
126
+ case 'gt':
127
+ case 'lt':
128
+ case 'gte':
129
+ case 'lte': {
130
+ const leftVal = evaluate(left, context);
131
+ const rightVal = evaluate(right, context);
132
+ return evaluateOrdering(operator, leftVal, rightVal);
133
+ }
134
+ default:
135
+ throw new EvaluationError(`Unknown operator '${operator}'`);
136
+ }
137
+ }
138
+ function evaluateOrdering(operator, left, right) {
139
+ // Both must be numbers or both must be strings for ordering comparisons
140
+ if (typeof left === 'number' && typeof right === 'number') {
141
+ switch (operator) {
142
+ case 'gt': return left > right;
143
+ case 'lt': return left < right;
144
+ case 'gte': return left >= right;
145
+ case 'lte': return left <= right;
146
+ }
147
+ }
148
+ if (typeof left === 'string' && typeof right === 'string') {
149
+ switch (operator) {
150
+ case 'gt': return left > right;
151
+ case 'lt': return left < right;
152
+ case 'gte': return left >= right;
153
+ case 'lte': return left <= right;
154
+ }
155
+ }
156
+ throw new EvaluationError(`Cannot compare ${typeLabel(left)} and ${typeLabel(right)} with '${operator}'. ` +
157
+ `Both operands must be numbers or both must be strings.`);
158
+ }
159
+ function typeLabel(value) {
160
+ if (value === null)
161
+ return 'null';
162
+ if (Array.isArray(value))
163
+ return 'array';
164
+ return typeof value;
165
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=evaluator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.test.d.ts","sourceRoot":"","sources":["../../../../src/workflow/expression/evaluator.test.ts"],"names":[],"mappings":""}