@shipfox/expression 1.1.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 (140) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +117 -0
  3. package/dist/evaluator/errors.d.ts +8 -0
  4. package/dist/evaluator/errors.d.ts.map +1 -0
  5. package/dist/evaluator/errors.js +13 -0
  6. package/dist/evaluator/errors.js.map +1 -0
  7. package/dist/evaluator/evaluate-workflow-expression.d.ts +11 -0
  8. package/dist/evaluator/evaluate-workflow-expression.d.ts.map +1 -0
  9. package/dist/evaluator/evaluate-workflow-expression.js +30 -0
  10. package/dist/evaluator/evaluate-workflow-expression.js.map +1 -0
  11. package/dist/evaluator/index.d.ts +3 -0
  12. package/dist/evaluator/index.d.ts.map +1 -0
  13. package/dist/evaluator/index.js +4 -0
  14. package/dist/evaluator/index.js.map +1 -0
  15. package/dist/expression/create-workflow-expression.d.ts +7 -0
  16. package/dist/expression/create-workflow-expression.d.ts.map +1 -0
  17. package/dist/expression/create-workflow-expression.js +156 -0
  18. package/dist/expression/create-workflow-expression.js.map +1 -0
  19. package/dist/expression/errors.d.ts +12 -0
  20. package/dist/expression/errors.d.ts.map +1 -0
  21. package/dist/expression/errors.js +13 -0
  22. package/dist/expression/errors.js.map +1 -0
  23. package/dist/expression/index.d.ts +4 -0
  24. package/dist/expression/index.d.ts.map +1 -0
  25. package/dist/expression/index.js +4 -0
  26. package/dist/expression/index.js.map +1 -0
  27. package/dist/expression/workflow-expression.d.ts +33 -0
  28. package/dist/expression/workflow-expression.d.ts.map +1 -0
  29. package/dist/expression/workflow-expression.js +3 -0
  30. package/dist/expression/workflow-expression.js.map +1 -0
  31. package/dist/index.d.ts +27 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +25 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/outputs/index.d.ts +2 -0
  36. package/dist/outputs/index.d.ts.map +1 -0
  37. package/dist/outputs/index.js +3 -0
  38. package/dist/outputs/index.js.map +1 -0
  39. package/dist/outputs/output-declarations.d.ts +39 -0
  40. package/dist/outputs/output-declarations.d.ts.map +1 -0
  41. package/dist/outputs/output-declarations.js +295 -0
  42. package/dist/outputs/output-declarations.js.map +1 -0
  43. package/dist/plan/bare-reference.d.ts +2 -0
  44. package/dist/plan/bare-reference.d.ts.map +1 -0
  45. package/dist/plan/bare-reference.js +23 -0
  46. package/dist/plan/bare-reference.js.map +1 -0
  47. package/dist/plan/context-key-access.d.ts +25 -0
  48. package/dist/plan/context-key-access.d.ts.map +1 -0
  49. package/dist/plan/context-key-access.js +249 -0
  50. package/dist/plan/context-key-access.js.map +1 -0
  51. package/dist/plan/evaluate-planned-predicate.d.ts +14 -0
  52. package/dist/plan/evaluate-planned-predicate.d.ts.map +1 -0
  53. package/dist/plan/evaluate-planned-predicate.js +31 -0
  54. package/dist/plan/evaluate-planned-predicate.js.map +1 -0
  55. package/dist/plan/evaluation-trace.d.ts +44 -0
  56. package/dist/plan/evaluation-trace.d.ts.map +1 -0
  57. package/dist/plan/evaluation-trace.js +95 -0
  58. package/dist/plan/evaluation-trace.js.map +1 -0
  59. package/dist/plan/extract-exact-context-roots.d.ts +2 -0
  60. package/dist/plan/extract-exact-context-roots.d.ts.map +1 -0
  61. package/dist/plan/extract-exact-context-roots.js +114 -0
  62. package/dist/plan/extract-exact-context-roots.js.map +1 -0
  63. package/dist/plan/fill.d.ts +3 -0
  64. package/dist/plan/fill.d.ts.map +1 -0
  65. package/dist/plan/fill.js +8 -0
  66. package/dist/plan/fill.js.map +1 -0
  67. package/dist/plan/freeze-run-command.d.ts +17 -0
  68. package/dist/plan/freeze-run-command.d.ts.map +1 -0
  69. package/dist/plan/freeze-run-command.js +33 -0
  70. package/dist/plan/freeze-run-command.js.map +1 -0
  71. package/dist/plan/freeze.d.ts +48 -0
  72. package/dist/plan/freeze.d.ts.map +1 -0
  73. package/dist/plan/freeze.js +148 -0
  74. package/dist/plan/freeze.js.map +1 -0
  75. package/dist/plan/plan-field.d.ts +26 -0
  76. package/dist/plan/plan-field.d.ts.map +1 -0
  77. package/dist/plan/plan-field.js +63 -0
  78. package/dist/plan/plan-field.js.map +1 -0
  79. package/dist/plan/predicate-shape.d.ts +2 -0
  80. package/dist/plan/predicate-shape.d.ts.map +1 -0
  81. package/dist/plan/predicate-shape.js +45 -0
  82. package/dist/plan/predicate-shape.js.map +1 -0
  83. package/dist/plan/resolved-field.d.ts +17 -0
  84. package/dist/plan/resolved-field.d.ts.map +1 -0
  85. package/dist/plan/resolved-field.js +3 -0
  86. package/dist/plan/resolved-field.js.map +1 -0
  87. package/dist/plan/route-expression.d.ts +9 -0
  88. package/dist/plan/route-expression.d.ts.map +1 -0
  89. package/dist/plan/route-expression.js +46 -0
  90. package/dist/plan/route-expression.js.map +1 -0
  91. package/dist/plan/validate-server-evaluable.d.ts +14 -0
  92. package/dist/plan/validate-server-evaluable.d.ts.map +1 -0
  93. package/dist/plan/validate-server-evaluable.js +20 -0
  94. package/dist/plan/validate-server-evaluable.js.map +1 -0
  95. package/dist/resolver/coerce-workflow-value-to-string.d.ts +2 -0
  96. package/dist/resolver/coerce-workflow-value-to-string.d.ts.map +1 -0
  97. package/dist/resolver/coerce-workflow-value-to-string.js +16 -0
  98. package/dist/resolver/coerce-workflow-value-to-string.js.map +1 -0
  99. package/dist/resolver/errors.d.ts +10 -0
  100. package/dist/resolver/errors.d.ts.map +1 -0
  101. package/dist/resolver/errors.js +12 -0
  102. package/dist/resolver/errors.js.map +1 -0
  103. package/dist/run/hoist-run-command.d.ts +33 -0
  104. package/dist/run/hoist-run-command.d.ts.map +1 -0
  105. package/dist/run/hoist-run-command.js +79 -0
  106. package/dist/run/hoist-run-command.js.map +1 -0
  107. package/dist/run/shell-quoting.d.ts +24 -0
  108. package/dist/run/shell-quoting.d.ts.map +1 -0
  109. package/dist/run/shell-quoting.js +364 -0
  110. package/dist/run/shell-quoting.js.map +1 -0
  111. package/dist/template/errors.d.ts +14 -0
  112. package/dist/template/errors.d.ts.map +1 -0
  113. package/dist/template/errors.js +14 -0
  114. package/dist/template/errors.js.map +1 -0
  115. package/dist/template/extract-cel-context-roots.d.ts +2 -0
  116. package/dist/template/extract-cel-context-roots.d.ts.map +1 -0
  117. package/dist/template/extract-cel-context-roots.js +110 -0
  118. package/dist/template/extract-cel-context-roots.js.map +1 -0
  119. package/dist/template/extract-cel-untrusted-path-accesses.d.ts +5 -0
  120. package/dist/template/extract-cel-untrusted-path-accesses.d.ts.map +1 -0
  121. package/dist/template/extract-cel-untrusted-path-accesses.js +140 -0
  122. package/dist/template/extract-cel-untrusted-path-accesses.js.map +1 -0
  123. package/dist/template/parse-workflow-template.d.ts +3 -0
  124. package/dist/template/parse-workflow-template.d.ts.map +1 -0
  125. package/dist/template/parse-workflow-template.js +111 -0
  126. package/dist/template/parse-workflow-template.js.map +1 -0
  127. package/dist/template/scan-cel-token.d.ts +3 -0
  128. package/dist/template/scan-cel-token.d.ts.map +1 -0
  129. package/dist/template/scan-cel-token.js +55 -0
  130. package/dist/template/scan-cel-token.js.map +1 -0
  131. package/dist/template/template-segment.d.ts +12 -0
  132. package/dist/template/template-segment.d.ts.map +1 -0
  133. package/dist/template/template-segment.js +3 -0
  134. package/dist/template/template-segment.js.map +1 -0
  135. package/dist/tsconfig.test.tsbuildinfo +1 -0
  136. package/dist/workflow-context/workflow-context.d.ts +458 -0
  137. package/dist/workflow-context/workflow-context.d.ts.map +1 -0
  138. package/dist/workflow-context/workflow-context.js +664 -0
  139. package/dist/workflow-context/workflow-context.js.map +1 -0
  140. package/package.json +49 -0
@@ -0,0 +1,249 @@
1
+ import { parse as parseCel } from '@marcbachmann/cel-js';
2
+ import { workflowContextRootRequiresLiteralKey } from '../workflow-context/workflow-context.js';
3
+ const binaryOperators = new Set([
4
+ '!=',
5
+ '==',
6
+ 'in',
7
+ '+',
8
+ '-',
9
+ '*',
10
+ '/',
11
+ '%',
12
+ '<',
13
+ '<=',
14
+ '>',
15
+ '>='
16
+ ]);
17
+ const comprehensionMethods = new Set([
18
+ 'all',
19
+ 'exists',
20
+ 'exists_one',
21
+ 'filter',
22
+ 'map'
23
+ ]);
24
+ export function analyzeContextKeyAccess(expression) {
25
+ const source = typeof expression === 'string' ? expression : expression.source;
26
+ const references = [];
27
+ const violations = [];
28
+ collectContextAccesses(parseCel(source).ast, source, new Set(), {
29
+ shouldRecord: (chain)=>workflowContextRootRequiresLiteralKey(chain.root),
30
+ record: (chain, expressionSource)=>recordLiteralKeyRootAccess(chain, expressionSource, references, violations)
31
+ });
32
+ return {
33
+ references,
34
+ violations
35
+ };
36
+ }
37
+ export function analyzeContextRootKeyAccess(expression, roots) {
38
+ const source = typeof expression === 'string' ? expression : expression.source;
39
+ const references = [];
40
+ const violations = [];
41
+ const selectedRoots = new Set(roots);
42
+ collectContextAccesses(parseCel(source).ast, source, new Set(), {
43
+ shouldRecord: (chain)=>selectedRoots.has(chain.root),
44
+ record: (chain, expressionSource)=>recordContextRootKeyAccess(chain, expressionSource, references, violations)
45
+ });
46
+ return {
47
+ references,
48
+ violations
49
+ };
50
+ }
51
+ function collectContextAccesses(node, source, scopedIdentifiers, visitor) {
52
+ if (binaryOperators.has(node.op) || node.op === '||' || node.op === '&&') {
53
+ collectBinaryContextAccesses(node.args, source, scopedIdentifiers, visitor);
54
+ return;
55
+ }
56
+ const chain = accessChain(node, scopedIdentifiers);
57
+ if (chain && visitor.shouldRecord(chain)) {
58
+ visitor.record(chain, source);
59
+ return;
60
+ }
61
+ switch(node.op){
62
+ case 'id':
63
+ case 'value':
64
+ return;
65
+ case '.':
66
+ case '.?':
67
+ collectContextAccesses(node.args[0], source, scopedIdentifiers, visitor);
68
+ return;
69
+ case '[]':
70
+ case '[?]':
71
+ collectBinaryContextAccesses(node.args, source, scopedIdentifiers, visitor);
72
+ return;
73
+ case 'call':
74
+ for (const argument of node.args[1]){
75
+ collectContextAccesses(argument, source, scopedIdentifiers, visitor);
76
+ }
77
+ return;
78
+ case 'rcall':
79
+ {
80
+ const [method, receiver, args] = node.args;
81
+ collectContextAccesses(receiver, source, scopedIdentifiers, visitor);
82
+ const binding = bindComprehensionAlias(method, args, scopedIdentifiers);
83
+ for (const argument of args.slice(binding.skipArgs)){
84
+ collectContextAccesses(argument, source, binding.scopedIdentifiers, visitor);
85
+ }
86
+ return;
87
+ }
88
+ case 'list':
89
+ for (const element of node.args){
90
+ collectContextAccesses(element, source, scopedIdentifiers, visitor);
91
+ }
92
+ return;
93
+ case 'map':
94
+ for (const [key, value] of node.args){
95
+ if (key.op !== 'id') {
96
+ collectContextAccesses(key, source, scopedIdentifiers, visitor);
97
+ }
98
+ collectContextAccesses(value, source, scopedIdentifiers, visitor);
99
+ }
100
+ return;
101
+ case '?:':
102
+ collectContextAccesses(node.args[0], source, scopedIdentifiers, visitor);
103
+ collectContextAccesses(node.args[1], source, scopedIdentifiers, visitor);
104
+ collectContextAccesses(node.args[2], source, scopedIdentifiers, visitor);
105
+ return;
106
+ case '!_':
107
+ case '-_':
108
+ collectContextAccesses(node.args, source, scopedIdentifiers, visitor);
109
+ return;
110
+ }
111
+ throw new Error(`Unsupported CEL AST operator: ${node.op}`);
112
+ }
113
+ function collectBinaryContextAccesses([left, right], source, scopedIdentifiers, visitor) {
114
+ collectContextAccesses(left, source, scopedIdentifiers, visitor);
115
+ collectContextAccesses(right, source, scopedIdentifiers, visitor);
116
+ }
117
+ function recordLiteralKeyRootAccess(chain, source, references, violations) {
118
+ if (chain.computed) {
119
+ violations.push({
120
+ root: chain.root,
121
+ source
122
+ });
123
+ return;
124
+ }
125
+ if (chain.root === 'vars' && chain.segments.length === 1) {
126
+ const key = chain.segments[0];
127
+ if (key === undefined) throw new Error('Expected vars key segment');
128
+ references.push({
129
+ root: chain.root,
130
+ key
131
+ });
132
+ return;
133
+ }
134
+ if (chain.root === 'secrets' && chain.segments.length === 1) {
135
+ const key = chain.segments[0];
136
+ if (key === undefined) throw new Error('Expected secret key segment');
137
+ references.push({
138
+ root: chain.root,
139
+ key
140
+ });
141
+ return;
142
+ }
143
+ if (chain.root === 'secrets' && chain.segments.length === 2) {
144
+ const store = chain.segments[0];
145
+ const key = chain.segments[1];
146
+ if (store === undefined || key === undefined) {
147
+ throw new Error('Expected secret store and key segments');
148
+ }
149
+ references.push({
150
+ root: chain.root,
151
+ store,
152
+ key
153
+ });
154
+ return;
155
+ }
156
+ violations.push({
157
+ root: chain.root,
158
+ source
159
+ });
160
+ }
161
+ function recordContextRootKeyAccess(chain, source, references, violations) {
162
+ const [key] = chain.segments;
163
+ if (chain.computed || key === undefined) {
164
+ violations.push({
165
+ root: chain.root,
166
+ source
167
+ });
168
+ return;
169
+ }
170
+ references.push({
171
+ root: chain.root,
172
+ key
173
+ });
174
+ }
175
+ function accessChain(node, scopedIdentifiers) {
176
+ switch(node.op){
177
+ case 'id':
178
+ return scopedIdentifiers.has(node.args) ? undefined : {
179
+ root: node.args,
180
+ segments: [],
181
+ computed: false
182
+ };
183
+ case '.':
184
+ {
185
+ const target = accessChain(node.args[0], scopedIdentifiers);
186
+ if (target === undefined) return undefined;
187
+ return {
188
+ ...target,
189
+ segments: [
190
+ ...target.segments,
191
+ node.args[1]
192
+ ]
193
+ };
194
+ }
195
+ case '.?':
196
+ {
197
+ const target = accessChain(node.args[0], scopedIdentifiers);
198
+ if (target === undefined) return undefined;
199
+ return {
200
+ ...target,
201
+ segments: [
202
+ ...target.segments,
203
+ node.args[1]
204
+ ],
205
+ computed: true
206
+ };
207
+ }
208
+ case '[]':
209
+ case '[?]':
210
+ {
211
+ const target = accessChain(node.args[0], scopedIdentifiers);
212
+ if (target === undefined) return undefined;
213
+ const literalSegment = literalStringValue(node.args[1]);
214
+ return {
215
+ ...target,
216
+ segments: literalSegment === undefined ? target.segments : [
217
+ ...target.segments,
218
+ literalSegment
219
+ ],
220
+ computed: true
221
+ };
222
+ }
223
+ default:
224
+ return undefined;
225
+ }
226
+ }
227
+ function literalStringValue(node) {
228
+ return node.op === 'value' && typeof node.args === 'string' ? node.args : undefined;
229
+ }
230
+ function bindComprehensionAlias(method, args, scopedIdentifiers) {
231
+ if (!comprehensionMethods.has(method)) return {
232
+ scopedIdentifiers,
233
+ skipArgs: 0
234
+ };
235
+ const [alias] = args;
236
+ if (alias?.op !== 'id') return {
237
+ scopedIdentifiers,
238
+ skipArgs: 0
239
+ };
240
+ return {
241
+ scopedIdentifiers: new Set([
242
+ ...scopedIdentifiers,
243
+ alias.args
244
+ ]),
245
+ skipArgs: 1
246
+ };
247
+ }
248
+
249
+ //# sourceMappingURL=context-key-access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plan/context-key-access.ts"],"sourcesContent":["import {type ASTNode, type BinaryOperator, parse as parseCel} from '@marcbachmann/cel-js';\nimport type {WorkflowExpression} from '../expression/workflow-expression.js';\nimport {workflowContextRootRequiresLiteralKey} from '../workflow-context/workflow-context.js';\n\nconst binaryOperators = new Set<BinaryOperator>([\n '!=',\n '==',\n 'in',\n '+',\n '-',\n '*',\n '/',\n '%',\n '<',\n '<=',\n '>',\n '>=',\n]);\n\nconst comprehensionMethods = new Set(['all', 'exists', 'exists_one', 'filter', 'map']);\n\nexport interface ContextKeyAccessReference {\n readonly root: 'vars' | 'secrets';\n readonly store?: string;\n readonly key: string;\n}\n\nexport interface ContextKeyAccessViolation {\n readonly root: string;\n readonly source: string;\n}\n\nexport interface ContextKeyAccessAnalysis {\n readonly references: readonly ContextKeyAccessReference[];\n readonly violations: readonly ContextKeyAccessViolation[];\n}\n\nexport interface ContextRootKeyAccessReference {\n readonly root: string;\n readonly key: string;\n}\n\nexport interface ContextRootKeyAccessAnalysis {\n readonly references: readonly ContextRootKeyAccessReference[];\n readonly violations: readonly ContextKeyAccessViolation[];\n}\n\ninterface AccessChain {\n readonly root: string;\n readonly segments: readonly string[];\n readonly computed: boolean;\n}\n\ninterface ContextAccessVisitor {\n readonly shouldRecord: (chain: AccessChain) => boolean;\n readonly record: (chain: AccessChain, source: string) => void;\n}\n\nexport function analyzeContextKeyAccess(\n expression: WorkflowExpression | string,\n): ContextKeyAccessAnalysis {\n const source = typeof expression === 'string' ? expression : expression.source;\n const references: ContextKeyAccessReference[] = [];\n const violations: ContextKeyAccessViolation[] = [];\n\n collectContextAccesses(parseCel(source).ast, source, new Set(), {\n shouldRecord: (chain) => workflowContextRootRequiresLiteralKey(chain.root),\n record: (chain, expressionSource) =>\n recordLiteralKeyRootAccess(chain, expressionSource, references, violations),\n });\n\n return {references, violations};\n}\n\nexport function analyzeContextRootKeyAccess(\n expression: WorkflowExpression | string,\n roots: readonly string[],\n): ContextRootKeyAccessAnalysis {\n const source = typeof expression === 'string' ? expression : expression.source;\n const references: ContextRootKeyAccessReference[] = [];\n const violations: ContextKeyAccessViolation[] = [];\n const selectedRoots = new Set(roots);\n\n collectContextAccesses(parseCel(source).ast, source, new Set(), {\n shouldRecord: (chain) => selectedRoots.has(chain.root),\n record: (chain, expressionSource) =>\n recordContextRootKeyAccess(chain, expressionSource, references, violations),\n });\n\n return {references, violations};\n}\n\nfunction collectContextAccesses(\n node: ASTNode,\n source: string,\n scopedIdentifiers: ReadonlySet<string>,\n visitor: ContextAccessVisitor,\n): void {\n if (binaryOperators.has(node.op as BinaryOperator) || node.op === '||' || node.op === '&&') {\n collectBinaryContextAccesses(\n node.args as [ASTNode, ASTNode],\n source,\n scopedIdentifiers,\n visitor,\n );\n return;\n }\n\n const chain = accessChain(node, scopedIdentifiers);\n if (chain && visitor.shouldRecord(chain)) {\n visitor.record(chain, source);\n return;\n }\n\n switch (node.op) {\n case 'id':\n case 'value':\n return;\n case '.':\n case '.?':\n collectContextAccesses(node.args[0], source, scopedIdentifiers, visitor);\n return;\n case '[]':\n case '[?]':\n collectBinaryContextAccesses(node.args, source, scopedIdentifiers, visitor);\n return;\n case 'call':\n for (const argument of node.args[1]) {\n collectContextAccesses(argument, source, scopedIdentifiers, visitor);\n }\n return;\n case 'rcall': {\n const [method, receiver, args] = node.args as [string, ASTNode, ASTNode[]];\n collectContextAccesses(receiver, source, scopedIdentifiers, visitor);\n const binding = bindComprehensionAlias(method, args, scopedIdentifiers);\n for (const argument of args.slice(binding.skipArgs)) {\n collectContextAccesses(argument, source, binding.scopedIdentifiers, visitor);\n }\n return;\n }\n case 'list':\n for (const element of node.args) {\n collectContextAccesses(element, source, scopedIdentifiers, visitor);\n }\n return;\n case 'map':\n for (const [key, value] of node.args) {\n if (key.op !== 'id') {\n collectContextAccesses(key, source, scopedIdentifiers, visitor);\n }\n collectContextAccesses(value, source, scopedIdentifiers, visitor);\n }\n return;\n case '?:':\n collectContextAccesses(node.args[0], source, scopedIdentifiers, visitor);\n collectContextAccesses(node.args[1], source, scopedIdentifiers, visitor);\n collectContextAccesses(node.args[2], source, scopedIdentifiers, visitor);\n return;\n case '!_':\n case '-_':\n collectContextAccesses(node.args, source, scopedIdentifiers, visitor);\n return;\n }\n\n throw new Error(`Unsupported CEL AST operator: ${(node as {op: string}).op}`);\n}\n\nfunction collectBinaryContextAccesses(\n [left, right]: [ASTNode, ASTNode],\n source: string,\n scopedIdentifiers: ReadonlySet<string>,\n visitor: ContextAccessVisitor,\n): void {\n collectContextAccesses(left, source, scopedIdentifiers, visitor);\n collectContextAccesses(right, source, scopedIdentifiers, visitor);\n}\n\nfunction recordLiteralKeyRootAccess(\n chain: AccessChain,\n source: string,\n references: ContextKeyAccessReference[],\n violations: ContextKeyAccessViolation[],\n): void {\n if (chain.computed) {\n violations.push({root: chain.root, source});\n return;\n }\n\n if (chain.root === 'vars' && chain.segments.length === 1) {\n const key = chain.segments[0];\n if (key === undefined) throw new Error('Expected vars key segment');\n references.push({root: chain.root, key});\n return;\n }\n\n if (chain.root === 'secrets' && chain.segments.length === 1) {\n const key = chain.segments[0];\n if (key === undefined) throw new Error('Expected secret key segment');\n references.push({root: chain.root, key});\n return;\n }\n\n if (chain.root === 'secrets' && chain.segments.length === 2) {\n const store = chain.segments[0];\n const key = chain.segments[1];\n if (store === undefined || key === undefined) {\n throw new Error('Expected secret store and key segments');\n }\n references.push({root: chain.root, store, key});\n return;\n }\n\n violations.push({root: chain.root, source});\n}\n\nfunction recordContextRootKeyAccess(\n chain: AccessChain,\n source: string,\n references: ContextRootKeyAccessReference[],\n violations: ContextKeyAccessViolation[],\n): void {\n const [key] = chain.segments;\n if (chain.computed || key === undefined) {\n violations.push({root: chain.root, source});\n return;\n }\n\n references.push({root: chain.root, key});\n}\n\nfunction accessChain(\n node: ASTNode,\n scopedIdentifiers: ReadonlySet<string>,\n): AccessChain | undefined {\n switch (node.op) {\n case 'id':\n return scopedIdentifiers.has(node.args)\n ? undefined\n : {root: node.args, segments: [], computed: false};\n case '.': {\n const target = accessChain(node.args[0], scopedIdentifiers);\n if (target === undefined) return undefined;\n return {...target, segments: [...target.segments, node.args[1]]};\n }\n case '.?': {\n const target = accessChain(node.args[0], scopedIdentifiers);\n if (target === undefined) return undefined;\n return {...target, segments: [...target.segments, node.args[1]], computed: true};\n }\n case '[]':\n case '[?]': {\n const target = accessChain(node.args[0], scopedIdentifiers);\n if (target === undefined) return undefined;\n const literalSegment = literalStringValue(node.args[1]);\n return {\n ...target,\n segments:\n literalSegment === undefined ? target.segments : [...target.segments, literalSegment],\n computed: true,\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction literalStringValue(node: ASTNode): string | undefined {\n return node.op === 'value' && typeof node.args === 'string' ? node.args : undefined;\n}\n\nfunction bindComprehensionAlias(\n method: string,\n args: readonly ASTNode[],\n scopedIdentifiers: ReadonlySet<string>,\n): {readonly scopedIdentifiers: ReadonlySet<string>; readonly skipArgs: number} {\n if (!comprehensionMethods.has(method)) return {scopedIdentifiers, skipArgs: 0};\n\n const [alias] = args;\n if (alias?.op !== 'id') return {scopedIdentifiers, skipArgs: 0};\n\n return {\n scopedIdentifiers: new Set([...scopedIdentifiers, alias.args]),\n skipArgs: 1,\n };\n}\n"],"names":["parse","parseCel","workflowContextRootRequiresLiteralKey","binaryOperators","Set","comprehensionMethods","analyzeContextKeyAccess","expression","source","references","violations","collectContextAccesses","ast","shouldRecord","chain","root","record","expressionSource","recordLiteralKeyRootAccess","analyzeContextRootKeyAccess","roots","selectedRoots","has","recordContextRootKeyAccess","node","scopedIdentifiers","visitor","op","collectBinaryContextAccesses","args","accessChain","argument","method","receiver","binding","bindComprehensionAlias","slice","skipArgs","element","key","value","Error","left","right","computed","push","segments","length","undefined","store","target","literalSegment","literalStringValue","alias"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type FailClosedPredicateOutcome, type WorkflowExpressionEvaluationContext } from '../evaluator/evaluate-workflow-expression.js';
2
+ import type { WorkflowExpression } from '../expression/workflow-expression.js';
3
+ import type { AvailabilitySite, WorkflowPredicateField } from '../workflow-context/workflow-context.js';
4
+ import { type RoutedExpression } from './route-expression.js';
5
+ export interface PlannedPredicateEvaluationResult extends FailClosedPredicateOutcome {
6
+ readonly route: RoutedExpression;
7
+ }
8
+ export declare function evaluatePlannedPredicateAtSite(params: {
9
+ readonly expression: WorkflowExpression;
10
+ readonly field: WorkflowPredicateField;
11
+ readonly site: AvailabilitySite;
12
+ readonly context: WorkflowExpressionEvaluationContext;
13
+ }): PlannedPredicateEvaluationResult;
14
+ //# sourceMappingURL=evaluate-planned-predicate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate-planned-predicate.d.ts","sourceRoot":"","sources":["../../src/plan/evaluate-planned-predicate.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,mCAAmC,EACzC,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EACV,gBAAgB,EAEhB,sBAAsB,EACvB,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EAAC,KAAK,gBAAgB,EAAkB,MAAM,uBAAuB,CAAC;AAE7E,MAAM,WAAW,gCAAiC,SAAQ,0BAA0B;IAClF,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;CAClC;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,mCAAmC,CAAC;CACvD,GAAG,gCAAgC,CAOnC"}
@@ -0,0 +1,31 @@
1
+ import { evaluateWorkflowPredicateFailClosed } from '../evaluator/evaluate-workflow-expression.js';
2
+ import { getWorkflowPredicateFieldMinimumFillTarget } from '../workflow-context/workflow-context.js';
3
+ import { shouldFillAtSite } from './fill.js';
4
+ import { routeExpression } from './route-expression.js';
5
+ export function evaluatePlannedPredicateAtSite(params) {
6
+ const route = routePredicateExpression(params.expression, params.field);
7
+ if (!shouldFillAtSite(route.fillTarget, params.site)) {
8
+ return {
9
+ value: false,
10
+ evaluationFailed: true,
11
+ route
12
+ };
13
+ }
14
+ return {
15
+ ...evaluateWorkflowPredicateFailClosed(params.expression, params.context),
16
+ route
17
+ };
18
+ }
19
+ function routePredicateExpression(expression, field) {
20
+ const route = routeExpression(expression);
21
+ return {
22
+ ...route,
23
+ fillTarget: laterFillTarget(route.fillTarget, getWorkflowPredicateFieldMinimumFillTarget(field))
24
+ };
25
+ }
26
+ function laterFillTarget(left, right) {
27
+ if (left === 'runner-fill') return left;
28
+ return shouldFillAtSite(right, left) ? left : right;
29
+ }
30
+
31
+ //# sourceMappingURL=evaluate-planned-predicate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plan/evaluate-planned-predicate.ts"],"sourcesContent":["import {\n evaluateWorkflowPredicateFailClosed,\n type FailClosedPredicateOutcome,\n type WorkflowExpressionEvaluationContext,\n} from '../evaluator/evaluate-workflow-expression.js';\nimport type {WorkflowExpression} from '../expression/workflow-expression.js';\nimport type {\n AvailabilitySite,\n FillTarget,\n WorkflowPredicateField,\n} from '../workflow-context/workflow-context.js';\nimport {getWorkflowPredicateFieldMinimumFillTarget} from '../workflow-context/workflow-context.js';\nimport {shouldFillAtSite} from './fill.js';\nimport {type RoutedExpression, routeExpression} from './route-expression.js';\n\nexport interface PlannedPredicateEvaluationResult extends FailClosedPredicateOutcome {\n readonly route: RoutedExpression;\n}\n\nexport function evaluatePlannedPredicateAtSite(params: {\n readonly expression: WorkflowExpression;\n readonly field: WorkflowPredicateField;\n readonly site: AvailabilitySite;\n readonly context: WorkflowExpressionEvaluationContext;\n}): PlannedPredicateEvaluationResult {\n const route = routePredicateExpression(params.expression, params.field);\n if (!shouldFillAtSite(route.fillTarget, params.site)) {\n return {value: false, evaluationFailed: true, route};\n }\n\n return {...evaluateWorkflowPredicateFailClosed(params.expression, params.context), route};\n}\n\nfunction routePredicateExpression(\n expression: WorkflowExpression,\n field: WorkflowPredicateField,\n): RoutedExpression {\n const route = routeExpression(expression);\n return {\n ...route,\n fillTarget: laterFillTarget(\n route.fillTarget,\n getWorkflowPredicateFieldMinimumFillTarget(field),\n ),\n };\n}\n\nfunction laterFillTarget(left: FillTarget, right: AvailabilitySite): FillTarget {\n if (left === 'runner-fill') return left;\n return shouldFillAtSite(right, left) ? left : right;\n}\n"],"names":["evaluateWorkflowPredicateFailClosed","getWorkflowPredicateFieldMinimumFillTarget","shouldFillAtSite","routeExpression","evaluatePlannedPredicateAtSite","params","route","routePredicateExpression","expression","field","fillTarget","site","value","evaluationFailed","context","laterFillTarget","left","right"],"mappings":"AAAA,SACEA,mCAAmC,QAG9B,+CAA+C;AAOtD,SAAQC,0CAA0C,QAAO,0CAA0C;AACnG,SAAQC,gBAAgB,QAAO,YAAY;AAC3C,SAA+BC,eAAe,QAAO,wBAAwB;AAM7E,OAAO,SAASC,+BAA+BC,MAK9C;IACC,MAAMC,QAAQC,yBAAyBF,OAAOG,UAAU,EAAEH,OAAOI,KAAK;IACtE,IAAI,CAACP,iBAAiBI,MAAMI,UAAU,EAAEL,OAAOM,IAAI,GAAG;QACpD,OAAO;YAACC,OAAO;YAAOC,kBAAkB;YAAMP;QAAK;IACrD;IAEA,OAAO;QAAC,GAAGN,oCAAoCK,OAAOG,UAAU,EAAEH,OAAOS,OAAO,CAAC;QAAER;IAAK;AAC1F;AAEA,SAASC,yBACPC,UAA8B,EAC9BC,KAA6B;IAE7B,MAAMH,QAAQH,gBAAgBK;IAC9B,OAAO;QACL,GAAGF,KAAK;QACRI,YAAYK,gBACVT,MAAMI,UAAU,EAChBT,2CAA2CQ;IAE/C;AACF;AAEA,SAASM,gBAAgBC,IAAgB,EAAEC,KAAuB;IAChE,IAAID,SAAS,eAAe,OAAOA;IACnC,OAAOd,iBAAiBe,OAAOD,QAAQA,OAAOC;AAChD"}
@@ -0,0 +1,44 @@
1
+ import type { AvailabilitySite, FillTarget } from '../workflow-context/workflow-context.js';
2
+ import type { RoutedExpression } from './route-expression.js';
3
+ export declare const EVALUATION_TRACE_VALUE_CAP_BYTES = 1024;
4
+ export declare const EVALUATION_TRACE_MAX_ENTRIES = 256;
5
+ export interface EvaluationTraceEntry {
6
+ readonly expression: string;
7
+ readonly roots: readonly string[];
8
+ readonly fillTarget: FillTarget;
9
+ readonly evaluatedAt: AvailabilitySite;
10
+ readonly value?: string;
11
+ readonly truncated?: boolean;
12
+ readonly exprTruncated?: boolean;
13
+ readonly reference?: boolean;
14
+ readonly degraded?: boolean;
15
+ }
16
+ export interface EvaluationTraceLimitEntry {
17
+ readonly truncated: true;
18
+ readonly dropped: number;
19
+ }
20
+ export type EvaluationTraceRowEntry = EvaluationTraceEntry | EvaluationTraceLimitEntry;
21
+ export interface EvaluationTraceEntryInput {
22
+ readonly expression: string;
23
+ readonly roots: readonly string[];
24
+ readonly fillTarget: FillTarget;
25
+ readonly evaluatedAt: AvailabilitySite;
26
+ readonly value?: string;
27
+ readonly reference?: boolean;
28
+ readonly degraded?: boolean;
29
+ }
30
+ export interface PredicateTraceEntryInput {
31
+ readonly expression: string;
32
+ readonly route: RoutedExpression;
33
+ readonly site: AvailabilitySite;
34
+ readonly value: boolean;
35
+ readonly degraded?: boolean;
36
+ }
37
+ export declare function capTraceValue(value: string): {
38
+ value: string;
39
+ truncated: boolean;
40
+ };
41
+ export declare function evaluationTraceEntry(input: EvaluationTraceEntryInput): EvaluationTraceEntry;
42
+ export declare function predicateTraceEntry(input: PredicateTraceEntryInput): EvaluationTraceEntry;
43
+ export declare function capTraceEntries<Entry extends EvaluationTraceRowEntry>(entries: readonly Entry[]): readonly (Exclude<Entry, EvaluationTraceLimitEntry> | EvaluationTraceLimitEntry)[];
44
+ //# sourceMappingURL=evaluation-trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation-trace.d.ts","sourceRoot":"","sources":["../../src/plan/evaluation-trace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,yCAAyC,CAAC;AAC1F,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAE5D,eAAO,MAAM,gCAAgC,OAAO,CAAC;AACrD,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAKhD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,uBAAuB,GAAG,oBAAoB,GAAG,yBAAyB,CAAC;AAEvF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAC,CAkBhF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,oBAAoB,CAgB3F;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,oBAAoB,CASzF;AAED,wBAAgB,eAAe,CAAC,KAAK,SAAS,uBAAuB,EACnE,OAAO,EAAE,SAAS,KAAK,EAAE,GACxB,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,yBAAyB,CAAC,GAAG,yBAAyB,CAAC,EAAE,CAsBpF"}
@@ -0,0 +1,95 @@
1
+ export const EVALUATION_TRACE_VALUE_CAP_BYTES = 1024;
2
+ export const EVALUATION_TRACE_MAX_ENTRIES = 256;
3
+ const TRACE_TRUNCATION_MARKER = '...[truncated]';
4
+ const textEncoder = new TextEncoder();
5
+ export function capTraceValue(value) {
6
+ if (textEncoder.encode(value).byteLength <= EVALUATION_TRACE_VALUE_CAP_BYTES) {
7
+ return {
8
+ value,
9
+ truncated: false
10
+ };
11
+ }
12
+ const budget = EVALUATION_TRACE_VALUE_CAP_BYTES - textEncoder.encode(TRACE_TRUNCATION_MARKER).byteLength;
13
+ let used = 0;
14
+ let capped = '';
15
+ for (const char of value){
16
+ const charBytes = textEncoder.encode(char).byteLength;
17
+ if (used + charBytes > budget) break;
18
+ capped += char;
19
+ used += charBytes;
20
+ }
21
+ return {
22
+ value: capped + TRACE_TRUNCATION_MARKER,
23
+ truncated: true
24
+ };
25
+ }
26
+ export function evaluationTraceEntry(input) {
27
+ const expression = capTraceValue(input.expression);
28
+ const value = input.value === undefined || input.reference === true ? undefined : capTraceValue(input.value);
29
+ return {
30
+ expression: expression.value,
31
+ roots: input.roots,
32
+ fillTarget: input.fillTarget,
33
+ evaluatedAt: input.evaluatedAt,
34
+ ...value === undefined ? {} : {
35
+ value: value.value
36
+ },
37
+ ...value?.truncated === true ? {
38
+ truncated: true
39
+ } : {},
40
+ ...expression.truncated ? {
41
+ exprTruncated: true
42
+ } : {},
43
+ ...input.reference === true ? {
44
+ reference: true
45
+ } : {},
46
+ ...input.degraded === true ? {
47
+ degraded: true
48
+ } : {}
49
+ };
50
+ }
51
+ export function predicateTraceEntry(input) {
52
+ return evaluationTraceEntry({
53
+ expression: input.expression,
54
+ roots: input.route.roots,
55
+ fillTarget: input.route.fillTarget,
56
+ evaluatedAt: input.site,
57
+ value: String(input.value),
58
+ ...input.degraded === true ? {
59
+ degraded: true
60
+ } : {}
61
+ });
62
+ }
63
+ export function capTraceEntries(entries) {
64
+ const traceEntries = [];
65
+ let dropped = 0;
66
+ for (const entry of entries){
67
+ if (isEvaluationTraceLimitEntry(entry)) {
68
+ dropped += entry.dropped;
69
+ continue;
70
+ }
71
+ traceEntries.push(entry);
72
+ }
73
+ const keepCount = EVALUATION_TRACE_MAX_ENTRIES - 1;
74
+ if (traceEntries.length + (dropped > 0 ? 1 : 0) <= EVALUATION_TRACE_MAX_ENTRIES) {
75
+ return dropped === 0 ? traceEntries : [
76
+ ...traceEntries,
77
+ {
78
+ truncated: true,
79
+ dropped
80
+ }
81
+ ];
82
+ }
83
+ return [
84
+ ...traceEntries.slice(0, keepCount),
85
+ {
86
+ truncated: true,
87
+ dropped: dropped + traceEntries.length - keepCount
88
+ }
89
+ ];
90
+ }
91
+ function isEvaluationTraceLimitEntry(entry) {
92
+ return 'dropped' in entry;
93
+ }
94
+
95
+ //# sourceMappingURL=evaluation-trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plan/evaluation-trace.ts"],"sourcesContent":["import type {AvailabilitySite, FillTarget} from '../workflow-context/workflow-context.js';\nimport type {RoutedExpression} from './route-expression.js';\n\nexport const EVALUATION_TRACE_VALUE_CAP_BYTES = 1024;\nexport const EVALUATION_TRACE_MAX_ENTRIES = 256;\n\nconst TRACE_TRUNCATION_MARKER = '...[truncated]';\nconst textEncoder = new TextEncoder();\n\nexport interface EvaluationTraceEntry {\n readonly expression: string;\n readonly roots: readonly string[];\n readonly fillTarget: FillTarget;\n readonly evaluatedAt: AvailabilitySite;\n readonly value?: string;\n readonly truncated?: boolean;\n readonly exprTruncated?: boolean;\n readonly reference?: boolean;\n readonly degraded?: boolean;\n}\n\nexport interface EvaluationTraceLimitEntry {\n readonly truncated: true;\n readonly dropped: number;\n}\n\nexport type EvaluationTraceRowEntry = EvaluationTraceEntry | EvaluationTraceLimitEntry;\n\nexport interface EvaluationTraceEntryInput {\n readonly expression: string;\n readonly roots: readonly string[];\n readonly fillTarget: FillTarget;\n readonly evaluatedAt: AvailabilitySite;\n readonly value?: string;\n readonly reference?: boolean;\n readonly degraded?: boolean;\n}\n\nexport interface PredicateTraceEntryInput {\n readonly expression: string;\n readonly route: RoutedExpression;\n readonly site: AvailabilitySite;\n readonly value: boolean;\n readonly degraded?: boolean;\n}\n\nexport function capTraceValue(value: string): {value: string; truncated: boolean} {\n if (textEncoder.encode(value).byteLength <= EVALUATION_TRACE_VALUE_CAP_BYTES) {\n return {value, truncated: false};\n }\n\n const budget =\n EVALUATION_TRACE_VALUE_CAP_BYTES - textEncoder.encode(TRACE_TRUNCATION_MARKER).byteLength;\n let used = 0;\n let capped = '';\n\n for (const char of value) {\n const charBytes = textEncoder.encode(char).byteLength;\n if (used + charBytes > budget) break;\n capped += char;\n used += charBytes;\n }\n\n return {value: capped + TRACE_TRUNCATION_MARKER, truncated: true};\n}\n\nexport function evaluationTraceEntry(input: EvaluationTraceEntryInput): EvaluationTraceEntry {\n const expression = capTraceValue(input.expression);\n const value =\n input.value === undefined || input.reference === true ? undefined : capTraceValue(input.value);\n\n return {\n expression: expression.value,\n roots: input.roots,\n fillTarget: input.fillTarget,\n evaluatedAt: input.evaluatedAt,\n ...(value === undefined ? {} : {value: value.value}),\n ...(value?.truncated === true ? {truncated: true} : {}),\n ...(expression.truncated ? {exprTruncated: true} : {}),\n ...(input.reference === true ? {reference: true} : {}),\n ...(input.degraded === true ? {degraded: true} : {}),\n };\n}\n\nexport function predicateTraceEntry(input: PredicateTraceEntryInput): EvaluationTraceEntry {\n return evaluationTraceEntry({\n expression: input.expression,\n roots: input.route.roots,\n fillTarget: input.route.fillTarget,\n evaluatedAt: input.site,\n value: String(input.value),\n ...(input.degraded === true ? {degraded: true} : {}),\n });\n}\n\nexport function capTraceEntries<Entry extends EvaluationTraceRowEntry>(\n entries: readonly Entry[],\n): readonly (Exclude<Entry, EvaluationTraceLimitEntry> | EvaluationTraceLimitEntry)[] {\n const traceEntries: Exclude<Entry, EvaluationTraceLimitEntry>[] = [];\n let dropped = 0;\n\n for (const entry of entries) {\n if (isEvaluationTraceLimitEntry(entry)) {\n dropped += entry.dropped;\n continue;\n }\n\n traceEntries.push(entry as Exclude<Entry, EvaluationTraceLimitEntry>);\n }\n\n const keepCount = EVALUATION_TRACE_MAX_ENTRIES - 1;\n if (traceEntries.length + (dropped > 0 ? 1 : 0) <= EVALUATION_TRACE_MAX_ENTRIES) {\n return dropped === 0 ? traceEntries : [...traceEntries, {truncated: true, dropped}];\n }\n\n return [\n ...traceEntries.slice(0, keepCount),\n {truncated: true, dropped: dropped + traceEntries.length - keepCount},\n ];\n}\n\nfunction isEvaluationTraceLimitEntry(\n entry: EvaluationTraceRowEntry,\n): entry is EvaluationTraceLimitEntry {\n return 'dropped' in entry;\n}\n"],"names":["EVALUATION_TRACE_VALUE_CAP_BYTES","EVALUATION_TRACE_MAX_ENTRIES","TRACE_TRUNCATION_MARKER","textEncoder","TextEncoder","capTraceValue","value","encode","byteLength","truncated","budget","used","capped","char","charBytes","evaluationTraceEntry","input","expression","undefined","reference","roots","fillTarget","evaluatedAt","exprTruncated","degraded","predicateTraceEntry","route","site","String","capTraceEntries","entries","traceEntries","dropped","entry","isEvaluationTraceLimitEntry","push","keepCount","length","slice"],"mappings":"AAGA,OAAO,MAAMA,mCAAmC,KAAK;AACrD,OAAO,MAAMC,+BAA+B,IAAI;AAEhD,MAAMC,0BAA0B;AAChC,MAAMC,cAAc,IAAIC;AAuCxB,OAAO,SAASC,cAAcC,KAAa;IACzC,IAAIH,YAAYI,MAAM,CAACD,OAAOE,UAAU,IAAIR,kCAAkC;QAC5E,OAAO;YAACM;YAAOG,WAAW;QAAK;IACjC;IAEA,MAAMC,SACJV,mCAAmCG,YAAYI,MAAM,CAACL,yBAAyBM,UAAU;IAC3F,IAAIG,OAAO;IACX,IAAIC,SAAS;IAEb,KAAK,MAAMC,QAAQP,MAAO;QACxB,MAAMQ,YAAYX,YAAYI,MAAM,CAACM,MAAML,UAAU;QACrD,IAAIG,OAAOG,YAAYJ,QAAQ;QAC/BE,UAAUC;QACVF,QAAQG;IACV;IAEA,OAAO;QAACR,OAAOM,SAASV;QAAyBO,WAAW;IAAI;AAClE;AAEA,OAAO,SAASM,qBAAqBC,KAAgC;IACnE,MAAMC,aAAaZ,cAAcW,MAAMC,UAAU;IACjD,MAAMX,QACJU,MAAMV,KAAK,KAAKY,aAAaF,MAAMG,SAAS,KAAK,OAAOD,YAAYb,cAAcW,MAAMV,KAAK;IAE/F,OAAO;QACLW,YAAYA,WAAWX,KAAK;QAC5Bc,OAAOJ,MAAMI,KAAK;QAClBC,YAAYL,MAAMK,UAAU;QAC5BC,aAAaN,MAAMM,WAAW;QAC9B,GAAIhB,UAAUY,YAAY,CAAC,IAAI;YAACZ,OAAOA,MAAMA,KAAK;QAAA,CAAC;QACnD,GAAIA,OAAOG,cAAc,OAAO;YAACA,WAAW;QAAI,IAAI,CAAC,CAAC;QACtD,GAAIQ,WAAWR,SAAS,GAAG;YAACc,eAAe;QAAI,IAAI,CAAC,CAAC;QACrD,GAAIP,MAAMG,SAAS,KAAK,OAAO;YAACA,WAAW;QAAI,IAAI,CAAC,CAAC;QACrD,GAAIH,MAAMQ,QAAQ,KAAK,OAAO;YAACA,UAAU;QAAI,IAAI,CAAC,CAAC;IACrD;AACF;AAEA,OAAO,SAASC,oBAAoBT,KAA+B;IACjE,OAAOD,qBAAqB;QAC1BE,YAAYD,MAAMC,UAAU;QAC5BG,OAAOJ,MAAMU,KAAK,CAACN,KAAK;QACxBC,YAAYL,MAAMU,KAAK,CAACL,UAAU;QAClCC,aAAaN,MAAMW,IAAI;QACvBrB,OAAOsB,OAAOZ,MAAMV,KAAK;QACzB,GAAIU,MAAMQ,QAAQ,KAAK,OAAO;YAACA,UAAU;QAAI,IAAI,CAAC,CAAC;IACrD;AACF;AAEA,OAAO,SAASK,gBACdC,OAAyB;IAEzB,MAAMC,eAA4D,EAAE;IACpE,IAAIC,UAAU;IAEd,KAAK,MAAMC,SAASH,QAAS;QAC3B,IAAII,4BAA4BD,QAAQ;YACtCD,WAAWC,MAAMD,OAAO;YACxB;QACF;QAEAD,aAAaI,IAAI,CAACF;IACpB;IAEA,MAAMG,YAAYnC,+BAA+B;IACjD,IAAI8B,aAAaM,MAAM,GAAIL,CAAAA,UAAU,IAAI,IAAI,CAAA,KAAM/B,8BAA8B;QAC/E,OAAO+B,YAAY,IAAID,eAAe;eAAIA;YAAc;gBAACtB,WAAW;gBAAMuB;YAAO;SAAE;IACrF;IAEA,OAAO;WACFD,aAAaO,KAAK,CAAC,GAAGF;QACzB;YAAC3B,WAAW;YAAMuB,SAASA,UAAUD,aAAaM,MAAM,GAAGD;QAAS;KACrE;AACH;AAEA,SAASF,4BACPD,KAA8B;IAE9B,OAAO,aAAaA;AACtB"}
@@ -0,0 +1,2 @@
1
+ export declare function extractExactContextRoots(source: string): string[];
2
+ //# sourceMappingURL=extract-exact-context-roots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-exact-context-roots.d.ts","sourceRoot":"","sources":["../../src/plan/extract-exact-context-roots.ts"],"names":[],"mappings":"AAmBA,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAIjE"}
@@ -0,0 +1,114 @@
1
+ import { parse as parseCel } from '@marcbachmann/cel-js';
2
+ const binaryOperators = new Set([
3
+ '!=',
4
+ '==',
5
+ 'in',
6
+ '+',
7
+ '-',
8
+ '*',
9
+ '/',
10
+ '%',
11
+ '<',
12
+ '<=',
13
+ '>',
14
+ '>='
15
+ ]);
16
+ const comprehensionMethods = new Set([
17
+ 'all',
18
+ 'exists',
19
+ 'exists_one',
20
+ 'filter',
21
+ 'map'
22
+ ]);
23
+ export function extractExactContextRoots(source) {
24
+ const roots = new Set();
25
+ collectExactContextRoots(parseCel(source).ast, roots, new Set());
26
+ return [
27
+ ...roots
28
+ ].sort();
29
+ }
30
+ function collectExactContextRoots(node, roots, scopedIdentifiers) {
31
+ if (binaryOperators.has(node.op) || node.op === '||' || node.op === '&&') {
32
+ collectBinaryExactContextRoots(node.args, roots, scopedIdentifiers);
33
+ return;
34
+ }
35
+ switch(node.op){
36
+ case 'id':
37
+ if (!scopedIdentifiers.has(node.args)) roots.add(node.args);
38
+ return;
39
+ case 'value':
40
+ return;
41
+ case '.':
42
+ case '.?':
43
+ collectExactContextRoots(node.args[0], roots, scopedIdentifiers);
44
+ return;
45
+ case '[]':
46
+ case '[?]':
47
+ collectBinaryExactContextRoots(node.args, roots, scopedIdentifiers);
48
+ return;
49
+ case 'call':
50
+ for (const argument of node.args[1]){
51
+ collectExactContextRoots(argument, roots, scopedIdentifiers);
52
+ }
53
+ return;
54
+ case 'rcall':
55
+ {
56
+ const [method, receiver, args] = node.args;
57
+ collectExactContextRoots(receiver, roots, scopedIdentifiers);
58
+ const binding = bindComprehensionAlias(method, args, scopedIdentifiers);
59
+ for (const argument of args.slice(binding.skipArgs)){
60
+ collectExactContextRoots(argument, roots, binding.scopedIdentifiers);
61
+ }
62
+ return;
63
+ }
64
+ case 'list':
65
+ for (const element of node.args){
66
+ collectExactContextRoots(element, roots, scopedIdentifiers);
67
+ }
68
+ return;
69
+ case 'map':
70
+ for (const [key, value] of node.args){
71
+ collectMapKeyExactContextRoots(key, roots, scopedIdentifiers);
72
+ collectExactContextRoots(value, roots, scopedIdentifiers);
73
+ }
74
+ return;
75
+ case '?:':
76
+ collectExactContextRoots(node.args[0], roots, scopedIdentifiers);
77
+ collectExactContextRoots(node.args[1], roots, scopedIdentifiers);
78
+ collectExactContextRoots(node.args[2], roots, scopedIdentifiers);
79
+ return;
80
+ case '!_':
81
+ case '-_':
82
+ collectExactContextRoots(node.args, roots, scopedIdentifiers);
83
+ return;
84
+ }
85
+ throw new Error(`Unsupported CEL AST operator: ${node.op}`);
86
+ }
87
+ function collectBinaryExactContextRoots([left, right], roots, scopedIdentifiers) {
88
+ collectExactContextRoots(left, roots, scopedIdentifiers);
89
+ collectExactContextRoots(right, roots, scopedIdentifiers);
90
+ }
91
+ function collectMapKeyExactContextRoots(key, roots, scopedIdentifiers) {
92
+ if (key.op === 'id') return;
93
+ collectExactContextRoots(key, roots, scopedIdentifiers);
94
+ }
95
+ function bindComprehensionAlias(method, args, scopedIdentifiers) {
96
+ if (!comprehensionMethods.has(method)) return {
97
+ scopedIdentifiers,
98
+ skipArgs: 0
99
+ };
100
+ const [alias] = args;
101
+ if (alias?.op !== 'id') return {
102
+ scopedIdentifiers,
103
+ skipArgs: 0
104
+ };
105
+ return {
106
+ scopedIdentifiers: new Set([
107
+ ...scopedIdentifiers,
108
+ alias.args
109
+ ]),
110
+ skipArgs: 1
111
+ };
112
+ }
113
+
114
+ //# sourceMappingURL=extract-exact-context-roots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plan/extract-exact-context-roots.ts"],"sourcesContent":["import {type ASTNode, type BinaryOperator, parse as parseCel} from '@marcbachmann/cel-js';\n\nconst binaryOperators = new Set<BinaryOperator>([\n '!=',\n '==',\n 'in',\n '+',\n '-',\n '*',\n '/',\n '%',\n '<',\n '<=',\n '>',\n '>=',\n]);\n\nconst comprehensionMethods = new Set(['all', 'exists', 'exists_one', 'filter', 'map']);\n\nexport function extractExactContextRoots(source: string): string[] {\n const roots = new Set<string>();\n collectExactContextRoots(parseCel(source).ast, roots, new Set());\n return [...roots].sort();\n}\n\nfunction collectExactContextRoots(\n node: ASTNode,\n roots: Set<string>,\n scopedIdentifiers: ReadonlySet<string>,\n): void {\n if (binaryOperators.has(node.op as BinaryOperator) || node.op === '||' || node.op === '&&') {\n collectBinaryExactContextRoots(node.args as [ASTNode, ASTNode], roots, scopedIdentifiers);\n return;\n }\n\n switch (node.op) {\n case 'id':\n if (!scopedIdentifiers.has(node.args)) roots.add(node.args);\n return;\n case 'value':\n return;\n case '.':\n case '.?':\n collectExactContextRoots(node.args[0], roots, scopedIdentifiers);\n return;\n case '[]':\n case '[?]':\n collectBinaryExactContextRoots(node.args, roots, scopedIdentifiers);\n return;\n case 'call':\n for (const argument of node.args[1]) {\n collectExactContextRoots(argument, roots, scopedIdentifiers);\n }\n return;\n case 'rcall': {\n const [method, receiver, args] = node.args as [string, ASTNode, ASTNode[]];\n collectExactContextRoots(receiver, roots, scopedIdentifiers);\n const binding = bindComprehensionAlias(method, args, scopedIdentifiers);\n for (const argument of args.slice(binding.skipArgs)) {\n collectExactContextRoots(argument, roots, binding.scopedIdentifiers);\n }\n return;\n }\n case 'list':\n for (const element of node.args) {\n collectExactContextRoots(element, roots, scopedIdentifiers);\n }\n return;\n case 'map':\n for (const [key, value] of node.args) {\n collectMapKeyExactContextRoots(key, roots, scopedIdentifiers);\n collectExactContextRoots(value, roots, scopedIdentifiers);\n }\n return;\n case '?:':\n collectExactContextRoots(node.args[0], roots, scopedIdentifiers);\n collectExactContextRoots(node.args[1], roots, scopedIdentifiers);\n collectExactContextRoots(node.args[2], roots, scopedIdentifiers);\n return;\n case '!_':\n case '-_':\n collectExactContextRoots(node.args, roots, scopedIdentifiers);\n return;\n }\n\n throw new Error(`Unsupported CEL AST operator: ${(node as {op: string}).op}`);\n}\n\nfunction collectBinaryExactContextRoots(\n [left, right]: [ASTNode, ASTNode],\n roots: Set<string>,\n scopedIdentifiers: ReadonlySet<string>,\n): void {\n collectExactContextRoots(left, roots, scopedIdentifiers);\n collectExactContextRoots(right, roots, scopedIdentifiers);\n}\n\nfunction collectMapKeyExactContextRoots(\n key: ASTNode,\n roots: Set<string>,\n scopedIdentifiers: ReadonlySet<string>,\n): void {\n if (key.op === 'id') return;\n collectExactContextRoots(key, roots, scopedIdentifiers);\n}\n\nfunction bindComprehensionAlias(\n method: string,\n args: readonly ASTNode[],\n scopedIdentifiers: ReadonlySet<string>,\n): {readonly scopedIdentifiers: ReadonlySet<string>; readonly skipArgs: number} {\n if (!comprehensionMethods.has(method)) return {scopedIdentifiers, skipArgs: 0};\n\n const [alias] = args;\n if (alias?.op !== 'id') return {scopedIdentifiers, skipArgs: 0};\n\n return {\n scopedIdentifiers: new Set([...scopedIdentifiers, alias.args]),\n skipArgs: 1,\n };\n}\n"],"names":["parse","parseCel","binaryOperators","Set","comprehensionMethods","extractExactContextRoots","source","roots","collectExactContextRoots","ast","sort","node","scopedIdentifiers","has","op","collectBinaryExactContextRoots","args","add","argument","method","receiver","binding","bindComprehensionAlias","slice","skipArgs","element","key","value","collectMapKeyExactContextRoots","Error","left","right","alias"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type AvailabilitySite } from '../workflow-context/workflow-context.js';
2
+ export declare function shouldFillAtSite(fillTarget: string, site: AvailabilitySite): boolean;
3
+ //# sourceMappingURL=fill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill.d.ts","sourceRoot":"","sources":["../../src/plan/fill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,gBAAgB,EAAoB,MAAM,yCAAyC,CAAC;AAEjG,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAKpF"}