@adcp/sdk 14.0.0-beta.12 → 14.0.0-beta.13

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/dist/lib/index.d.mts +3 -3
  2. package/dist/lib/index.d.ts +3 -3
  3. package/dist/lib/index.d.ts.map +1 -1
  4. package/dist/lib/index.js +2 -0
  5. package/dist/lib/index.js.map +1 -1
  6. package/dist/lib/index.mjs +3 -1
  7. package/dist/lib/index.mjs.map +1 -1
  8. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  9. package/dist/lib/server/create-adcp-server.d.mts +2 -2
  10. package/dist/lib/server/create-adcp-server.d.ts +2 -2
  11. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  12. package/dist/lib/server/create-adcp-server.js +6 -1
  13. package/dist/lib/server/create-adcp-server.js.map +1 -1
  14. package/dist/lib/server/create-adcp-server.mjs +6 -1
  15. package/dist/lib/server/create-adcp-server.mjs.map +1 -1
  16. package/dist/lib/server/decisioning/index.d.mts +3 -3
  17. package/dist/lib/server/decisioning/index.d.ts +3 -3
  18. package/dist/lib/server/decisioning/index.d.ts.map +1 -1
  19. package/dist/lib/server/decisioning/index.js.map +1 -1
  20. package/dist/lib/server/decisioning/index.mjs.map +1 -1
  21. package/dist/lib/server/decisioning/runtime/from-platform.d.mts +24 -17
  22. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +24 -17
  23. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
  24. package/dist/lib/server/decisioning/runtime/from-platform.js +71 -42
  25. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  26. package/dist/lib/server/decisioning/runtime/from-platform.mjs +75 -43
  27. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  28. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.mts +15 -21
  29. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +15 -21
  30. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -1
  31. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +100 -30
  32. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -1
  33. package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +100 -30
  34. package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
  35. package/dist/lib/server/decisioning/runtime/task-registry.d.mts +30 -16
  36. package/dist/lib/server/decisioning/runtime/task-registry.d.ts +30 -16
  37. package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -1
  38. package/dist/lib/server/decisioning/runtime/task-registry.js +40 -20
  39. package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -1
  40. package/dist/lib/server/decisioning/runtime/task-registry.mjs +38 -19
  41. package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
  42. package/dist/lib/server/decisioning/runtime/to-context.d.mts +2 -2
  43. package/dist/lib/server/decisioning/runtime/to-context.d.ts +2 -2
  44. package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -1
  45. package/dist/lib/server/decisioning/runtime/to-context.js +2 -2
  46. package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -1
  47. package/dist/lib/server/decisioning/runtime/to-context.mjs +2 -2
  48. package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
  49. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.mts +3 -2
  50. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +3 -2
  51. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -1
  52. package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -1
  53. package/dist/lib/server/decisioning/specialisms/creative.d.mts +10 -10
  54. package/dist/lib/server/decisioning/specialisms/creative.d.ts +10 -10
  55. package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -1
  56. package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -1
  57. package/dist/lib/server/index.d.mts +1 -1
  58. package/dist/lib/server/index.d.ts +1 -1
  59. package/dist/lib/server/index.d.ts.map +1 -1
  60. package/dist/lib/server/index.js.map +1 -1
  61. package/dist/lib/server/index.mjs.map +1 -1
  62. package/dist/lib/testing/storyboard/default-invariants.d.ts.map +1 -1
  63. package/dist/lib/testing/storyboard/default-invariants.js +11 -2
  64. package/dist/lib/testing/storyboard/default-invariants.js.map +1 -1
  65. package/dist/lib/testing/storyboard/default-invariants.mjs +11 -2
  66. package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
  67. package/dist/lib/testing/storyboard/index.d.mts +1 -1
  68. package/dist/lib/testing/storyboard/index.d.ts +1 -1
  69. package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
  70. package/dist/lib/testing/storyboard/index.js.map +1 -1
  71. package/dist/lib/testing/storyboard/index.mjs.map +1 -1
  72. package/dist/lib/testing/storyboard/loader.d.ts.map +1 -1
  73. package/dist/lib/testing/storyboard/loader.js +14 -0
  74. package/dist/lib/testing/storyboard/loader.js.map +1 -1
  75. package/dist/lib/testing/storyboard/loader.mjs +14 -0
  76. package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
  77. package/dist/lib/testing/storyboard/phase-condition.d.mts +41 -0
  78. package/dist/lib/testing/storyboard/phase-condition.d.ts +42 -0
  79. package/dist/lib/testing/storyboard/phase-condition.d.ts.map +1 -0
  80. package/dist/lib/testing/storyboard/phase-condition.js +215 -0
  81. package/dist/lib/testing/storyboard/phase-condition.js.map +1 -0
  82. package/dist/lib/testing/storyboard/phase-condition.mjs +189 -0
  83. package/dist/lib/testing/storyboard/phase-condition.mjs.map +1 -0
  84. package/dist/lib/testing/storyboard/request-builder.d.ts.map +1 -1
  85. package/dist/lib/testing/storyboard/request-builder.js +15 -2
  86. package/dist/lib/testing/storyboard/request-builder.js.map +1 -1
  87. package/dist/lib/testing/storyboard/request-builder.mjs +15 -2
  88. package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
  89. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
  90. package/dist/lib/testing/storyboard/runner.js +57 -23
  91. package/dist/lib/testing/storyboard/runner.js.map +1 -1
  92. package/dist/lib/testing/storyboard/runner.mjs +57 -23
  93. package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
  94. package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
  95. package/dist/lib/testing/storyboard/task-map.js +6 -2
  96. package/dist/lib/testing/storyboard/task-map.js.map +1 -1
  97. package/dist/lib/testing/storyboard/task-map.mjs +6 -2
  98. package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
  99. package/dist/lib/testing/storyboard/types.d.mts +5 -4
  100. package/dist/lib/testing/storyboard/types.d.ts +5 -4
  101. package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
  102. package/dist/lib/testing/storyboard/types.js.map +1 -1
  103. package/dist/lib/testing/storyboard/types.mjs.map +1 -1
  104. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  105. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  106. package/dist/lib/testing/storyboard/webhook-assertions.d.ts.map +1 -1
  107. package/dist/lib/testing/storyboard/webhook-assertions.js +60 -4
  108. package/dist/lib/testing/storyboard/webhook-assertions.js.map +1 -1
  109. package/dist/lib/testing/storyboard/webhook-assertions.mjs +60 -4
  110. package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
  111. package/dist/lib/testing/storyboard/webhook-receiver.d.mts +15 -0
  112. package/dist/lib/testing/storyboard/webhook-receiver.d.ts +15 -0
  113. package/dist/lib/testing/storyboard/webhook-receiver.d.ts.map +1 -1
  114. package/dist/lib/testing/storyboard/webhook-receiver.js +57 -6
  115. package/dist/lib/testing/storyboard/webhook-receiver.js.map +1 -1
  116. package/dist/lib/testing/storyboard/webhook-receiver.mjs +57 -6
  117. package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
  118. package/dist/lib/testing/types.d.mts +2 -0
  119. package/dist/lib/testing/types.d.ts +2 -0
  120. package/dist/lib/testing/types.d.ts.map +1 -1
  121. package/dist/lib/testing/types.js.map +1 -1
  122. package/dist/lib/types/core.generated.d.mts +5 -2
  123. package/dist/lib/types/core.generated.d.ts +5 -2
  124. package/dist/lib/types/core.generated.d.ts.map +1 -1
  125. package/dist/lib/types/core.generated.js.map +1 -1
  126. package/dist/lib/types/index.d.mts +1 -1
  127. package/dist/lib/types/index.d.ts +1 -1
  128. package/dist/lib/types/index.d.ts.map +1 -1
  129. package/dist/lib/types/index.js.map +1 -1
  130. package/dist/lib/types/index.mjs.map +1 -1
  131. package/dist/lib/types/list-transformers.d.ts +9 -5
  132. package/dist/lib/types/schemas.generated.d.ts +21 -298
  133. package/dist/lib/types/schemas.generated.d.ts.map +1 -1
  134. package/dist/lib/types/schemas.generated.js +5 -2
  135. package/dist/lib/types/schemas.generated.js.map +1 -1
  136. package/dist/lib/types/schemas.generated.mjs +4 -2
  137. package/dist/lib/types/schemas.generated.mjs.map +1 -1
  138. package/dist/lib/types/server-payload-aliases.d.mts +2 -1
  139. package/dist/lib/types/server-payload-aliases.d.ts +2 -1
  140. package/dist/lib/types/server-payload-aliases.d.ts.map +1 -1
  141. package/dist/lib/types/server-payload-aliases.js.map +1 -1
  142. package/dist/lib/types/tools.generated.d.mts +5 -2
  143. package/dist/lib/types/tools.generated.d.ts +5 -2
  144. package/dist/lib/types/tools.generated.d.ts.map +1 -1
  145. package/dist/lib/types/tools.generated.js.map +1 -1
  146. package/dist/lib/utils/build-creative-return-builders.d.mts +5 -1
  147. package/dist/lib/utils/build-creative-return-builders.d.ts +5 -1
  148. package/dist/lib/utils/build-creative-return-builders.d.ts.map +1 -1
  149. package/dist/lib/utils/build-creative-return-builders.js +9 -3
  150. package/dist/lib/utils/build-creative-return-builders.js.map +1 -1
  151. package/dist/lib/utils/build-creative-return-builders.mjs +7 -2
  152. package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
  153. package/dist/lib/utils/response-unwrapper.js +1 -1
  154. package/dist/lib/utils/response-unwrapper.js.map +1 -1
  155. package/dist/lib/utils/response-unwrapper.mjs +1 -1
  156. package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
  157. package/dist/lib/validation/schema-loader.d.ts.map +1 -1
  158. package/dist/lib/validation/schema-loader.js +16 -7
  159. package/dist/lib/validation/schema-loader.js.map +1 -1
  160. package/dist/lib/validation/schema-loader.mjs +16 -7
  161. package/dist/lib/validation/schema-loader.mjs.map +1 -1
  162. package/dist/lib/version.d.mts +3 -3
  163. package/dist/lib/version.d.ts +3 -3
  164. package/dist/lib/version.js +3 -3
  165. package/dist/lib/version.js.map +1 -1
  166. package/dist/lib/version.mjs +3 -3
  167. package/dist/lib/version.mjs.map +1 -1
  168. package/docs/llms.txt +2 -2
  169. package/docs/migration-5.x-to-6.x.md +3 -2
  170. package/docs/migration-task-registry-scoping.md +61 -0
  171. package/examples/hello_seller_adapter_guaranteed.ts +1 -1
  172. package/package.json +4 -4
  173. package/skills/build-decisioning-creative-template/SKILL.md +2 -2
  174. package/skills/build-decisioning-platform/SKILL.md +4 -2
  175. package/skills/build-decisioning-platform/advanced/REFERENCE.md +7 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phase-condition.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/phase-condition.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,aAAa,GAAG;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AACzF,KAAK,WAAW,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAChE,KAAK,SAAS,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAC9D,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;CAC9B,CAAC;AACF,KAAK,MAAM,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,kBAAkB,EAAE,CAAA;CAAE,CAAC;AAC7D,KAAK,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;AAC7C,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAO/E,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CAsD1E;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAE9F;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAErE"}
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var phase_condition_exports = {};
20
+ __export(phase_condition_exports, {
21
+ evaluatePhaseCondition: () => evaluatePhaseCondition,
22
+ parsePhaseCondition: () => parsePhaseCondition,
23
+ phaseConditionUsesContext: () => phaseConditionUsesContext
24
+ });
25
+ module.exports = __toCommonJS(phase_condition_exports);
26
+ function parsePhaseCondition(expression) {
27
+ const tokens = tokenize(expression);
28
+ if (tokens.length === 0) throw syntaxError(expression, 0, "expression must not be empty");
29
+ let cursor = 0;
30
+ const peek = () => tokens[cursor];
31
+ const take = () => tokens[cursor++];
32
+ const parseValue = () => {
33
+ const token = peek();
34
+ if (token?.kind === "reference") {
35
+ take();
36
+ return token.value;
37
+ }
38
+ if (token?.kind === "literal") {
39
+ take();
40
+ return { kind: "literal", value: token.value };
41
+ }
42
+ throw syntaxError(expression, token?.offset ?? expression.length, "expected a runtime reference or literal");
43
+ };
44
+ const parseUnary = () => {
45
+ const token = peek();
46
+ if (token?.kind === "not") {
47
+ take();
48
+ return { kind: "not", operand: parseUnary() };
49
+ }
50
+ return parseValue();
51
+ };
52
+ const parseEquality = () => {
53
+ const left = parseUnary();
54
+ const operator = peek();
55
+ if (operator?.kind !== "equals" && operator?.kind !== "not_equals") return left;
56
+ take();
57
+ const right = parseUnary();
58
+ return {
59
+ kind: "equality",
60
+ operator: operator.kind === "equals" ? "==" : "!=",
61
+ left,
62
+ right
63
+ };
64
+ };
65
+ const operands = [parseEquality()];
66
+ while (peek()?.kind === "or") {
67
+ take();
68
+ operands.push(parseEquality());
69
+ }
70
+ const trailing = peek();
71
+ if (trailing) {
72
+ throw syntaxError(expression, trailing.offset, `unsupported token ${JSON.stringify(expression[trailing.offset])}`);
73
+ }
74
+ return operands.length === 1 ? operands[0] : { kind: "or", operands };
75
+ }
76
+ function evaluatePhaseCondition(expression, scope) {
77
+ return Boolean(evaluateNode(parsePhaseCondition(expression), scope));
78
+ }
79
+ function phaseConditionUsesContext(expression) {
80
+ return nodeUsesContext(parsePhaseCondition(expression));
81
+ }
82
+ function evaluateNode(node, scope) {
83
+ switch (node.kind) {
84
+ case "literal":
85
+ return node.value;
86
+ case "reference":
87
+ return resolveReference(node, scope);
88
+ case "not":
89
+ return !Boolean(evaluateNode(node.operand, scope));
90
+ case "equality": {
91
+ const equal = evaluateNode(node.left, scope) === evaluateNode(node.right, scope);
92
+ return node.operator === "==" ? equal : !equal;
93
+ }
94
+ case "or":
95
+ return node.operands.some((operand) => Boolean(evaluateNode(operand, scope)));
96
+ }
97
+ }
98
+ function resolveReference(reference, scope) {
99
+ let value = scope[reference.root];
100
+ for (const segment of reference.path) {
101
+ if (value === null || typeof value !== "object" || !Object.prototype.hasOwnProperty.call(value, segment)) {
102
+ return void 0;
103
+ }
104
+ value = value[segment];
105
+ }
106
+ return value;
107
+ }
108
+ function nodeUsesContext(node) {
109
+ switch (node.kind) {
110
+ case "literal":
111
+ return false;
112
+ case "reference":
113
+ return node.root === "context";
114
+ case "not":
115
+ return nodeUsesContext(node.operand);
116
+ case "equality":
117
+ return nodeUsesContext(node.left) || nodeUsesContext(node.right);
118
+ case "or":
119
+ return node.operands.some(nodeUsesContext);
120
+ }
121
+ }
122
+ function tokenize(expression) {
123
+ const tokens = [];
124
+ let offset = 0;
125
+ while (offset < expression.length) {
126
+ const char = expression[offset];
127
+ if (/\s/.test(char)) {
128
+ offset++;
129
+ continue;
130
+ }
131
+ if (expression.startsWith("||", offset)) {
132
+ tokens.push({ kind: "or", offset });
133
+ offset += 2;
134
+ continue;
135
+ }
136
+ if (expression.startsWith("==", offset)) {
137
+ tokens.push({ kind: "equals", offset });
138
+ offset += 2;
139
+ continue;
140
+ }
141
+ if (expression.startsWith("!=", offset)) {
142
+ tokens.push({ kind: "not_equals", offset });
143
+ offset += 2;
144
+ continue;
145
+ }
146
+ if (char === "!") {
147
+ tokens.push({ kind: "not", offset });
148
+ offset++;
149
+ continue;
150
+ }
151
+ if (char === "'" || char === '"') {
152
+ const literal = readStringLiteral(expression, offset, char);
153
+ tokens.push({ kind: "literal", value: literal.value, offset });
154
+ offset = literal.nextOffset;
155
+ continue;
156
+ }
157
+ const rest = expression.slice(offset);
158
+ const reference = /^(context|test_kit)((?:\.[A-Za-z0-9_]+)+)/.exec(rest);
159
+ if (reference) {
160
+ const full = reference[0];
161
+ const next = rest[full.length];
162
+ if (next && /[A-Za-z0-9_.]/.test(next)) {
163
+ throw syntaxError(expression, offset + full.length, "invalid runtime reference");
164
+ }
165
+ tokens.push({
166
+ kind: "reference",
167
+ value: {
168
+ kind: "reference",
169
+ root: reference[1],
170
+ path: reference[2].slice(1).split(".")
171
+ },
172
+ offset
173
+ });
174
+ offset += full.length;
175
+ continue;
176
+ }
177
+ const boolean = /^(true|false)\b/.exec(rest);
178
+ if (boolean) {
179
+ tokens.push({ kind: "literal", value: boolean[1] === "true", offset });
180
+ offset += boolean[0].length;
181
+ continue;
182
+ }
183
+ throw syntaxError(expression, offset, `unsupported token ${JSON.stringify(char)}`);
184
+ }
185
+ return tokens;
186
+ }
187
+ function readStringLiteral(expression, start, quote) {
188
+ let value = "";
189
+ for (let offset = start + 1; offset < expression.length; offset++) {
190
+ const char = expression[offset];
191
+ if (char === quote) return { value, nextOffset: offset + 1 };
192
+ if (char === "\\") {
193
+ const escaped = expression[offset + 1];
194
+ if (escaped !== quote && escaped !== "\\") {
195
+ throw syntaxError(expression, offset, "string literals only support escaped quotes and backslashes");
196
+ }
197
+ value += escaped;
198
+ offset++;
199
+ continue;
200
+ }
201
+ if (char === "\n" || char === "\r") throw syntaxError(expression, offset, "string literals must stay on one line");
202
+ value += char;
203
+ }
204
+ throw syntaxError(expression, start, "unterminated string literal");
205
+ }
206
+ function syntaxError(expression, offset, detail) {
207
+ return new Error(`invalid skip_if expression at offset ${offset}: ${detail} (${JSON.stringify(expression)})`);
208
+ }
209
+ // Annotate the CommonJS export names for ESM import in node:
210
+ 0 && (module.exports = {
211
+ evaluatePhaseCondition,
212
+ parsePhaseCondition,
213
+ phaseConditionUsesContext
214
+ });
215
+ //# sourceMappingURL=phase-condition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/testing/storyboard/phase-condition.ts"],"sourcesContent":["/**\n * Closed, side-effect-free grammar for storyboard phase `skip_if` guards.\n *\n * Supported forms are deliberately small: runtime references rooted at\n * `context` or `test_kit`, truthiness/negation, `==` / `!=`, boolean and\n * quoted string literals, and logical OR. Anything else is an authoring\n * error rather than an expression that silently falls through to \"run\".\n */\n\nexport type PhaseConditionScope = {\n context?: Record<string, unknown>;\n test_kit?: unknown;\n};\n\ntype ReferenceNode = { kind: 'reference'; root: 'context' | 'test_kit'; path: string[] };\ntype LiteralNode = { kind: 'literal'; value: boolean | string };\ntype UnaryNode = { kind: 'not'; operand: PhaseConditionNode };\ntype EqualityNode = {\n kind: 'equality';\n operator: '==' | '!=';\n left: ValueNode | UnaryNode;\n right: ValueNode | UnaryNode;\n};\ntype OrNode = { kind: 'or'; operands: PhaseConditionNode[] };\ntype ValueNode = ReferenceNode | LiteralNode;\nexport type PhaseConditionNode = ValueNode | UnaryNode | EqualityNode | OrNode;\n\ntype Token =\n | { kind: 'reference'; value: ReferenceNode; offset: number }\n | { kind: 'literal'; value: boolean | string; offset: number }\n | { kind: 'not' | 'equals' | 'not_equals' | 'or'; offset: number };\n\nexport function parsePhaseCondition(expression: string): PhaseConditionNode {\n const tokens = tokenize(expression);\n if (tokens.length === 0) throw syntaxError(expression, 0, 'expression must not be empty');\n\n let cursor = 0;\n const peek = (): Token | undefined => tokens[cursor];\n const take = (): Token => tokens[cursor++]!;\n\n const parseValue = (): ValueNode => {\n const token = peek();\n if (token?.kind === 'reference') {\n take();\n return token.value;\n }\n if (token?.kind === 'literal') {\n take();\n return { kind: 'literal', value: token.value };\n }\n throw syntaxError(expression, token?.offset ?? expression.length, 'expected a runtime reference or literal');\n };\n\n const parseUnary = (): ValueNode | UnaryNode => {\n const token = peek();\n if (token?.kind === 'not') {\n take();\n return { kind: 'not', operand: parseUnary() };\n }\n return parseValue();\n };\n\n const parseEquality = (): PhaseConditionNode => {\n const left = parseUnary();\n const operator = peek();\n if (operator?.kind !== 'equals' && operator?.kind !== 'not_equals') return left;\n take();\n const right = parseUnary();\n return {\n kind: 'equality',\n operator: operator.kind === 'equals' ? '==' : '!=',\n left,\n right,\n };\n };\n\n const operands = [parseEquality()];\n while (peek()?.kind === 'or') {\n take();\n operands.push(parseEquality());\n }\n const trailing = peek();\n if (trailing) {\n throw syntaxError(expression, trailing.offset, `unsupported token ${JSON.stringify(expression[trailing.offset])}`);\n }\n return operands.length === 1 ? operands[0]! : { kind: 'or', operands };\n}\n\nexport function evaluatePhaseCondition(expression: string, scope: PhaseConditionScope): boolean {\n return Boolean(evaluateNode(parsePhaseCondition(expression), scope));\n}\n\nexport function phaseConditionUsesContext(expression: string): boolean {\n return nodeUsesContext(parsePhaseCondition(expression));\n}\n\nfunction evaluateNode(node: PhaseConditionNode, scope: PhaseConditionScope): unknown {\n switch (node.kind) {\n case 'literal':\n return node.value;\n case 'reference':\n return resolveReference(node, scope);\n case 'not':\n return !Boolean(evaluateNode(node.operand, scope));\n case 'equality': {\n const equal = evaluateNode(node.left, scope) === evaluateNode(node.right, scope);\n return node.operator === '==' ? equal : !equal;\n }\n case 'or':\n return node.operands.some(operand => Boolean(evaluateNode(operand, scope)));\n }\n}\n\nfunction resolveReference(reference: ReferenceNode, scope: PhaseConditionScope): unknown {\n let value: unknown = scope[reference.root];\n for (const segment of reference.path) {\n if (value === null || typeof value !== 'object' || !Object.prototype.hasOwnProperty.call(value, segment)) {\n return undefined;\n }\n value = (value as Record<string, unknown>)[segment];\n }\n return value;\n}\n\nfunction nodeUsesContext(node: PhaseConditionNode): boolean {\n switch (node.kind) {\n case 'literal':\n return false;\n case 'reference':\n return node.root === 'context';\n case 'not':\n return nodeUsesContext(node.operand);\n case 'equality':\n return nodeUsesContext(node.left) || nodeUsesContext(node.right);\n case 'or':\n return node.operands.some(nodeUsesContext);\n }\n}\n\nfunction tokenize(expression: string): Token[] {\n const tokens: Token[] = [];\n let offset = 0;\n while (offset < expression.length) {\n const char = expression[offset]!;\n if (/\\s/.test(char)) {\n offset++;\n continue;\n }\n if (expression.startsWith('||', offset)) {\n tokens.push({ kind: 'or', offset });\n offset += 2;\n continue;\n }\n if (expression.startsWith('==', offset)) {\n tokens.push({ kind: 'equals', offset });\n offset += 2;\n continue;\n }\n if (expression.startsWith('!=', offset)) {\n tokens.push({ kind: 'not_equals', offset });\n offset += 2;\n continue;\n }\n if (char === '!') {\n tokens.push({ kind: 'not', offset });\n offset++;\n continue;\n }\n if (char === \"'\" || char === '\"') {\n const literal = readStringLiteral(expression, offset, char);\n tokens.push({ kind: 'literal', value: literal.value, offset });\n offset = literal.nextOffset;\n continue;\n }\n\n const rest = expression.slice(offset);\n // Preserve the original test-kit path compatibility: authored fixture\n // maps may use numeric-leading keys such as format dimensions (`300x250`).\n const reference = /^(context|test_kit)((?:\\.[A-Za-z0-9_]+)+)/.exec(rest);\n if (reference) {\n const full = reference[0]!;\n const next = rest[full.length];\n if (next && /[A-Za-z0-9_.]/.test(next)) {\n throw syntaxError(expression, offset + full.length, 'invalid runtime reference');\n }\n tokens.push({\n kind: 'reference',\n value: {\n kind: 'reference',\n root: reference[1] as 'context' | 'test_kit',\n path: reference[2]!.slice(1).split('.'),\n },\n offset,\n });\n offset += full.length;\n continue;\n }\n\n const boolean = /^(true|false)\\b/.exec(rest);\n if (boolean) {\n tokens.push({ kind: 'literal', value: boolean[1] === 'true', offset });\n offset += boolean[0].length;\n continue;\n }\n throw syntaxError(expression, offset, `unsupported token ${JSON.stringify(char)}`);\n }\n return tokens;\n}\n\nfunction readStringLiteral(expression: string, start: number, quote: \"'\" | '\"'): { value: string; nextOffset: number } {\n let value = '';\n for (let offset = start + 1; offset < expression.length; offset++) {\n const char = expression[offset]!;\n if (char === quote) return { value, nextOffset: offset + 1 };\n if (char === '\\\\') {\n const escaped = expression[offset + 1];\n if (escaped !== quote && escaped !== '\\\\') {\n throw syntaxError(expression, offset, 'string literals only support escaped quotes and backslashes');\n }\n value += escaped;\n offset++;\n continue;\n }\n if (char === '\\n' || char === '\\r') throw syntaxError(expression, offset, 'string literals must stay on one line');\n value += char;\n }\n throw syntaxError(expression, start, 'unterminated string literal');\n}\n\nfunction syntaxError(expression: string, offset: number, detail: string): Error {\n return new Error(`invalid skip_if expression at offset ${offset}: ${detail} (${JSON.stringify(expression)})`);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,189 @@
1
+ function parsePhaseCondition(expression) {
2
+ const tokens = tokenize(expression);
3
+ if (tokens.length === 0) throw syntaxError(expression, 0, "expression must not be empty");
4
+ let cursor = 0;
5
+ const peek = () => tokens[cursor];
6
+ const take = () => tokens[cursor++];
7
+ const parseValue = () => {
8
+ const token = peek();
9
+ if (token?.kind === "reference") {
10
+ take();
11
+ return token.value;
12
+ }
13
+ if (token?.kind === "literal") {
14
+ take();
15
+ return { kind: "literal", value: token.value };
16
+ }
17
+ throw syntaxError(expression, token?.offset ?? expression.length, "expected a runtime reference or literal");
18
+ };
19
+ const parseUnary = () => {
20
+ const token = peek();
21
+ if (token?.kind === "not") {
22
+ take();
23
+ return { kind: "not", operand: parseUnary() };
24
+ }
25
+ return parseValue();
26
+ };
27
+ const parseEquality = () => {
28
+ const left = parseUnary();
29
+ const operator = peek();
30
+ if (operator?.kind !== "equals" && operator?.kind !== "not_equals") return left;
31
+ take();
32
+ const right = parseUnary();
33
+ return {
34
+ kind: "equality",
35
+ operator: operator.kind === "equals" ? "==" : "!=",
36
+ left,
37
+ right
38
+ };
39
+ };
40
+ const operands = [parseEquality()];
41
+ while (peek()?.kind === "or") {
42
+ take();
43
+ operands.push(parseEquality());
44
+ }
45
+ const trailing = peek();
46
+ if (trailing) {
47
+ throw syntaxError(expression, trailing.offset, `unsupported token ${JSON.stringify(expression[trailing.offset])}`);
48
+ }
49
+ return operands.length === 1 ? operands[0] : { kind: "or", operands };
50
+ }
51
+ function evaluatePhaseCondition(expression, scope) {
52
+ return Boolean(evaluateNode(parsePhaseCondition(expression), scope));
53
+ }
54
+ function phaseConditionUsesContext(expression) {
55
+ return nodeUsesContext(parsePhaseCondition(expression));
56
+ }
57
+ function evaluateNode(node, scope) {
58
+ switch (node.kind) {
59
+ case "literal":
60
+ return node.value;
61
+ case "reference":
62
+ return resolveReference(node, scope);
63
+ case "not":
64
+ return !Boolean(evaluateNode(node.operand, scope));
65
+ case "equality": {
66
+ const equal = evaluateNode(node.left, scope) === evaluateNode(node.right, scope);
67
+ return node.operator === "==" ? equal : !equal;
68
+ }
69
+ case "or":
70
+ return node.operands.some((operand) => Boolean(evaluateNode(operand, scope)));
71
+ }
72
+ }
73
+ function resolveReference(reference, scope) {
74
+ let value = scope[reference.root];
75
+ for (const segment of reference.path) {
76
+ if (value === null || typeof value !== "object" || !Object.prototype.hasOwnProperty.call(value, segment)) {
77
+ return void 0;
78
+ }
79
+ value = value[segment];
80
+ }
81
+ return value;
82
+ }
83
+ function nodeUsesContext(node) {
84
+ switch (node.kind) {
85
+ case "literal":
86
+ return false;
87
+ case "reference":
88
+ return node.root === "context";
89
+ case "not":
90
+ return nodeUsesContext(node.operand);
91
+ case "equality":
92
+ return nodeUsesContext(node.left) || nodeUsesContext(node.right);
93
+ case "or":
94
+ return node.operands.some(nodeUsesContext);
95
+ }
96
+ }
97
+ function tokenize(expression) {
98
+ const tokens = [];
99
+ let offset = 0;
100
+ while (offset < expression.length) {
101
+ const char = expression[offset];
102
+ if (/\s/.test(char)) {
103
+ offset++;
104
+ continue;
105
+ }
106
+ if (expression.startsWith("||", offset)) {
107
+ tokens.push({ kind: "or", offset });
108
+ offset += 2;
109
+ continue;
110
+ }
111
+ if (expression.startsWith("==", offset)) {
112
+ tokens.push({ kind: "equals", offset });
113
+ offset += 2;
114
+ continue;
115
+ }
116
+ if (expression.startsWith("!=", offset)) {
117
+ tokens.push({ kind: "not_equals", offset });
118
+ offset += 2;
119
+ continue;
120
+ }
121
+ if (char === "!") {
122
+ tokens.push({ kind: "not", offset });
123
+ offset++;
124
+ continue;
125
+ }
126
+ if (char === "'" || char === '"') {
127
+ const literal = readStringLiteral(expression, offset, char);
128
+ tokens.push({ kind: "literal", value: literal.value, offset });
129
+ offset = literal.nextOffset;
130
+ continue;
131
+ }
132
+ const rest = expression.slice(offset);
133
+ const reference = /^(context|test_kit)((?:\.[A-Za-z0-9_]+)+)/.exec(rest);
134
+ if (reference) {
135
+ const full = reference[0];
136
+ const next = rest[full.length];
137
+ if (next && /[A-Za-z0-9_.]/.test(next)) {
138
+ throw syntaxError(expression, offset + full.length, "invalid runtime reference");
139
+ }
140
+ tokens.push({
141
+ kind: "reference",
142
+ value: {
143
+ kind: "reference",
144
+ root: reference[1],
145
+ path: reference[2].slice(1).split(".")
146
+ },
147
+ offset
148
+ });
149
+ offset += full.length;
150
+ continue;
151
+ }
152
+ const boolean = /^(true|false)\b/.exec(rest);
153
+ if (boolean) {
154
+ tokens.push({ kind: "literal", value: boolean[1] === "true", offset });
155
+ offset += boolean[0].length;
156
+ continue;
157
+ }
158
+ throw syntaxError(expression, offset, `unsupported token ${JSON.stringify(char)}`);
159
+ }
160
+ return tokens;
161
+ }
162
+ function readStringLiteral(expression, start, quote) {
163
+ let value = "";
164
+ for (let offset = start + 1; offset < expression.length; offset++) {
165
+ const char = expression[offset];
166
+ if (char === quote) return { value, nextOffset: offset + 1 };
167
+ if (char === "\\") {
168
+ const escaped = expression[offset + 1];
169
+ if (escaped !== quote && escaped !== "\\") {
170
+ throw syntaxError(expression, offset, "string literals only support escaped quotes and backslashes");
171
+ }
172
+ value += escaped;
173
+ offset++;
174
+ continue;
175
+ }
176
+ if (char === "\n" || char === "\r") throw syntaxError(expression, offset, "string literals must stay on one line");
177
+ value += char;
178
+ }
179
+ throw syntaxError(expression, start, "unterminated string literal");
180
+ }
181
+ function syntaxError(expression, offset, detail) {
182
+ return new Error(`invalid skip_if expression at offset ${offset}: ${detail} (${JSON.stringify(expression)})`);
183
+ }
184
+ export {
185
+ evaluatePhaseCondition,
186
+ parsePhaseCondition,
187
+ phaseConditionUsesContext
188
+ };
189
+ //# sourceMappingURL=phase-condition.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/testing/storyboard/phase-condition.ts"],"sourcesContent":["/**\n * Closed, side-effect-free grammar for storyboard phase `skip_if` guards.\n *\n * Supported forms are deliberately small: runtime references rooted at\n * `context` or `test_kit`, truthiness/negation, `==` / `!=`, boolean and\n * quoted string literals, and logical OR. Anything else is an authoring\n * error rather than an expression that silently falls through to \"run\".\n */\n\nexport type PhaseConditionScope = {\n context?: Record<string, unknown>;\n test_kit?: unknown;\n};\n\ntype ReferenceNode = { kind: 'reference'; root: 'context' | 'test_kit'; path: string[] };\ntype LiteralNode = { kind: 'literal'; value: boolean | string };\ntype UnaryNode = { kind: 'not'; operand: PhaseConditionNode };\ntype EqualityNode = {\n kind: 'equality';\n operator: '==' | '!=';\n left: ValueNode | UnaryNode;\n right: ValueNode | UnaryNode;\n};\ntype OrNode = { kind: 'or'; operands: PhaseConditionNode[] };\ntype ValueNode = ReferenceNode | LiteralNode;\nexport type PhaseConditionNode = ValueNode | UnaryNode | EqualityNode | OrNode;\n\ntype Token =\n | { kind: 'reference'; value: ReferenceNode; offset: number }\n | { kind: 'literal'; value: boolean | string; offset: number }\n | { kind: 'not' | 'equals' | 'not_equals' | 'or'; offset: number };\n\nexport function parsePhaseCondition(expression: string): PhaseConditionNode {\n const tokens = tokenize(expression);\n if (tokens.length === 0) throw syntaxError(expression, 0, 'expression must not be empty');\n\n let cursor = 0;\n const peek = (): Token | undefined => tokens[cursor];\n const take = (): Token => tokens[cursor++]!;\n\n const parseValue = (): ValueNode => {\n const token = peek();\n if (token?.kind === 'reference') {\n take();\n return token.value;\n }\n if (token?.kind === 'literal') {\n take();\n return { kind: 'literal', value: token.value };\n }\n throw syntaxError(expression, token?.offset ?? expression.length, 'expected a runtime reference or literal');\n };\n\n const parseUnary = (): ValueNode | UnaryNode => {\n const token = peek();\n if (token?.kind === 'not') {\n take();\n return { kind: 'not', operand: parseUnary() };\n }\n return parseValue();\n };\n\n const parseEquality = (): PhaseConditionNode => {\n const left = parseUnary();\n const operator = peek();\n if (operator?.kind !== 'equals' && operator?.kind !== 'not_equals') return left;\n take();\n const right = parseUnary();\n return {\n kind: 'equality',\n operator: operator.kind === 'equals' ? '==' : '!=',\n left,\n right,\n };\n };\n\n const operands = [parseEquality()];\n while (peek()?.kind === 'or') {\n take();\n operands.push(parseEquality());\n }\n const trailing = peek();\n if (trailing) {\n throw syntaxError(expression, trailing.offset, `unsupported token ${JSON.stringify(expression[trailing.offset])}`);\n }\n return operands.length === 1 ? operands[0]! : { kind: 'or', operands };\n}\n\nexport function evaluatePhaseCondition(expression: string, scope: PhaseConditionScope): boolean {\n return Boolean(evaluateNode(parsePhaseCondition(expression), scope));\n}\n\nexport function phaseConditionUsesContext(expression: string): boolean {\n return nodeUsesContext(parsePhaseCondition(expression));\n}\n\nfunction evaluateNode(node: PhaseConditionNode, scope: PhaseConditionScope): unknown {\n switch (node.kind) {\n case 'literal':\n return node.value;\n case 'reference':\n return resolveReference(node, scope);\n case 'not':\n return !Boolean(evaluateNode(node.operand, scope));\n case 'equality': {\n const equal = evaluateNode(node.left, scope) === evaluateNode(node.right, scope);\n return node.operator === '==' ? equal : !equal;\n }\n case 'or':\n return node.operands.some(operand => Boolean(evaluateNode(operand, scope)));\n }\n}\n\nfunction resolveReference(reference: ReferenceNode, scope: PhaseConditionScope): unknown {\n let value: unknown = scope[reference.root];\n for (const segment of reference.path) {\n if (value === null || typeof value !== 'object' || !Object.prototype.hasOwnProperty.call(value, segment)) {\n return undefined;\n }\n value = (value as Record<string, unknown>)[segment];\n }\n return value;\n}\n\nfunction nodeUsesContext(node: PhaseConditionNode): boolean {\n switch (node.kind) {\n case 'literal':\n return false;\n case 'reference':\n return node.root === 'context';\n case 'not':\n return nodeUsesContext(node.operand);\n case 'equality':\n return nodeUsesContext(node.left) || nodeUsesContext(node.right);\n case 'or':\n return node.operands.some(nodeUsesContext);\n }\n}\n\nfunction tokenize(expression: string): Token[] {\n const tokens: Token[] = [];\n let offset = 0;\n while (offset < expression.length) {\n const char = expression[offset]!;\n if (/\\s/.test(char)) {\n offset++;\n continue;\n }\n if (expression.startsWith('||', offset)) {\n tokens.push({ kind: 'or', offset });\n offset += 2;\n continue;\n }\n if (expression.startsWith('==', offset)) {\n tokens.push({ kind: 'equals', offset });\n offset += 2;\n continue;\n }\n if (expression.startsWith('!=', offset)) {\n tokens.push({ kind: 'not_equals', offset });\n offset += 2;\n continue;\n }\n if (char === '!') {\n tokens.push({ kind: 'not', offset });\n offset++;\n continue;\n }\n if (char === \"'\" || char === '\"') {\n const literal = readStringLiteral(expression, offset, char);\n tokens.push({ kind: 'literal', value: literal.value, offset });\n offset = literal.nextOffset;\n continue;\n }\n\n const rest = expression.slice(offset);\n // Preserve the original test-kit path compatibility: authored fixture\n // maps may use numeric-leading keys such as format dimensions (`300x250`).\n const reference = /^(context|test_kit)((?:\\.[A-Za-z0-9_]+)+)/.exec(rest);\n if (reference) {\n const full = reference[0]!;\n const next = rest[full.length];\n if (next && /[A-Za-z0-9_.]/.test(next)) {\n throw syntaxError(expression, offset + full.length, 'invalid runtime reference');\n }\n tokens.push({\n kind: 'reference',\n value: {\n kind: 'reference',\n root: reference[1] as 'context' | 'test_kit',\n path: reference[2]!.slice(1).split('.'),\n },\n offset,\n });\n offset += full.length;\n continue;\n }\n\n const boolean = /^(true|false)\\b/.exec(rest);\n if (boolean) {\n tokens.push({ kind: 'literal', value: boolean[1] === 'true', offset });\n offset += boolean[0].length;\n continue;\n }\n throw syntaxError(expression, offset, `unsupported token ${JSON.stringify(char)}`);\n }\n return tokens;\n}\n\nfunction readStringLiteral(expression: string, start: number, quote: \"'\" | '\"'): { value: string; nextOffset: number } {\n let value = '';\n for (let offset = start + 1; offset < expression.length; offset++) {\n const char = expression[offset]!;\n if (char === quote) return { value, nextOffset: offset + 1 };\n if (char === '\\\\') {\n const escaped = expression[offset + 1];\n if (escaped !== quote && escaped !== '\\\\') {\n throw syntaxError(expression, offset, 'string literals only support escaped quotes and backslashes');\n }\n value += escaped;\n offset++;\n continue;\n }\n if (char === '\\n' || char === '\\r') throw syntaxError(expression, offset, 'string literals must stay on one line');\n value += char;\n }\n throw syntaxError(expression, start, 'unterminated string literal');\n}\n\nfunction syntaxError(expression: string, offset: number, detail: string): Error {\n return new Error(`invalid skip_if expression at offset ${offset}: ${detail} (${JSON.stringify(expression)})`);\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"request-builder.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/request-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAu+BhE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,WAAW,EACpB,UAAU,CAAC,EAAE,eAAe,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA4BzB;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D;AAQD,6DAA6D;AAC7D,eAAO,MAAM,YAAY,sBAAgB,CAAC;AAE1C,kEAAkE;AAClE,eAAO,MAAM,iBAAiB,2BAAqB,CAAC"}
1
+ {"version":3,"file":"request-builder.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/request-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AA+/BhE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,WAAW,EACpB,UAAU,CAAC,EAAE,eAAe,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA4BzB;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D;AAQD,6DAA6D;AAC7D,eAAO,MAAM,YAAY,sBAAgB,CAAC;AAE1C,kEAAkE;AAClE,eAAO,MAAM,iBAAiB,2BAAqB,CAAC"}
@@ -34,6 +34,8 @@ const FIXTURE_AWARE_ENRICHERS = /* @__PURE__ */ new Set([
34
34
  // merges discovery-derived product_id / pricing_option_id INTO fixture packages[0]
35
35
  "comply_test_controller",
36
36
  // forces account.sandbox: true regardless of fixture
37
+ "check_governance",
38
+ // preserves the authored intent-vs-delivery request shape
37
39
  "get_products",
38
40
  // preserves wholesale fixture fields while keeping resolved account scope authoritative
39
41
  "update_media_buy",
@@ -491,8 +493,18 @@ const REQUEST_ENRICHERS = {
491
493
  ]
492
494
  };
493
495
  },
494
- check_governance(step, context, options) {
495
- return {
496
+ check_governance(step, context, options, runnerVars) {
497
+ const fixture = step.sample_request !== void 0 ? omitEnvelopeFields(
498
+ (0, import_context.injectContext)({ ...step.sample_request }, context, runnerVars)
499
+ ) : void 0;
500
+ const isDelivery = fixture?.phase === "delivery" || fixture?.planned_delivery !== void 0 || fixture?.delivery_metrics !== void 0 || fixture?.governance_context !== void 0;
501
+ if (fixture && isDelivery) {
502
+ return {
503
+ ...fixture,
504
+ caller: fixture.caller ?? FALLBACK_CALLER_AGENT_URL
505
+ };
506
+ }
507
+ const fallback = {
496
508
  plan_id: context.plan_id ?? "unknown",
497
509
  caller: FALLBACK_CALLER_AGENT_URL,
498
510
  tool: "get_products",
@@ -504,6 +516,7 @@ const REQUEST_ENRICHERS = {
504
516
  total_budget: options.budget ?? 1e4
505
517
  }
506
518
  };
519
+ return fixture ? { ...fallback, ...fixture } : fallback;
507
520
  },
508
521
  get_account_financials(_step, context, options) {
509
522
  return {