@adcp/sdk 16.2.0 → 16.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -0
- package/dist/lib/core/AgentClient.js +17 -1
- package/dist/lib/core/AgentClient.mjs +17 -1
- package/dist/lib/core/SingleAgentClient.js +13 -0
- package/dist/lib/core/SingleAgentClient.mjs +13 -0
- package/dist/lib/core/TaskExecutor.js +88 -13
- package/dist/lib/core/TaskExecutor.mjs +89 -14
- package/dist/lib/errors/index.d.mts +34 -0
- package/dist/lib/errors/index.d.ts +34 -0
- package/dist/lib/errors/index.js +11 -0
- package/dist/lib/errors/index.mjs +10 -0
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.mjs +2 -0
- package/dist/lib/media-buy/compatibility.d.mts +1 -0
- package/dist/lib/media-buy/compatibility.d.ts +1 -0
- package/dist/lib/media-buy/compatibility.js +33 -10
- package/dist/lib/media-buy/compatibility.mjs +32 -14
- package/dist/lib/negotiation/buyer.js +11 -5
- package/dist/lib/negotiation/buyer.mjs +11 -5
- package/dist/lib/negotiation/types.d.mts +4 -2
- package/dist/lib/negotiation/types.d.ts +4 -2
- package/dist/lib/negotiation/verification.d.mts +15 -6
- package/dist/lib/negotiation/verification.d.ts +15 -6
- package/dist/lib/negotiation/verification.js +146 -27
- package/dist/lib/negotiation/verification.mjs +146 -28
- package/dist/lib/negotiation/version.d.mts +6 -0
- package/dist/lib/negotiation/version.d.ts +6 -0
- package/dist/lib/negotiation/version.js +60 -0
- package/dist/lib/negotiation/version.mjs +33 -0
- package/dist/lib/server/create-adcp-server.js +1 -1
- package/dist/lib/server/create-adcp-server.mjs +1 -1
- package/dist/lib/server/error-arm-tools.d.mts +10 -10
- package/dist/lib/server/error-arm-tools.d.ts +10 -10
- package/dist/lib/server/error-arm-tools.js +22 -58
- package/dist/lib/server/error-arm-tools.mjs +30 -65
- package/dist/lib/testing/compliance/comply.js +17 -0
- package/dist/lib/testing/compliance/comply.mjs +17 -0
- package/dist/lib/testing/index.d.mts +3 -0
- package/dist/lib/testing/index.d.ts +3 -0
- package/dist/lib/testing/index.js +44 -2
- package/dist/lib/testing/index.mjs +42 -0
- package/dist/lib/testing/storyboard/collection-selection.d.mts +259 -0
- package/dist/lib/testing/storyboard/collection-selection.d.ts +259 -0
- package/dist/lib/testing/storyboard/collection-selection.js +384 -0
- package/dist/lib/testing/storyboard/collection-selection.mjs +348 -0
- package/dist/lib/testing/storyboard/context.js +12 -6
- package/dist/lib/testing/storyboard/context.mjs +12 -6
- package/dist/lib/testing/storyboard/fixture-resolution.d.mts +39 -1
- package/dist/lib/testing/storyboard/fixture-resolution.d.ts +39 -1
- package/dist/lib/testing/storyboard/fixture-resolution.js +216 -12
- package/dist/lib/testing/storyboard/fixture-resolution.mjs +218 -12
- package/dist/lib/testing/storyboard/index.d.mts +9 -2
- package/dist/lib/testing/storyboard/index.d.ts +9 -2
- package/dist/lib/testing/storyboard/index.js +51 -2
- package/dist/lib/testing/storyboard/index.mjs +49 -1
- package/dist/lib/testing/storyboard/prepared-fixtures.d.mts +471 -0
- package/dist/lib/testing/storyboard/prepared-fixtures.d.ts +471 -0
- package/dist/lib/testing/storyboard/prepared-fixtures.js +434 -0
- package/dist/lib/testing/storyboard/prepared-fixtures.mjs +389 -0
- package/dist/lib/testing/storyboard/protected-context.d.mts +127 -0
- package/dist/lib/testing/storyboard/protected-context.d.ts +127 -0
- package/dist/lib/testing/storyboard/protected-context.js +301 -0
- package/dist/lib/testing/storyboard/protected-context.mjs +267 -0
- package/dist/lib/testing/storyboard/rejection-hints.js +13 -4
- package/dist/lib/testing/storyboard/rejection-hints.mjs +13 -4
- package/dist/lib/testing/storyboard/runner.d.mts +24 -0
- package/dist/lib/testing/storyboard/runner.d.ts +24 -0
- package/dist/lib/testing/storyboard/runner.js +1061 -105
- package/dist/lib/testing/storyboard/runner.mjs +1075 -106
- package/dist/lib/testing/storyboard/seeding.d.mts +15 -1
- package/dist/lib/testing/storyboard/seeding.d.ts +15 -1
- package/dist/lib/testing/storyboard/seeding.js +272 -12
- package/dist/lib/testing/storyboard/seeding.mjs +274 -13
- package/dist/lib/testing/storyboard/types.d.mts +207 -10
- package/dist/lib/testing/storyboard/types.d.ts +207 -10
- package/dist/lib/testing/storyboard/types.js +1 -1
- package/dist/lib/testing/storyboard/types.mjs +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/storyboard/validations.js +95 -0
- package/dist/lib/testing/storyboard/validations.mjs +95 -0
- package/dist/lib/validation/bundled-schema-store.js +5 -0
- package/dist/lib/validation/bundled-schema-store.mjs +4 -0
- package/dist/lib/validation/schema-loader.js +19 -2
- package/dist/lib/validation/schema-loader.mjs +22 -3
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +1 -1
- package/docs/guides/COLLECTION-FIXTURE-FOUNDATION.md +850 -0
- package/docs/guides/PROPOSAL-TERMS-VERIFICATION.md +66 -0
- package/docs/llms.txt +3 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/package.json +1 -1
|
@@ -21,7 +21,9 @@ __export(fixture_resolution_exports, {
|
|
|
21
21
|
FixtureBindingRegistry: () => FixtureBindingRegistry,
|
|
22
22
|
applyFixtureBindingsToRequest: () => applyFixtureBindingsToRequest,
|
|
23
23
|
buildFixtureResolutionSpecs: () => buildFixtureResolutionSpecs,
|
|
24
|
+
matchFixtureRequirementsWithWitness: () => matchFixtureRequirementsWithWitness,
|
|
24
25
|
matchesFixtureRequirements: () => matchesFixtureRequirements,
|
|
26
|
+
normalizeFixtureContextOutputs: () => normalizeFixtureContextOutputs,
|
|
25
27
|
normalizeFixtureMatchExpression: () => normalizeFixtureMatchExpression,
|
|
26
28
|
validateFixtureResolutionDeclarations: () => validateFixtureResolutionDeclarations
|
|
27
29
|
});
|
|
@@ -30,8 +32,18 @@ var import_node_util = require("node:util");
|
|
|
30
32
|
var import_version = require('../../version.js');
|
|
31
33
|
var import_schema_loader = require('../../validation/schema-loader.js');
|
|
32
34
|
var import_canonical_format_satisfaction = require('./canonical-format-satisfaction.js');
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
var import_collection_selection = require('./collection-selection.js');
|
|
36
|
+
var import_path = require('./path.js');
|
|
37
|
+
var import_protected_context = require('./protected-context.js');
|
|
38
|
+
const OPERATORS = [
|
|
39
|
+
"equals",
|
|
40
|
+
"present",
|
|
41
|
+
"contains_all",
|
|
42
|
+
"any_match",
|
|
43
|
+
"canonical_format_satisfies",
|
|
44
|
+
"collection_selection_satisfies"
|
|
45
|
+
];
|
|
46
|
+
const DECLARATION_KEYS = /* @__PURE__ */ new Set(["handle", "strategies", "match", "allow_reuse", "context_outputs"]);
|
|
35
47
|
const PRICING_DECLARATION_KEYS = /* @__PURE__ */ new Set([...DECLARATION_KEYS, "product_handle"]);
|
|
36
48
|
function isRecord(value) {
|
|
37
49
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -103,6 +115,12 @@ function normalizeClause(value, location) {
|
|
|
103
115
|
operator,
|
|
104
116
|
where: normalizeFixtureMatchExpression(value.where, `${location}.where`)
|
|
105
117
|
};
|
|
118
|
+
case "collection_selection_satisfies":
|
|
119
|
+
return {
|
|
120
|
+
path: value.path,
|
|
121
|
+
operator,
|
|
122
|
+
value: (0, import_collection_selection.normalizeCollectionSelectionSelector)(value.value, `${location}.value`)
|
|
123
|
+
};
|
|
106
124
|
case "canonical_format_satisfies":
|
|
107
125
|
assertPlainObject(value.value, `${location}.value`);
|
|
108
126
|
if (typeof value.value.format_kind !== "string" || value.value.format_kind.length === 0) {
|
|
@@ -114,7 +132,7 @@ function normalizeClause(value, location) {
|
|
|
114
132
|
return { path: value.path, operator, value: value.value };
|
|
115
133
|
}
|
|
116
134
|
}
|
|
117
|
-
function validateDeclaration(declaration, location, allowedKeys) {
|
|
135
|
+
function validateDeclaration(declaration, location, allowedKeys, entityKind = "product") {
|
|
118
136
|
assertPlainObject(declaration, location);
|
|
119
137
|
const unknown = Object.keys(declaration).filter((key) => !allowedKeys.has(key));
|
|
120
138
|
if (unknown.length > 0) throw new Error(`${location}: unknown key(s): ${unknown.join(", ")}`);
|
|
@@ -142,10 +160,87 @@ function validateDeclaration(declaration, location, allowedKeys) {
|
|
|
142
160
|
if (Array.isArray(declaration.strategies) && declaration.strategies.includes("discover") && clauses.length === 0) {
|
|
143
161
|
throw new Error(`${location}.match: discover strategy requires at least one authored predicate`);
|
|
144
162
|
}
|
|
163
|
+
normalizeFixtureContextOutputs(declaration.context_outputs, `${location}.context_outputs`, clauses, entityKind);
|
|
164
|
+
}
|
|
165
|
+
const FIXTURE_CONTEXT_OUTPUT_KEYS = /* @__PURE__ */ new Set(["key", "path", "witness", "snapshot"]);
|
|
166
|
+
function normalizeFixtureContextOutputs(value, location, clauses, entityKind = "product") {
|
|
167
|
+
if (value === void 0) return [];
|
|
168
|
+
assertArray(value, location);
|
|
169
|
+
if (value.length === 0) throw new Error(`${location}: must contain at least one capture when present`);
|
|
170
|
+
const hasCollectionPredicate = clauses.some((clause) => clause.operator === "collection_selection_satisfies");
|
|
171
|
+
const seen = /* @__PURE__ */ new Set();
|
|
172
|
+
return value.map((raw, index) => {
|
|
173
|
+
const entryLocation = `${location}[${index}]`;
|
|
174
|
+
assertPlainObject(raw, entryLocation);
|
|
175
|
+
const unknown = Object.keys(raw).filter((key) => !FIXTURE_CONTEXT_OUTPUT_KEYS.has(key));
|
|
176
|
+
if (unknown.length > 0) {
|
|
177
|
+
throw new Error(`${entryLocation}: unknown key(s): ${unknown.join(", ")}`);
|
|
178
|
+
}
|
|
179
|
+
if (typeof raw.key !== "string" || raw.key.length === 0) {
|
|
180
|
+
throw new Error(`${entryLocation}.key: must be a non-empty string`);
|
|
181
|
+
}
|
|
182
|
+
if (!(0, import_protected_context.isProtectedContextKey)(raw.key)) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
`${entryLocation}.key: fixture captures must use the reserved "__adcp_fixture_" prefix so later steps, caller context and seller responses cannot replace them; received "${raw.key}"`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
(0, import_protected_context.assertWellFormedProtectedKey)(raw.key, entryLocation + ".key");
|
|
188
|
+
if (seen.has(raw.key)) throw new Error(`${entryLocation}.key: duplicate capture key "${raw.key}"`);
|
|
189
|
+
seen.add(raw.key);
|
|
190
|
+
const forms = ["path", "witness", "snapshot"].filter((form) => Object.hasOwn(raw, form));
|
|
191
|
+
if (forms.length !== 1) {
|
|
192
|
+
throw new Error(
|
|
193
|
+
`${entryLocation}: must set exactly one of 'path', 'witness' or 'snapshot'; received ${forms.length === 0 ? "none" : forms.join(" + ")}`
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
const hasPath = forms[0] === "path";
|
|
197
|
+
if (forms[0] === "snapshot") {
|
|
198
|
+
if (raw.snapshot !== "selected_entity") {
|
|
199
|
+
throw new Error(`${entryLocation}.snapshot: must be 'selected_entity'`);
|
|
200
|
+
}
|
|
201
|
+
return { key: raw.key, snapshot: "selected_entity" };
|
|
202
|
+
}
|
|
203
|
+
if (hasPath) {
|
|
204
|
+
if (typeof raw.path !== "string" || raw.path.length === 0) {
|
|
205
|
+
throw new Error(`${entryLocation}.path: must be a non-empty string`);
|
|
206
|
+
}
|
|
207
|
+
if (raw.path.startsWith("/")) {
|
|
208
|
+
throw new Error(
|
|
209
|
+
`${entryLocation}.path: capture paths use the dotted storyboard grammar ("currency", "pricing_options[0].rate"), not the RFC 6901 pointers that match[].path takes; drop the leading "/" \u2014 received "${raw.path}"`
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
if ((0, import_path.parsePath)(raw.path).length === 0) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
`${entryLocation}.path: must name at least one field in the dotted storyboard grammar ("currency", "pricing_options[0].rate") \u2014 received "${raw.path}", which resolves to the whole selected entity. To capture the whole entity, say so: snapshot: 'selected_entity'.`
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
if (raw.path.split(".").some((segment) => segment.length === 0)) {
|
|
218
|
+
throw new Error(`${entryLocation}.path: every dotted segment must name a field \u2014 received "${raw.path}".`);
|
|
219
|
+
}
|
|
220
|
+
return { key: raw.key, path: raw.path };
|
|
221
|
+
}
|
|
222
|
+
if (typeof raw.witness !== "string" || !import_collection_selection.COLLECTION_WITNESS_KINDS.includes(raw.witness)) {
|
|
223
|
+
throw new Error(`${entryLocation}.witness: must be one of ${import_collection_selection.COLLECTION_WITNESS_KINDS.join(", ")}`);
|
|
224
|
+
}
|
|
225
|
+
if (entityKind === "pricing_option") {
|
|
226
|
+
throw new Error(
|
|
227
|
+
`${entryLocation}.witness: a collection witness describes the product, not one of its pricing options; declare it under fixture_resolution.products.<product_handle>.context_outputs instead`
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
if (!hasCollectionPredicate) {
|
|
231
|
+
throw new Error(
|
|
232
|
+
`${entryLocation}.witness: requires a collection_selection_satisfies predicate on the same declaration`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
return { key: raw.key, witness: raw.witness };
|
|
236
|
+
});
|
|
145
237
|
}
|
|
146
238
|
function validateFixtureResolutionDeclarations(storyboard) {
|
|
147
239
|
const root = storyboard.fixture_resolution;
|
|
148
|
-
if (root === void 0)
|
|
240
|
+
if (root === void 0) {
|
|
241
|
+
assertNoReservedOrdinaryKeys(storyboard);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
149
244
|
assertPlainObject(root, `[${storyboard.id}] fixture_resolution`);
|
|
150
245
|
const unknownRoot = Object.keys(root).filter((key) => key !== "products" && key !== "pricing_options");
|
|
151
246
|
if (unknownRoot.length > 0) {
|
|
@@ -195,7 +290,7 @@ function validateFixtureResolutionDeclarations(storyboard) {
|
|
|
195
290
|
for (let index = 0; index < root.pricing_options.length; index++) {
|
|
196
291
|
const declaration = root.pricing_options[index];
|
|
197
292
|
const location = `[${storyboard.id}] fixture_resolution.pricing_options[${index}]`;
|
|
198
|
-
validateDeclaration(declaration, location, PRICING_DECLARATION_KEYS);
|
|
293
|
+
validateDeclaration(declaration, location, PRICING_DECLARATION_KEYS, "pricing_option");
|
|
199
294
|
const typedDeclaration = declaration;
|
|
200
295
|
if (typeof typedDeclaration.product_handle !== "string" || typedDeclaration.product_handle.length === 0) {
|
|
201
296
|
throw new Error(`${location}.product_handle: must be a non-empty string`);
|
|
@@ -212,6 +307,68 @@ function validateFixtureResolutionDeclarations(storyboard) {
|
|
|
212
307
|
}
|
|
213
308
|
}
|
|
214
309
|
}
|
|
310
|
+
assertNoReservedOrdinaryKeys(storyboard);
|
|
311
|
+
assertUniqueFixtureCaptureKeys(storyboard);
|
|
312
|
+
}
|
|
313
|
+
function assertNoReservedOrdinaryKeys(storyboard) {
|
|
314
|
+
const reject = (key, location) => {
|
|
315
|
+
if ((0, import_protected_context.isProtectedContextKey)(key)) {
|
|
316
|
+
throw new Error(
|
|
317
|
+
`${location}: "${key}" uses the reserved "__adcp_fixture_" prefix, which is owned by fixture preparation. Rename it to any key not starting with "__adcp_fixture_".`
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
321
|
+
throw new Error(
|
|
322
|
+
`${location}: "${key}" is a prototype-sensitive context key and cannot be used; rename it to anything other than __proto__, constructor or prototype`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
for (const key of Object.keys(storyboard.context ?? {})) {
|
|
327
|
+
reject(key, `[${storyboard.id}] context`);
|
|
328
|
+
}
|
|
329
|
+
for (const phase of storyboard.phases ?? []) {
|
|
330
|
+
for (const step of phase.steps ?? []) {
|
|
331
|
+
for (const output of step.context_outputs ?? []) {
|
|
332
|
+
if (typeof output.key !== "string") continue;
|
|
333
|
+
if ((0, import_protected_context.isProtectedContextKey)(output.key)) {
|
|
334
|
+
throw new Error(
|
|
335
|
+
`[${storyboard.id}] phase '${phase.id}' step '${step.id}': context_outputs entry "${output.key}" uses the reserved "__adcp_fixture_" prefix; step captures cannot write fixture-preparation state. Declare it under fixture_resolution instead, or rename the key.`
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
reject(output.key, `[${storyboard.id}] phase '${phase.id}' step '${step.id}' context_outputs`);
|
|
339
|
+
}
|
|
340
|
+
const gates = step.not_applicable_if;
|
|
341
|
+
for (const gate of gates === void 0 ? [] : Array.isArray(gates) ? gates : [gates]) {
|
|
342
|
+
for (const key of gate.context_keys ?? []) {
|
|
343
|
+
if (typeof key === "string") {
|
|
344
|
+
reject(key, `[${storyboard.id}] phase '${phase.id}' step '${step.id}' not_applicable_if.context_keys`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function assertUniqueFixtureCaptureKeys(storyboard) {
|
|
352
|
+
const owners = /* @__PURE__ */ new Map();
|
|
353
|
+
const claim = (key, owner) => {
|
|
354
|
+
const existing = owners.get(key);
|
|
355
|
+
if (existing !== void 0) {
|
|
356
|
+
throw new Error(
|
|
357
|
+
`[${storyboard.id}] fixture_resolution: capture key "${key}" is declared by both ${existing} and ${owner}`
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
owners.set(key, owner);
|
|
361
|
+
};
|
|
362
|
+
for (const declaration of storyboard.fixture_resolution?.products ?? []) {
|
|
363
|
+
for (const output of declaration.context_outputs ?? []) {
|
|
364
|
+
claim(output.key, `products."${declaration.handle}"`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
for (const declaration of storyboard.fixture_resolution?.pricing_options ?? []) {
|
|
368
|
+
for (const output of declaration.context_outputs ?? []) {
|
|
369
|
+
claim(output.key, `pricing_options."${declaration.product_handle}/${declaration.handle}"`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
215
372
|
}
|
|
216
373
|
function resolveCandidatePath(candidate, pointer) {
|
|
217
374
|
let current = candidate;
|
|
@@ -235,9 +392,38 @@ function matchesFixtureRequirements(candidate, clauses) {
|
|
|
235
392
|
return Array.isArray(actual) && actual.some((value) => matchesFixtureRequirements(value, clause.where ?? []));
|
|
236
393
|
case "canonical_format_satisfies":
|
|
237
394
|
return (0, import_canonical_format_satisfaction.productCanonicalFormatSatisfies)(actual, clause.value);
|
|
395
|
+
case "collection_selection_satisfies":
|
|
396
|
+
return (0, import_collection_selection.evaluateCollectionSelection)(actual, clause.value).eligible;
|
|
238
397
|
}
|
|
239
398
|
});
|
|
240
399
|
}
|
|
400
|
+
function matchFixtureRequirementsWithWitness(candidate, clauses) {
|
|
401
|
+
let witness;
|
|
402
|
+
let matched = true;
|
|
403
|
+
let reason;
|
|
404
|
+
for (const clause of clauses) {
|
|
405
|
+
if (clause.operator !== "collection_selection_satisfies") {
|
|
406
|
+
if (matched && !matchesFixtureRequirements(candidate, [clause])) {
|
|
407
|
+
matched = false;
|
|
408
|
+
reason = `${clause.operator} at "${clause.path || "(whole candidate)"}" did not match`;
|
|
409
|
+
}
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const actual = resolveCandidatePath(candidate, clause.path);
|
|
413
|
+
const evaluation = (0, import_collection_selection.evaluateCollectionSelection)(actual, clause.value);
|
|
414
|
+
if (!evaluation.eligible) {
|
|
415
|
+
if (matched) reason = evaluation.reason;
|
|
416
|
+
matched = false;
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
witness = evaluation.witness;
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
matched,
|
|
423
|
+
...witness && { witness },
|
|
424
|
+
...reason !== void 0 && { reason }
|
|
425
|
+
};
|
|
426
|
+
}
|
|
241
427
|
function buildFixtureResolutionSpecs(storyboard) {
|
|
242
428
|
const specs = [];
|
|
243
429
|
const productFixtures = new Map(
|
|
@@ -260,13 +446,22 @@ function buildFixtureResolutionSpecs(storyboard) {
|
|
|
260
446
|
if (!fixture) continue;
|
|
261
447
|
if (typeof fixture.product_id !== "string" || fixture.product_id.length === 0) continue;
|
|
262
448
|
const { product_id: handle, ...requirementFixture } = fixture;
|
|
449
|
+
const productClauses = normalizeFixtureMatchExpression(
|
|
450
|
+
declaration?.match,
|
|
451
|
+
`fixture_resolution.products.${handle}.match`
|
|
452
|
+
);
|
|
263
453
|
specs.push({
|
|
264
454
|
entityType: "product",
|
|
265
455
|
handle,
|
|
266
456
|
fixture: requirementFixture,
|
|
267
457
|
strategies: [...declaration?.strategies ?? ["seed"]],
|
|
268
|
-
clauses:
|
|
269
|
-
allowReuse: declaration?.allow_reuse === true
|
|
458
|
+
clauses: productClauses,
|
|
459
|
+
allowReuse: declaration?.allow_reuse === true,
|
|
460
|
+
contextOutputs: normalizeFixtureContextOutputs(
|
|
461
|
+
declaration?.context_outputs,
|
|
462
|
+
`fixture_resolution.products.${handle}.context_outputs`,
|
|
463
|
+
productClauses
|
|
464
|
+
)
|
|
270
465
|
});
|
|
271
466
|
}
|
|
272
467
|
const declaredPricing = storyboard.fixture_resolution?.pricing_options ?? [];
|
|
@@ -288,17 +483,24 @@ function buildFixtureResolutionSpecs(storyboard) {
|
|
|
288
483
|
const handle = fixture.pricing_option_id;
|
|
289
484
|
if (typeof parent !== "string" || !parent || typeof handle !== "string" || !handle) continue;
|
|
290
485
|
const { product_id: _parent, pricing_option_id: _handle, ...requirementFixture } = fixture;
|
|
486
|
+
const pricingClauses = normalizeFixtureMatchExpression(
|
|
487
|
+
declaration?.match,
|
|
488
|
+
`fixture_resolution.pricing_options.${parent}/${handle}.match`
|
|
489
|
+
);
|
|
291
490
|
specs.push({
|
|
292
491
|
entityType: "product_pricing_option",
|
|
293
492
|
handle,
|
|
294
493
|
parentProductHandle: parent,
|
|
295
494
|
fixture: requirementFixture,
|
|
296
495
|
strategies: [...declaration?.strategies ?? ["seed"]],
|
|
297
|
-
clauses:
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
496
|
+
clauses: pricingClauses,
|
|
497
|
+
allowReuse: declaration?.allow_reuse === true,
|
|
498
|
+
contextOutputs: normalizeFixtureContextOutputs(
|
|
499
|
+
declaration?.context_outputs,
|
|
500
|
+
`fixture_resolution.pricing_options.${parent}/${handle}.context_outputs`,
|
|
501
|
+
pricingClauses,
|
|
502
|
+
"pricing_option"
|
|
503
|
+
)
|
|
302
504
|
});
|
|
303
505
|
}
|
|
304
506
|
return specs;
|
|
@@ -417,7 +619,9 @@ function applyFixtureBindingsToRequest(request, toolName, bindings, version = im
|
|
|
417
619
|
FixtureBindingRegistry,
|
|
418
620
|
applyFixtureBindingsToRequest,
|
|
419
621
|
buildFixtureResolutionSpecs,
|
|
622
|
+
matchFixtureRequirementsWithWitness,
|
|
420
623
|
matchesFixtureRequirements,
|
|
624
|
+
normalizeFixtureContextOutputs,
|
|
421
625
|
normalizeFixtureMatchExpression,
|
|
422
626
|
validateFixtureResolutionDeclarations
|
|
423
627
|
});
|
|
@@ -2,8 +2,22 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
2
2
|
import { ADCP_VERSION } from "../../version.mjs";
|
|
3
3
|
import { getRequestSchemaEntityPaths } from "../../validation/schema-loader.mjs";
|
|
4
4
|
import { productCanonicalFormatSatisfies } from "./canonical-format-satisfaction.mjs";
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
COLLECTION_WITNESS_KINDS,
|
|
7
|
+
evaluateCollectionSelection,
|
|
8
|
+
normalizeCollectionSelectionSelector
|
|
9
|
+
} from "./collection-selection.mjs";
|
|
10
|
+
import { parsePath } from "./path.mjs";
|
|
11
|
+
import { assertWellFormedProtectedKey, isProtectedContextKey } from "./protected-context.mjs";
|
|
12
|
+
const OPERATORS = [
|
|
13
|
+
"equals",
|
|
14
|
+
"present",
|
|
15
|
+
"contains_all",
|
|
16
|
+
"any_match",
|
|
17
|
+
"canonical_format_satisfies",
|
|
18
|
+
"collection_selection_satisfies"
|
|
19
|
+
];
|
|
20
|
+
const DECLARATION_KEYS = /* @__PURE__ */ new Set(["handle", "strategies", "match", "allow_reuse", "context_outputs"]);
|
|
7
21
|
const PRICING_DECLARATION_KEYS = /* @__PURE__ */ new Set([...DECLARATION_KEYS, "product_handle"]);
|
|
8
22
|
function isRecord(value) {
|
|
9
23
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -75,6 +89,12 @@ function normalizeClause(value, location) {
|
|
|
75
89
|
operator,
|
|
76
90
|
where: normalizeFixtureMatchExpression(value.where, `${location}.where`)
|
|
77
91
|
};
|
|
92
|
+
case "collection_selection_satisfies":
|
|
93
|
+
return {
|
|
94
|
+
path: value.path,
|
|
95
|
+
operator,
|
|
96
|
+
value: normalizeCollectionSelectionSelector(value.value, `${location}.value`)
|
|
97
|
+
};
|
|
78
98
|
case "canonical_format_satisfies":
|
|
79
99
|
assertPlainObject(value.value, `${location}.value`);
|
|
80
100
|
if (typeof value.value.format_kind !== "string" || value.value.format_kind.length === 0) {
|
|
@@ -86,7 +106,7 @@ function normalizeClause(value, location) {
|
|
|
86
106
|
return { path: value.path, operator, value: value.value };
|
|
87
107
|
}
|
|
88
108
|
}
|
|
89
|
-
function validateDeclaration(declaration, location, allowedKeys) {
|
|
109
|
+
function validateDeclaration(declaration, location, allowedKeys, entityKind = "product") {
|
|
90
110
|
assertPlainObject(declaration, location);
|
|
91
111
|
const unknown = Object.keys(declaration).filter((key) => !allowedKeys.has(key));
|
|
92
112
|
if (unknown.length > 0) throw new Error(`${location}: unknown key(s): ${unknown.join(", ")}`);
|
|
@@ -114,10 +134,87 @@ function validateDeclaration(declaration, location, allowedKeys) {
|
|
|
114
134
|
if (Array.isArray(declaration.strategies) && declaration.strategies.includes("discover") && clauses.length === 0) {
|
|
115
135
|
throw new Error(`${location}.match: discover strategy requires at least one authored predicate`);
|
|
116
136
|
}
|
|
137
|
+
normalizeFixtureContextOutputs(declaration.context_outputs, `${location}.context_outputs`, clauses, entityKind);
|
|
138
|
+
}
|
|
139
|
+
const FIXTURE_CONTEXT_OUTPUT_KEYS = /* @__PURE__ */ new Set(["key", "path", "witness", "snapshot"]);
|
|
140
|
+
function normalizeFixtureContextOutputs(value, location, clauses, entityKind = "product") {
|
|
141
|
+
if (value === void 0) return [];
|
|
142
|
+
assertArray(value, location);
|
|
143
|
+
if (value.length === 0) throw new Error(`${location}: must contain at least one capture when present`);
|
|
144
|
+
const hasCollectionPredicate = clauses.some((clause) => clause.operator === "collection_selection_satisfies");
|
|
145
|
+
const seen = /* @__PURE__ */ new Set();
|
|
146
|
+
return value.map((raw, index) => {
|
|
147
|
+
const entryLocation = `${location}[${index}]`;
|
|
148
|
+
assertPlainObject(raw, entryLocation);
|
|
149
|
+
const unknown = Object.keys(raw).filter((key) => !FIXTURE_CONTEXT_OUTPUT_KEYS.has(key));
|
|
150
|
+
if (unknown.length > 0) {
|
|
151
|
+
throw new Error(`${entryLocation}: unknown key(s): ${unknown.join(", ")}`);
|
|
152
|
+
}
|
|
153
|
+
if (typeof raw.key !== "string" || raw.key.length === 0) {
|
|
154
|
+
throw new Error(`${entryLocation}.key: must be a non-empty string`);
|
|
155
|
+
}
|
|
156
|
+
if (!isProtectedContextKey(raw.key)) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
`${entryLocation}.key: fixture captures must use the reserved "__adcp_fixture_" prefix so later steps, caller context and seller responses cannot replace them; received "${raw.key}"`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
assertWellFormedProtectedKey(raw.key, entryLocation + ".key");
|
|
162
|
+
if (seen.has(raw.key)) throw new Error(`${entryLocation}.key: duplicate capture key "${raw.key}"`);
|
|
163
|
+
seen.add(raw.key);
|
|
164
|
+
const forms = ["path", "witness", "snapshot"].filter((form) => Object.hasOwn(raw, form));
|
|
165
|
+
if (forms.length !== 1) {
|
|
166
|
+
throw new Error(
|
|
167
|
+
`${entryLocation}: must set exactly one of 'path', 'witness' or 'snapshot'; received ${forms.length === 0 ? "none" : forms.join(" + ")}`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
const hasPath = forms[0] === "path";
|
|
171
|
+
if (forms[0] === "snapshot") {
|
|
172
|
+
if (raw.snapshot !== "selected_entity") {
|
|
173
|
+
throw new Error(`${entryLocation}.snapshot: must be 'selected_entity'`);
|
|
174
|
+
}
|
|
175
|
+
return { key: raw.key, snapshot: "selected_entity" };
|
|
176
|
+
}
|
|
177
|
+
if (hasPath) {
|
|
178
|
+
if (typeof raw.path !== "string" || raw.path.length === 0) {
|
|
179
|
+
throw new Error(`${entryLocation}.path: must be a non-empty string`);
|
|
180
|
+
}
|
|
181
|
+
if (raw.path.startsWith("/")) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`${entryLocation}.path: capture paths use the dotted storyboard grammar ("currency", "pricing_options[0].rate"), not the RFC 6901 pointers that match[].path takes; drop the leading "/" \u2014 received "${raw.path}"`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
if (parsePath(raw.path).length === 0) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
`${entryLocation}.path: must name at least one field in the dotted storyboard grammar ("currency", "pricing_options[0].rate") \u2014 received "${raw.path}", which resolves to the whole selected entity. To capture the whole entity, say so: snapshot: 'selected_entity'.`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
if (raw.path.split(".").some((segment) => segment.length === 0)) {
|
|
192
|
+
throw new Error(`${entryLocation}.path: every dotted segment must name a field \u2014 received "${raw.path}".`);
|
|
193
|
+
}
|
|
194
|
+
return { key: raw.key, path: raw.path };
|
|
195
|
+
}
|
|
196
|
+
if (typeof raw.witness !== "string" || !COLLECTION_WITNESS_KINDS.includes(raw.witness)) {
|
|
197
|
+
throw new Error(`${entryLocation}.witness: must be one of ${COLLECTION_WITNESS_KINDS.join(", ")}`);
|
|
198
|
+
}
|
|
199
|
+
if (entityKind === "pricing_option") {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`${entryLocation}.witness: a collection witness describes the product, not one of its pricing options; declare it under fixture_resolution.products.<product_handle>.context_outputs instead`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
if (!hasCollectionPredicate) {
|
|
205
|
+
throw new Error(
|
|
206
|
+
`${entryLocation}.witness: requires a collection_selection_satisfies predicate on the same declaration`
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
return { key: raw.key, witness: raw.witness };
|
|
210
|
+
});
|
|
117
211
|
}
|
|
118
212
|
function validateFixtureResolutionDeclarations(storyboard) {
|
|
119
213
|
const root = storyboard.fixture_resolution;
|
|
120
|
-
if (root === void 0)
|
|
214
|
+
if (root === void 0) {
|
|
215
|
+
assertNoReservedOrdinaryKeys(storyboard);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
121
218
|
assertPlainObject(root, `[${storyboard.id}] fixture_resolution`);
|
|
122
219
|
const unknownRoot = Object.keys(root).filter((key) => key !== "products" && key !== "pricing_options");
|
|
123
220
|
if (unknownRoot.length > 0) {
|
|
@@ -167,7 +264,7 @@ function validateFixtureResolutionDeclarations(storyboard) {
|
|
|
167
264
|
for (let index = 0; index < root.pricing_options.length; index++) {
|
|
168
265
|
const declaration = root.pricing_options[index];
|
|
169
266
|
const location = `[${storyboard.id}] fixture_resolution.pricing_options[${index}]`;
|
|
170
|
-
validateDeclaration(declaration, location, PRICING_DECLARATION_KEYS);
|
|
267
|
+
validateDeclaration(declaration, location, PRICING_DECLARATION_KEYS, "pricing_option");
|
|
171
268
|
const typedDeclaration = declaration;
|
|
172
269
|
if (typeof typedDeclaration.product_handle !== "string" || typedDeclaration.product_handle.length === 0) {
|
|
173
270
|
throw new Error(`${location}.product_handle: must be a non-empty string`);
|
|
@@ -184,6 +281,68 @@ function validateFixtureResolutionDeclarations(storyboard) {
|
|
|
184
281
|
}
|
|
185
282
|
}
|
|
186
283
|
}
|
|
284
|
+
assertNoReservedOrdinaryKeys(storyboard);
|
|
285
|
+
assertUniqueFixtureCaptureKeys(storyboard);
|
|
286
|
+
}
|
|
287
|
+
function assertNoReservedOrdinaryKeys(storyboard) {
|
|
288
|
+
const reject = (key, location) => {
|
|
289
|
+
if (isProtectedContextKey(key)) {
|
|
290
|
+
throw new Error(
|
|
291
|
+
`${location}: "${key}" uses the reserved "__adcp_fixture_" prefix, which is owned by fixture preparation. Rename it to any key not starting with "__adcp_fixture_".`
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
295
|
+
throw new Error(
|
|
296
|
+
`${location}: "${key}" is a prototype-sensitive context key and cannot be used; rename it to anything other than __proto__, constructor or prototype`
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
for (const key of Object.keys(storyboard.context ?? {})) {
|
|
301
|
+
reject(key, `[${storyboard.id}] context`);
|
|
302
|
+
}
|
|
303
|
+
for (const phase of storyboard.phases ?? []) {
|
|
304
|
+
for (const step of phase.steps ?? []) {
|
|
305
|
+
for (const output of step.context_outputs ?? []) {
|
|
306
|
+
if (typeof output.key !== "string") continue;
|
|
307
|
+
if (isProtectedContextKey(output.key)) {
|
|
308
|
+
throw new Error(
|
|
309
|
+
`[${storyboard.id}] phase '${phase.id}' step '${step.id}': context_outputs entry "${output.key}" uses the reserved "__adcp_fixture_" prefix; step captures cannot write fixture-preparation state. Declare it under fixture_resolution instead, or rename the key.`
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
reject(output.key, `[${storyboard.id}] phase '${phase.id}' step '${step.id}' context_outputs`);
|
|
313
|
+
}
|
|
314
|
+
const gates = step.not_applicable_if;
|
|
315
|
+
for (const gate of gates === void 0 ? [] : Array.isArray(gates) ? gates : [gates]) {
|
|
316
|
+
for (const key of gate.context_keys ?? []) {
|
|
317
|
+
if (typeof key === "string") {
|
|
318
|
+
reject(key, `[${storyboard.id}] phase '${phase.id}' step '${step.id}' not_applicable_if.context_keys`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function assertUniqueFixtureCaptureKeys(storyboard) {
|
|
326
|
+
const owners = /* @__PURE__ */ new Map();
|
|
327
|
+
const claim = (key, owner) => {
|
|
328
|
+
const existing = owners.get(key);
|
|
329
|
+
if (existing !== void 0) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
`[${storyboard.id}] fixture_resolution: capture key "${key}" is declared by both ${existing} and ${owner}`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
owners.set(key, owner);
|
|
335
|
+
};
|
|
336
|
+
for (const declaration of storyboard.fixture_resolution?.products ?? []) {
|
|
337
|
+
for (const output of declaration.context_outputs ?? []) {
|
|
338
|
+
claim(output.key, `products."${declaration.handle}"`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
for (const declaration of storyboard.fixture_resolution?.pricing_options ?? []) {
|
|
342
|
+
for (const output of declaration.context_outputs ?? []) {
|
|
343
|
+
claim(output.key, `pricing_options."${declaration.product_handle}/${declaration.handle}"`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
187
346
|
}
|
|
188
347
|
function resolveCandidatePath(candidate, pointer) {
|
|
189
348
|
let current = candidate;
|
|
@@ -207,9 +366,38 @@ function matchesFixtureRequirements(candidate, clauses) {
|
|
|
207
366
|
return Array.isArray(actual) && actual.some((value) => matchesFixtureRequirements(value, clause.where ?? []));
|
|
208
367
|
case "canonical_format_satisfies":
|
|
209
368
|
return productCanonicalFormatSatisfies(actual, clause.value);
|
|
369
|
+
case "collection_selection_satisfies":
|
|
370
|
+
return evaluateCollectionSelection(actual, clause.value).eligible;
|
|
210
371
|
}
|
|
211
372
|
});
|
|
212
373
|
}
|
|
374
|
+
function matchFixtureRequirementsWithWitness(candidate, clauses) {
|
|
375
|
+
let witness;
|
|
376
|
+
let matched = true;
|
|
377
|
+
let reason;
|
|
378
|
+
for (const clause of clauses) {
|
|
379
|
+
if (clause.operator !== "collection_selection_satisfies") {
|
|
380
|
+
if (matched && !matchesFixtureRequirements(candidate, [clause])) {
|
|
381
|
+
matched = false;
|
|
382
|
+
reason = `${clause.operator} at "${clause.path || "(whole candidate)"}" did not match`;
|
|
383
|
+
}
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
const actual = resolveCandidatePath(candidate, clause.path);
|
|
387
|
+
const evaluation = evaluateCollectionSelection(actual, clause.value);
|
|
388
|
+
if (!evaluation.eligible) {
|
|
389
|
+
if (matched) reason = evaluation.reason;
|
|
390
|
+
matched = false;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
witness = evaluation.witness;
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
matched,
|
|
397
|
+
...witness && { witness },
|
|
398
|
+
...reason !== void 0 && { reason }
|
|
399
|
+
};
|
|
400
|
+
}
|
|
213
401
|
function buildFixtureResolutionSpecs(storyboard) {
|
|
214
402
|
const specs = [];
|
|
215
403
|
const productFixtures = new Map(
|
|
@@ -232,13 +420,22 @@ function buildFixtureResolutionSpecs(storyboard) {
|
|
|
232
420
|
if (!fixture) continue;
|
|
233
421
|
if (typeof fixture.product_id !== "string" || fixture.product_id.length === 0) continue;
|
|
234
422
|
const { product_id: handle, ...requirementFixture } = fixture;
|
|
423
|
+
const productClauses = normalizeFixtureMatchExpression(
|
|
424
|
+
declaration?.match,
|
|
425
|
+
`fixture_resolution.products.${handle}.match`
|
|
426
|
+
);
|
|
235
427
|
specs.push({
|
|
236
428
|
entityType: "product",
|
|
237
429
|
handle,
|
|
238
430
|
fixture: requirementFixture,
|
|
239
431
|
strategies: [...declaration?.strategies ?? ["seed"]],
|
|
240
|
-
clauses:
|
|
241
|
-
allowReuse: declaration?.allow_reuse === true
|
|
432
|
+
clauses: productClauses,
|
|
433
|
+
allowReuse: declaration?.allow_reuse === true,
|
|
434
|
+
contextOutputs: normalizeFixtureContextOutputs(
|
|
435
|
+
declaration?.context_outputs,
|
|
436
|
+
`fixture_resolution.products.${handle}.context_outputs`,
|
|
437
|
+
productClauses
|
|
438
|
+
)
|
|
242
439
|
});
|
|
243
440
|
}
|
|
244
441
|
const declaredPricing = storyboard.fixture_resolution?.pricing_options ?? [];
|
|
@@ -260,17 +457,24 @@ function buildFixtureResolutionSpecs(storyboard) {
|
|
|
260
457
|
const handle = fixture.pricing_option_id;
|
|
261
458
|
if (typeof parent !== "string" || !parent || typeof handle !== "string" || !handle) continue;
|
|
262
459
|
const { product_id: _parent, pricing_option_id: _handle, ...requirementFixture } = fixture;
|
|
460
|
+
const pricingClauses = normalizeFixtureMatchExpression(
|
|
461
|
+
declaration?.match,
|
|
462
|
+
`fixture_resolution.pricing_options.${parent}/${handle}.match`
|
|
463
|
+
);
|
|
263
464
|
specs.push({
|
|
264
465
|
entityType: "product_pricing_option",
|
|
265
466
|
handle,
|
|
266
467
|
parentProductHandle: parent,
|
|
267
468
|
fixture: requirementFixture,
|
|
268
469
|
strategies: [...declaration?.strategies ?? ["seed"]],
|
|
269
|
-
clauses:
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
470
|
+
clauses: pricingClauses,
|
|
471
|
+
allowReuse: declaration?.allow_reuse === true,
|
|
472
|
+
contextOutputs: normalizeFixtureContextOutputs(
|
|
473
|
+
declaration?.context_outputs,
|
|
474
|
+
`fixture_resolution.pricing_options.${parent}/${handle}.context_outputs`,
|
|
475
|
+
pricingClauses,
|
|
476
|
+
"pricing_option"
|
|
477
|
+
)
|
|
274
478
|
});
|
|
275
479
|
}
|
|
276
480
|
return specs;
|
|
@@ -388,7 +592,9 @@ export {
|
|
|
388
592
|
FixtureBindingRegistry,
|
|
389
593
|
applyFixtureBindingsToRequest,
|
|
390
594
|
buildFixtureResolutionSpecs,
|
|
595
|
+
matchFixtureRequirementsWithWitness,
|
|
391
596
|
matchesFixtureRequirements,
|
|
597
|
+
normalizeFixtureContextOutputs,
|
|
392
598
|
normalizeFixtureMatchExpression,
|
|
393
599
|
validateFixtureResolutionDeclarations
|
|
394
600
|
};
|
|
@@ -16,9 +16,16 @@ export type { CapturedWebhook, CapturedWebhookChallenge, CreateWebhookReceiverOp
|
|
|
16
16
|
export { createRunnerVariables } from './context.mjs';
|
|
17
17
|
export type { RunnerVariables } from './context.mjs';
|
|
18
18
|
export { WEBHOOK_ASSERTION_TASKS } from './webhook-assertions.mjs';
|
|
19
|
-
export { runStoryboard, runStoryboardStep, applyAdcpVersionRunOptions, applyStoryboardVersionOptions, getFirstStepPreview, summarizeStrictValidation, listStrictOnlyFailures, resolveCapabilityPath, evaluateCapabilityPredicate, describeStoryboardCapabilityGates, buildDiscoveryFailedResult, } from './runner.mjs';
|
|
19
|
+
export { prepareStoryboardFixtures, runStoryboard, runStoryboardStep, applyAdcpVersionRunOptions, applyStoryboardVersionOptions, getFirstStepPreview, summarizeStrictValidation, listStrictOnlyFailures, resolveCapabilityPath, evaluateCapabilityPredicate, describeStoryboardCapabilityGates, buildDiscoveryFailedResult, } from './runner.mjs';
|
|
20
20
|
export { parseStoryboard, loadStoryboardFile, normalizeValidationOnlyTasks, VALIDATION_ONLY_TASK } from './loader.mjs';
|
|
21
|
-
export { applyFixtureBindingsToRequest, buildFixtureResolutionSpecs, FixtureBindingRegistry, matchesFixtureRequirements, normalizeFixtureMatchExpression, validateFixtureResolutionDeclarations, } from './fixture-resolution.mjs';
|
|
21
|
+
export { applyFixtureBindingsToRequest, buildFixtureResolutionSpecs, FixtureBindingRegistry, matchesFixtureRequirements, matchFixtureRequirementsWithWitness, normalizeFixtureContextOutputs, normalizeFixtureMatchExpression, validateFixtureResolutionDeclarations, } from './fixture-resolution.mjs';
|
|
22
|
+
export type { FixtureContextOutput } from './types.mjs';
|
|
23
|
+
export { COLLECTION_DIAGNOSTIC_LIMIT, COLLECTION_PAIR_LIMIT, COLLECTION_TARGETING_MODES, COLLECTION_WITNESS_KINDS, compareCollectionPairs, diffCollectionPairSets, evaluateCollectionSelection, formatCollectionPair, normalizeCollectionSelectionSelector, normalizeCollectionSelectors, productSatisfiesCollectionSelection, readCollectionWitness, summarizeCollectionPairs, } from './collection-selection.mjs';
|
|
24
|
+
export type { ResolvedCollectionSelectionSelector, CollectionNormalizationCode, CollectionNormalizationFailure, CollectionNormalizationResult, CrossPublisherCollectionRelation, CollectionPair, CollectionSelectionEvaluation, CollectionSelectionSelector, CollectionSelectionWitness, CollectionSelectorObject, CollectionWitnessKind, CollectionWitnessReadResult, NormalizedCollectionSelectors, } from './collection-selection.mjs';
|
|
25
|
+
export { isProtectedContextKey, PROTECTED_CONTEXT_PREFIX, ProtectedContextViolation } from './protected-context.mjs';
|
|
26
|
+
export type { ProtectedContextViolationCode } from './protected-context.mjs';
|
|
27
|
+
export { isTrustedPreparedFixtures, PREPARED_FIXTURES_CONTRACT_VERSION, PreparedStoryboardFixtures, withPreparedFixtures, } from './prepared-fixtures.mjs';
|
|
28
|
+
export type { PreparedFixtureBinding, PreparedFixtureSelection, PreparedFixturesAuthorizer, PreparedFixturesDecision, PreparedFixturesDisposition, PreparedFixturesLookup, PreparedFixturesRefusal, PreparedFixturesRefusalCode, PreparedFixturesReference, PreparedSchemaArtifact, } from './prepared-fixtures.mjs';
|
|
22
29
|
export { getComplianceCacheDir, getExternalSchemaRootForCompliance, loadComplianceIndex, listBundles, loadBundleStoryboards, listAllComplianceStoryboards, getComplianceStoryboardById, findBundleById, resolveBundleOrStoryboard, resolveStoryboardsForCapabilities, isComplianceVersionSupported, loadSpecialismDetail, listSpecialisms, CapabilityResolutionError, PROTOCOL_TO_PATH, UNBASELINED_SUPPORTED_PROTOCOLS, } from './compliance.mjs';
|
|
23
30
|
export type { AgentCapabilities, BundleKind, BundleRef, CapabilityResolutionCode, ComplianceIndex, ComplianceIndexProtocol, ComplianceIndexSpecialism, NotApplicableStoryboard, ResolveOptions, ResolvedBundle, ResolvedStoryboards, SpecialismDetail, } from './compliance.mjs';
|
|
24
31
|
export { TASK_TO_METHOD, executeStoryboardTask } from './task-map.mjs';
|