@adcp/sdk 16.5.0 → 16.6.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 (236) hide show
  1. package/dist/lib/adapters/version/3.0/brand-fields.d.mts +7 -1
  2. package/dist/lib/adapters/version/3.0/brand-fields.d.ts +7 -1
  3. package/dist/lib/adapters/version/3.0/brand-fields.js +139 -3
  4. package/dist/lib/adapters/version/3.0/brand-fields.mjs +136 -2
  5. package/dist/lib/adapters/version/3.0/index.js +6 -0
  6. package/dist/lib/adapters/version/3.0/index.mjs +7 -1
  7. package/dist/lib/adapters/version/3.1/bidding.js +1 -1
  8. package/dist/lib/adapters/version/3.1/bidding.mjs +1 -1
  9. package/dist/lib/adapters/version/types.d.mts +5 -0
  10. package/dist/lib/adapters/version/types.d.ts +5 -0
  11. package/dist/lib/canonical-references/index.js +2 -0
  12. package/dist/lib/canonical-references/index.mjs +2 -0
  13. package/dist/lib/client/account-changes.d.mts +3 -1
  14. package/dist/lib/client/account-changes.d.ts +3 -1
  15. package/dist/lib/client/account-changes.js +22 -2
  16. package/dist/lib/client/account-changes.mjs +22 -2
  17. package/dist/lib/conformance/oracle.js +3 -2
  18. package/dist/lib/conformance/oracle.mjs +3 -2
  19. package/dist/lib/core/AgentClient.d.mts +165 -1
  20. package/dist/lib/core/AgentClient.d.ts +165 -1
  21. package/dist/lib/core/AgentClient.js +446 -8
  22. package/dist/lib/core/AgentClient.mjs +446 -8
  23. package/dist/lib/core/ConversationTypes.d.mts +8 -0
  24. package/dist/lib/core/ConversationTypes.d.ts +8 -0
  25. package/dist/lib/core/ProtocolResponseParser.d.mts +1 -1
  26. package/dist/lib/core/ProtocolResponseParser.d.ts +1 -1
  27. package/dist/lib/core/ProtocolResponseParser.js +28 -18
  28. package/dist/lib/core/ProtocolResponseParser.mjs +11 -1
  29. package/dist/lib/core/ResponseValidator.js +1 -1
  30. package/dist/lib/core/ResponseValidator.mjs +1 -1
  31. package/dist/lib/core/SingleAgentClient.d.mts +116 -6
  32. package/dist/lib/core/SingleAgentClient.d.ts +116 -6
  33. package/dist/lib/core/SingleAgentClient.js +556 -84
  34. package/dist/lib/core/SingleAgentClient.mjs +545 -72
  35. package/dist/lib/core/TaskExecutor.d.mts +7 -0
  36. package/dist/lib/core/TaskExecutor.d.ts +7 -0
  37. package/dist/lib/core/TaskExecutor.js +23 -8
  38. package/dist/lib/core/TaskExecutor.mjs +23 -8
  39. package/dist/lib/core/task-status.d.mts +2 -0
  40. package/dist/lib/core/task-status.d.ts +2 -0
  41. package/dist/lib/core/task-status.js +11 -2
  42. package/dist/lib/core/task-status.mjs +9 -1
  43. package/dist/lib/errors/index.d.mts +22 -0
  44. package/dist/lib/errors/index.d.ts +22 -0
  45. package/dist/lib/errors/index.js +43 -0
  46. package/dist/lib/errors/index.mjs +42 -0
  47. package/dist/lib/identity-3.3/trust.d.mts +1 -4
  48. package/dist/lib/identity-3.3/trust.d.ts +1 -4
  49. package/dist/lib/identity-3.3/trust.js +34 -21
  50. package/dist/lib/identity-3.3/trust.mjs +34 -21
  51. package/dist/lib/identity-3.3/validation.js +5 -3
  52. package/dist/lib/identity-3.3/validation.mjs +6 -4
  53. package/dist/lib/index.d.mts +8 -54
  54. package/dist/lib/index.d.ts +8 -54
  55. package/dist/lib/index.js +15 -0
  56. package/dist/lib/index.mjs +11 -0
  57. package/dist/lib/media-buy/action-assessment.js +29 -3
  58. package/dist/lib/media-buy/action-assessment.mjs +32 -4
  59. package/dist/lib/media-buy/action-contracts.d.mts +3 -0
  60. package/dist/lib/media-buy/action-contracts.d.ts +3 -0
  61. package/dist/lib/media-buy/action-contracts.js +24 -1
  62. package/dist/lib/media-buy/action-contracts.mjs +22 -1
  63. package/dist/lib/media-buy/compatibility.js +6 -1
  64. package/dist/lib/media-buy/compatibility.mjs +6 -1
  65. package/dist/lib/media-buy/preflight.js +1 -1
  66. package/dist/lib/media-buy/preflight.mjs +3 -2
  67. package/dist/lib/media-buy/types.d.mts +6 -1
  68. package/dist/lib/media-buy/types.d.ts +6 -1
  69. package/dist/lib/protocols/mcp-modern.d.mts +2 -0
  70. package/dist/lib/protocols/mcp-modern.d.ts +2 -0
  71. package/dist/lib/protocols/mcp-modern.js +31 -5
  72. package/dist/lib/protocols/mcp-modern.mjs +31 -5
  73. package/dist/lib/protocols/mcp-scope.d.mts +6 -1
  74. package/dist/lib/protocols/mcp-scope.d.ts +6 -1
  75. package/dist/lib/protocols/mcp-scope.js +25 -3
  76. package/dist/lib/protocols/mcp-scope.mjs +24 -3
  77. package/dist/lib/protocols/mcp.js +12 -6
  78. package/dist/lib/protocols/mcp.mjs +13 -6
  79. package/dist/lib/reporting/inspection.js +1 -0
  80. package/dist/lib/reporting/inspection.mjs +1 -0
  81. package/dist/lib/schemas/browser.d.mts +2 -0
  82. package/dist/lib/schemas/browser.d.ts +2 -0
  83. package/dist/lib/schemas/browser.js +3 -0
  84. package/dist/lib/schemas/browser.mjs +2 -0
  85. package/dist/lib/schemas/index.d.mts +5 -2
  86. package/dist/lib/schemas/index.d.ts +5 -2
  87. package/dist/lib/schemas/index.js +5 -0
  88. package/dist/lib/schemas/index.mjs +4 -0
  89. package/dist/lib/server/account-response-identity.d.mts +17 -0
  90. package/dist/lib/server/account-response-identity.d.ts +17 -0
  91. package/dist/lib/server/account-response-identity.js +52 -0
  92. package/dist/lib/server/account-response-identity.mjs +28 -0
  93. package/dist/lib/server/account-sync-contract.js +1 -0
  94. package/dist/lib/server/account-sync-contract.mjs +1 -0
  95. package/dist/lib/server/create-adcp-server.js +32 -19
  96. package/dist/lib/server/create-adcp-server.mjs +36 -12
  97. package/dist/lib/server/decisioning/account.d.mts +13 -6
  98. package/dist/lib/server/decisioning/account.d.ts +13 -6
  99. package/dist/lib/server/decisioning/account.js +37 -15
  100. package/dist/lib/server/decisioning/account.mjs +37 -15
  101. package/dist/lib/server/decisioning/runtime/from-platform.d.mts +5 -5
  102. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +5 -5
  103. package/dist/lib/server/decisioning/runtime/from-platform.js +6 -6
  104. package/dist/lib/server/decisioning/runtime/from-platform.mjs +6 -6
  105. package/dist/lib/server/index.d.mts +1 -1
  106. package/dist/lib/server/index.d.ts +1 -1
  107. package/dist/lib/server/index.js +2 -0
  108. package/dist/lib/server/index.mjs +2 -0
  109. package/dist/lib/server/media-buy-action-resolver.d.mts +3 -0
  110. package/dist/lib/server/media-buy-action-resolver.d.ts +3 -0
  111. package/dist/lib/server/media-buy-action-resolver.js +32 -0
  112. package/dist/lib/server/media-buy-action-resolver.mjs +32 -0
  113. package/dist/lib/server/media-buy-store.d.mts +26 -12
  114. package/dist/lib/server/media-buy-store.d.ts +26 -12
  115. package/dist/lib/server/media-buy-store.js +69 -21
  116. package/dist/lib/server/media-buy-store.mjs +69 -21
  117. package/dist/lib/server/responses.js +9 -1
  118. package/dist/lib/server/responses.mjs +9 -1
  119. package/dist/lib/server/state-machine.d.mts +10 -11
  120. package/dist/lib/server/state-machine.d.ts +10 -11
  121. package/dist/lib/server/state-machine.js +20 -5
  122. package/dist/lib/server/state-machine.mjs +19 -5
  123. package/dist/lib/signing/agent-fetch.d.mts +1 -1
  124. package/dist/lib/signing/agent-fetch.d.ts +1 -1
  125. package/dist/lib/signing/agent-fetch.js +3 -3
  126. package/dist/lib/signing/agent-fetch.mjs +3 -3
  127. package/dist/lib/testing/client.d.mts +1 -0
  128. package/dist/lib/testing/client.d.ts +1 -0
  129. package/dist/lib/testing/client.js +6 -5
  130. package/dist/lib/testing/client.mjs +6 -5
  131. package/dist/lib/testing/storyboard/canonical-format-satisfaction.js +60 -14
  132. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +60 -14
  133. package/dist/lib/testing/storyboard/compliance.d.mts +2 -5
  134. package/dist/lib/testing/storyboard/compliance.d.ts +2 -5
  135. package/dist/lib/testing/storyboard/compliance.js +62 -13
  136. package/dist/lib/testing/storyboard/compliance.mjs +63 -14
  137. package/dist/lib/testing/storyboard/context.d.mts +13 -3
  138. package/dist/lib/testing/storyboard/context.d.ts +13 -3
  139. package/dist/lib/testing/storyboard/context.js +15 -10
  140. package/dist/lib/testing/storyboard/context.mjs +15 -10
  141. package/dist/lib/testing/storyboard/default-invariants.js +10 -8
  142. package/dist/lib/testing/storyboard/default-invariants.mjs +11 -9
  143. package/dist/lib/testing/storyboard/request-signing/vector-loader.d.mts +2 -0
  144. package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts +2 -0
  145. package/dist/lib/testing/storyboard/request-signing/vector-loader.js +11 -0
  146. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +10 -0
  147. package/dist/lib/testing/storyboard/runner.js +23 -10
  148. package/dist/lib/testing/storyboard/runner.mjs +23 -10
  149. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  150. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  151. package/dist/lib/testing/storyboard/validations.js +4 -1
  152. package/dist/lib/testing/storyboard/validations.mjs +4 -1
  153. package/dist/lib/testing/test-controller.js +3 -0
  154. package/dist/lib/testing/test-controller.mjs +3 -0
  155. package/dist/lib/types/asset-instances.d.mts +1 -1
  156. package/dist/lib/types/asset-instances.d.ts +1 -1
  157. package/dist/lib/types/index.d.mts +5 -0
  158. package/dist/lib/types/index.d.ts +5 -0
  159. package/dist/lib/types/index.js +6 -1
  160. package/dist/lib/types/index.mjs +4 -1
  161. package/dist/lib/types/inline-enums.generated.d.mts +30 -4
  162. package/dist/lib/types/inline-enums.generated.d.ts +30 -4
  163. package/dist/lib/types/inline-enums.generated.js +41 -2
  164. package/dist/lib/types/inline-enums.generated.mjs +28 -2
  165. package/dist/lib/types/media-buy-delivery-report.d.mts +4 -0
  166. package/dist/lib/types/media-buy-delivery-report.d.ts +4 -0
  167. package/dist/lib/types/media-buy-delivery-report.js +16 -0
  168. package/dist/lib/types/media-buy-delivery-report.mjs +0 -0
  169. package/dist/lib/types/schemas.generated.d.ts +20 -69
  170. package/dist/lib/types/schemas.generated.js +29 -46
  171. package/dist/lib/types/schemas.generated.mjs +29 -46
  172. package/dist/lib/types/targeting-keys.generated.d.mts +4 -0
  173. package/dist/lib/types/targeting-keys.generated.d.ts +4 -0
  174. package/dist/lib/types/targeting-keys.generated.js +105 -0
  175. package/dist/lib/types/targeting-keys.generated.mjs +80 -0
  176. package/dist/lib/utils/adcp-version-config.js +5 -2
  177. package/dist/lib/utils/adcp-version-config.mjs +5 -2
  178. package/dist/lib/utils/envelope-status-compat.d.mts +18 -1
  179. package/dist/lib/utils/envelope-status-compat.d.ts +18 -1
  180. package/dist/lib/utils/envelope-status-compat.js +11 -5
  181. package/dist/lib/utils/envelope-status-compat.mjs +11 -5
  182. package/dist/lib/utils/response-unwrapper.js +18 -10
  183. package/dist/lib/utils/response-unwrapper.mjs +18 -10
  184. package/dist/lib/v2/format-schema/resolver.js +1 -1
  185. package/dist/lib/v2/format-schema/resolver.mjs +1 -1
  186. package/dist/lib/v2/projection/creative-delivery.js +123 -30
  187. package/dist/lib/v2/projection/creative-delivery.mjs +127 -30
  188. package/dist/lib/v2/projection/index.d.mts +1 -0
  189. package/dist/lib/v2/projection/index.d.ts +1 -0
  190. package/dist/lib/v2/projection/index.js +3 -0
  191. package/dist/lib/v2/projection/index.mjs +2 -0
  192. package/dist/lib/v2/projection/legacy-metadata.d.mts +19 -0
  193. package/dist/lib/v2/projection/legacy-metadata.d.ts +19 -0
  194. package/dist/lib/v2/projection/legacy-metadata.js +91 -0
  195. package/dist/lib/v2/projection/legacy-metadata.mjs +86 -0
  196. package/dist/lib/validation/compact-schema.d.mts +27 -0
  197. package/dist/lib/validation/compact-schema.d.ts +27 -0
  198. package/dist/lib/validation/compact-schema.js +276 -0
  199. package/dist/lib/validation/compact-schema.mjs +250 -0
  200. package/dist/lib/validation/media-buy-delivery-report.d.mts +8 -0
  201. package/dist/lib/validation/media-buy-delivery-report.d.ts +8 -0
  202. package/dist/lib/validation/media-buy-delivery-report.js +31 -0
  203. package/dist/lib/validation/media-buy-delivery-report.mjs +7 -0
  204. package/dist/lib/validation/schema-diagnostic-origins.d.mts +21 -0
  205. package/dist/lib/validation/schema-diagnostic-origins.d.ts +21 -0
  206. package/dist/lib/validation/schema-diagnostic-origins.js +193 -0
  207. package/dist/lib/validation/schema-diagnostic-origins.mjs +169 -0
  208. package/dist/lib/validation/schema-loader.js +86 -16
  209. package/dist/lib/validation/schema-loader.mjs +82 -16
  210. package/dist/lib/validation/schema-validator.d.mts +10 -19
  211. package/dist/lib/validation/schema-validator.d.ts +10 -19
  212. package/dist/lib/validation/schema-validator.js +136 -43
  213. package/dist/lib/validation/schema-validator.mjs +140 -44
  214. package/dist/lib/version.d.mts +3 -3
  215. package/dist/lib/version.d.ts +3 -3
  216. package/dist/lib/version.js +3 -3
  217. package/dist/lib/version.mjs +3 -3
  218. package/dist/lib/webhooks/index.d.mts +3 -0
  219. package/dist/lib/webhooks/index.d.ts +3 -0
  220. package/dist/lib/webhooks/index.js +3 -0
  221. package/dist/lib/webhooks/index.mjs +2 -0
  222. package/dist/lib/webhooks/media-buy-delivery.d.mts +43 -0
  223. package/dist/lib/webhooks/media-buy-delivery.d.ts +43 -0
  224. package/dist/lib/webhooks/media-buy-delivery.js +119 -0
  225. package/dist/lib/webhooks/media-buy-delivery.mjs +94 -0
  226. package/docs/TYPE-SUMMARY.md +2 -2
  227. package/docs/guides/BUILD-AN-AGENT.md +9 -1
  228. package/docs/guides/DELIVERY-WEBHOOK-PARSING.md +135 -0
  229. package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +15 -0
  230. package/docs/guides/TYPED-CLIENT-TOOLS.md +49 -0
  231. package/docs/llms.txt +3 -3
  232. package/docs/migration-14.x-rc-worksheet.md +4 -4
  233. package/docs/migration-6.6-to-6.7.md +14 -0
  234. package/docs/migration-account-change-feed.md +19 -0
  235. package/docs/releases/sdk-16.6-adoption-fixes.md +33 -0
  236. package/package.json +2 -2
@@ -208,17 +208,41 @@ function evaluatePackage(pkg, pointer, index, products) {
208
208
  actual: productId ?? null
209
209
  };
210
210
  }
211
+ const routes = [];
211
212
  const formatOptionRefs = Array.isArray(pkg.format_option_refs) ? pkg.format_option_refs : [];
212
213
  if (formatOptionRefs.length > 0) {
213
- return evaluateFormatOptionRefs(formatOptionRefs, product, pointer);
214
+ routes.push({ name: "format_option_refs", verdict: evaluateFormatOptionRefs(formatOptionRefs, product, pointer) });
214
215
  }
215
216
  const formatIds = Array.isArray(pkg.format_ids) ? pkg.format_ids : [];
216
217
  if (formatIds.length > 0) {
217
- return evaluateLegacyFormatIds(formatIds, product, pointer, productId);
218
+ routes.push({ name: "format_ids", verdict: evaluateLegacyFormatIds(formatIds, product, pointer, productId) });
218
219
  }
219
220
  const canonicalSelectors = extractCanonicalSelectors(pkg, pointer);
220
221
  if (canonicalSelectors.length > 0) {
221
- return evaluateCanonicalSelectors(canonicalSelectors, product);
222
+ routes.push({ name: "canonical selectors", verdict: evaluateCanonicalSelectors(canonicalSelectors, product) });
223
+ }
224
+ const failed = routes.find((route) => !route.verdict.satisfied);
225
+ if (failed) return failed.verdict;
226
+ const primary = routes[0];
227
+ if (primary) {
228
+ const selected = new Set(primary.verdict.selectedDeclarations);
229
+ const conflicting = routes.slice(1).find((route) => {
230
+ const other = new Set(route.verdict.selectedDeclarations);
231
+ return selected.size !== other.size || [...selected].some((index2) => !other.has(index2));
232
+ });
233
+ if (conflicting) {
234
+ return {
235
+ satisfied: false,
236
+ bug_class: "directionality",
237
+ detail: `Conflicting selector routes ${primary.name} and ${conflicting.name} select different product format_options[] sets`,
238
+ json_pointer: pointer,
239
+ observations: routes.map((route) => ({
240
+ route: route.name,
241
+ selected_declarations: route.verdict.selectedDeclarations
242
+ }))
243
+ };
244
+ }
245
+ return primary.verdict;
222
246
  }
223
247
  return {
224
248
  satisfied: true,
@@ -238,6 +262,7 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
238
262
  actual: refs
239
263
  };
240
264
  }
265
+ const selected = /* @__PURE__ */ new Set();
241
266
  for (let i = 0; i < refs.length; i++) {
242
267
  const ref = refs[i];
243
268
  if (!isRecord(ref)) {
@@ -267,13 +292,13 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
267
292
  actual: ref
268
293
  };
269
294
  }
270
- const match = declarations.find((decl) => {
295
+ const match = declarations.findIndex((decl) => {
271
296
  if (ref.scope === "publisher") {
272
297
  return decl.publisher_domain === ref.publisher_domain && decl.format_option_id === ref.format_option_id && typeof ref.publisher_domain === "string";
273
298
  }
274
299
  return decl.format_option_id === ref.format_option_id && !decl.publisher_domain;
275
300
  });
276
- if (!match) {
301
+ if (match < 0) {
277
302
  return {
278
303
  satisfied: false,
279
304
  bug_class: "closed_set",
@@ -283,16 +308,19 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
283
308
  observations: [{ available_format_option_ids: declarations.map(declarationLabel).filter(Boolean) }]
284
309
  };
285
310
  }
311
+ selected.add(match);
286
312
  }
287
313
  return {
288
314
  satisfied: true,
289
315
  bug_class: "directionality",
290
316
  detail: "Every format_option_refs[] entry resolved to the target product format_options[] closed set",
291
- json_pointer: `${packagePointer}/format_option_refs`
317
+ json_pointer: `${packagePointer}/format_option_refs`,
318
+ selectedDeclarations: [...selected]
292
319
  };
293
320
  }
294
321
  function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
295
322
  const declarations = productFormatOptions(product);
323
+ const selected = /* @__PURE__ */ new Set();
296
324
  for (let i = 0; i < refs.length; i++) {
297
325
  const ref = refs[i];
298
326
  if (!isFormatId(ref)) {
@@ -304,12 +332,22 @@ function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
304
332
  actual: ref
305
333
  };
306
334
  }
307
- const direct = declarations.find((decl) => (decl.v1_format_ref ?? []).some((v1) => sameFormatId(v1, ref)));
308
- if (direct) continue;
335
+ const direct = declarations.flatMap(
336
+ (decl, index) => (decl.v1_format_ref ?? []).some((v1) => sameFormatId(v1, ref)) ? [index] : []
337
+ );
338
+ if (direct.length > 0) {
339
+ for (const index of direct) selected.add(index);
340
+ continue;
341
+ }
309
342
  const projected = projectLegacyRef(ref, productId, `${packagePointer}/format_ids/${i}`);
310
343
  if (projected) {
311
- const match = declarations.find((decl) => canonicalSelectorSatisfiesDeclaration(projected, decl).ok);
312
- if (match) continue;
344
+ const matches = declarations.flatMap(
345
+ (decl, index) => canonicalSelectorSatisfiesDeclaration(projected, decl).ok ? [index] : []
346
+ );
347
+ if (matches.length > 0) {
348
+ for (const index of matches) selected.add(index);
349
+ continue;
350
+ }
313
351
  }
314
352
  if (declarations.length === 0 && Array.isArray(product.format_ids) && product.format_ids.some((fid) => isFormatId(fid) && sameFormatId(fid, ref))) {
315
353
  continue;
@@ -327,7 +365,8 @@ function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
327
365
  satisfied: true,
328
366
  bug_class: "normalization",
329
367
  detail: "Every legacy format_id normalized to a product canonical declaration or product legacy format_id",
330
- json_pointer: `${packagePointer}/format_ids`
368
+ json_pointer: `${packagePointer}/format_ids`,
369
+ selectedDeclarations: [...selected]
331
370
  };
332
371
  }
333
372
  function evaluateCanonicalSelectors(selectors, product) {
@@ -341,6 +380,7 @@ function evaluateCanonicalSelectors(selectors, product) {
341
380
  actual: selectors
342
381
  };
343
382
  }
383
+ const selected = /* @__PURE__ */ new Set();
344
384
  for (const selector of selectors) {
345
385
  const candidates = declarations.filter((decl) => decl.format_kind === selector.format_kind);
346
386
  if (candidates.length === 0) {
@@ -353,7 +393,12 @@ function evaluateCanonicalSelectors(selectors, product) {
353
393
  };
354
394
  }
355
395
  const checks = candidates.map((decl) => canonicalSelectorSatisfiesDeclaration(selector, decl));
356
- if (checks.some((c) => c.ok)) continue;
396
+ if (checks.some((c) => c.ok)) {
397
+ for (const [index, decl] of declarations.entries()) {
398
+ if (canonicalSelectorSatisfiesDeclaration(selector, decl).ok) selected.add(index);
399
+ }
400
+ continue;
401
+ }
357
402
  const primary = checks.find((c) => c.bug_class === "range_containment") ?? checks[0];
358
403
  return {
359
404
  satisfied: false,
@@ -368,7 +413,8 @@ function evaluateCanonicalSelectors(selectors, product) {
368
413
  satisfied: true,
369
414
  bug_class: "directionality",
370
415
  detail: "Every canonical selector satisfies at least one product format_options[] declaration",
371
- json_pointer: selectors[0]?.pointer ?? null
416
+ json_pointer: selectors[0]?.pointer ?? null,
417
+ selectedDeclarations: [...selected]
372
418
  };
373
419
  }
374
420
  function canonicalSelectorSatisfiesDeclaration(selector, decl) {
@@ -737,7 +783,7 @@ function collectRejectionInfo(value, codes, fields, messages, depth = 0) {
737
783
  }
738
784
  function rejectionSupportsFormatFailure(rejection) {
739
785
  if (!rejection) return false;
740
- if (rejection.codes.some((code) => code.startsWith("FORMAT_"))) return true;
786
+ if (rejection.codes.some((code) => code.startsWith("FORMAT_") || code === "CONFLICTING_SELECTORS")) return true;
741
787
  return [...rejection.fields, ...rejection.messages].some(
742
788
  (text) => /format|format_option|format_id|selector/i.test(text)
743
789
  );
@@ -184,17 +184,41 @@ function evaluatePackage(pkg, pointer, index, products) {
184
184
  actual: productId ?? null
185
185
  };
186
186
  }
187
+ const routes = [];
187
188
  const formatOptionRefs = Array.isArray(pkg.format_option_refs) ? pkg.format_option_refs : [];
188
189
  if (formatOptionRefs.length > 0) {
189
- return evaluateFormatOptionRefs(formatOptionRefs, product, pointer);
190
+ routes.push({ name: "format_option_refs", verdict: evaluateFormatOptionRefs(formatOptionRefs, product, pointer) });
190
191
  }
191
192
  const formatIds = Array.isArray(pkg.format_ids) ? pkg.format_ids : [];
192
193
  if (formatIds.length > 0) {
193
- return evaluateLegacyFormatIds(formatIds, product, pointer, productId);
194
+ routes.push({ name: "format_ids", verdict: evaluateLegacyFormatIds(formatIds, product, pointer, productId) });
194
195
  }
195
196
  const canonicalSelectors = extractCanonicalSelectors(pkg, pointer);
196
197
  if (canonicalSelectors.length > 0) {
197
- return evaluateCanonicalSelectors(canonicalSelectors, product);
198
+ routes.push({ name: "canonical selectors", verdict: evaluateCanonicalSelectors(canonicalSelectors, product) });
199
+ }
200
+ const failed = routes.find((route) => !route.verdict.satisfied);
201
+ if (failed) return failed.verdict;
202
+ const primary = routes[0];
203
+ if (primary) {
204
+ const selected = new Set(primary.verdict.selectedDeclarations);
205
+ const conflicting = routes.slice(1).find((route) => {
206
+ const other = new Set(route.verdict.selectedDeclarations);
207
+ return selected.size !== other.size || [...selected].some((index2) => !other.has(index2));
208
+ });
209
+ if (conflicting) {
210
+ return {
211
+ satisfied: false,
212
+ bug_class: "directionality",
213
+ detail: `Conflicting selector routes ${primary.name} and ${conflicting.name} select different product format_options[] sets`,
214
+ json_pointer: pointer,
215
+ observations: routes.map((route) => ({
216
+ route: route.name,
217
+ selected_declarations: route.verdict.selectedDeclarations
218
+ }))
219
+ };
220
+ }
221
+ return primary.verdict;
198
222
  }
199
223
  return {
200
224
  satisfied: true,
@@ -214,6 +238,7 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
214
238
  actual: refs
215
239
  };
216
240
  }
241
+ const selected = /* @__PURE__ */ new Set();
217
242
  for (let i = 0; i < refs.length; i++) {
218
243
  const ref = refs[i];
219
244
  if (!isRecord(ref)) {
@@ -243,13 +268,13 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
243
268
  actual: ref
244
269
  };
245
270
  }
246
- const match = declarations.find((decl) => {
271
+ const match = declarations.findIndex((decl) => {
247
272
  if (ref.scope === "publisher") {
248
273
  return decl.publisher_domain === ref.publisher_domain && decl.format_option_id === ref.format_option_id && typeof ref.publisher_domain === "string";
249
274
  }
250
275
  return decl.format_option_id === ref.format_option_id && !decl.publisher_domain;
251
276
  });
252
- if (!match) {
277
+ if (match < 0) {
253
278
  return {
254
279
  satisfied: false,
255
280
  bug_class: "closed_set",
@@ -259,16 +284,19 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
259
284
  observations: [{ available_format_option_ids: declarations.map(declarationLabel).filter(Boolean) }]
260
285
  };
261
286
  }
287
+ selected.add(match);
262
288
  }
263
289
  return {
264
290
  satisfied: true,
265
291
  bug_class: "directionality",
266
292
  detail: "Every format_option_refs[] entry resolved to the target product format_options[] closed set",
267
- json_pointer: `${packagePointer}/format_option_refs`
293
+ json_pointer: `${packagePointer}/format_option_refs`,
294
+ selectedDeclarations: [...selected]
268
295
  };
269
296
  }
270
297
  function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
271
298
  const declarations = productFormatOptions(product);
299
+ const selected = /* @__PURE__ */ new Set();
272
300
  for (let i = 0; i < refs.length; i++) {
273
301
  const ref = refs[i];
274
302
  if (!isFormatId(ref)) {
@@ -280,12 +308,22 @@ function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
280
308
  actual: ref
281
309
  };
282
310
  }
283
- const direct = declarations.find((decl) => (decl.v1_format_ref ?? []).some((v1) => sameFormatId(v1, ref)));
284
- if (direct) continue;
311
+ const direct = declarations.flatMap(
312
+ (decl, index) => (decl.v1_format_ref ?? []).some((v1) => sameFormatId(v1, ref)) ? [index] : []
313
+ );
314
+ if (direct.length > 0) {
315
+ for (const index of direct) selected.add(index);
316
+ continue;
317
+ }
285
318
  const projected = projectLegacyRef(ref, productId, `${packagePointer}/format_ids/${i}`);
286
319
  if (projected) {
287
- const match = declarations.find((decl) => canonicalSelectorSatisfiesDeclaration(projected, decl).ok);
288
- if (match) continue;
320
+ const matches = declarations.flatMap(
321
+ (decl, index) => canonicalSelectorSatisfiesDeclaration(projected, decl).ok ? [index] : []
322
+ );
323
+ if (matches.length > 0) {
324
+ for (const index of matches) selected.add(index);
325
+ continue;
326
+ }
289
327
  }
290
328
  if (declarations.length === 0 && Array.isArray(product.format_ids) && product.format_ids.some((fid) => isFormatId(fid) && sameFormatId(fid, ref))) {
291
329
  continue;
@@ -303,7 +341,8 @@ function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
303
341
  satisfied: true,
304
342
  bug_class: "normalization",
305
343
  detail: "Every legacy format_id normalized to a product canonical declaration or product legacy format_id",
306
- json_pointer: `${packagePointer}/format_ids`
344
+ json_pointer: `${packagePointer}/format_ids`,
345
+ selectedDeclarations: [...selected]
307
346
  };
308
347
  }
309
348
  function evaluateCanonicalSelectors(selectors, product) {
@@ -317,6 +356,7 @@ function evaluateCanonicalSelectors(selectors, product) {
317
356
  actual: selectors
318
357
  };
319
358
  }
359
+ const selected = /* @__PURE__ */ new Set();
320
360
  for (const selector of selectors) {
321
361
  const candidates = declarations.filter((decl) => decl.format_kind === selector.format_kind);
322
362
  if (candidates.length === 0) {
@@ -329,7 +369,12 @@ function evaluateCanonicalSelectors(selectors, product) {
329
369
  };
330
370
  }
331
371
  const checks = candidates.map((decl) => canonicalSelectorSatisfiesDeclaration(selector, decl));
332
- if (checks.some((c) => c.ok)) continue;
372
+ if (checks.some((c) => c.ok)) {
373
+ for (const [index, decl] of declarations.entries()) {
374
+ if (canonicalSelectorSatisfiesDeclaration(selector, decl).ok) selected.add(index);
375
+ }
376
+ continue;
377
+ }
333
378
  const primary = checks.find((c) => c.bug_class === "range_containment") ?? checks[0];
334
379
  return {
335
380
  satisfied: false,
@@ -344,7 +389,8 @@ function evaluateCanonicalSelectors(selectors, product) {
344
389
  satisfied: true,
345
390
  bug_class: "directionality",
346
391
  detail: "Every canonical selector satisfies at least one product format_options[] declaration",
347
- json_pointer: selectors[0]?.pointer ?? null
392
+ json_pointer: selectors[0]?.pointer ?? null,
393
+ selectedDeclarations: [...selected]
348
394
  };
349
395
  }
350
396
  function canonicalSelectorSatisfiesDeclaration(selector, decl) {
@@ -713,7 +759,7 @@ function collectRejectionInfo(value, codes, fields, messages, depth = 0) {
713
759
  }
714
760
  function rejectionSupportsFormatFailure(rejection) {
715
761
  if (!rejection) return false;
716
- if (rejection.codes.some((code) => code.startsWith("FORMAT_"))) return true;
762
+ if (rejection.codes.some((code) => code.startsWith("FORMAT_") || code === "CONFLICTING_SELECTORS")) return true;
717
763
  return [...rejection.fields, ...rejection.messages].some(
718
764
  (text) => /format|format_option|format_id|selector/i.test(text)
719
765
  );
@@ -181,12 +181,9 @@ export declare function getExternalSchemaRootForCompliance(options: ResolveOptio
181
181
  export declare function loadBundleStoryboards(ref: BundleRef): Storyboard[];
182
182
  /** Enumerate every bundle present in the cache (universal + protocols + specialisms). */
183
183
  export declare function listBundles(options?: ResolveOptions): BundleRef[];
184
- /** List every storyboard the cache can produce, across all bundles. */
184
+ /** List every storyboard the selected immutable bundle can produce, as detached records. */
185
185
  export declare function listAllComplianceStoryboards(options?: ResolveOptions): Storyboard[];
186
- /**
187
- * Find a storyboard by its internal `id` (the YAML's `id:` field).
188
- * Scans every bundle in the cache. Returns undefined if no match.
189
- */
186
+ /** Find a storyboard by its internal YAML id without reparsing a warm bundle. */
190
187
  export declare function getComplianceStoryboardById(id: string, options?: ResolveOptions): Storyboard | undefined;
191
188
  /** Find a bundle by its directory/file id (`media-buy`, `sales-guaranteed`, `capability-discovery`). */
192
189
  export declare function findBundleById(id: string, options?: ResolveOptions): BundleRef | undefined;
@@ -181,12 +181,9 @@ export declare function getExternalSchemaRootForCompliance(options: ResolveOptio
181
181
  export declare function loadBundleStoryboards(ref: BundleRef): Storyboard[];
182
182
  /** Enumerate every bundle present in the cache (universal + protocols + specialisms). */
183
183
  export declare function listBundles(options?: ResolveOptions): BundleRef[];
184
- /** List every storyboard the cache can produce, across all bundles. */
184
+ /** List every storyboard the selected immutable bundle can produce, as detached records. */
185
185
  export declare function listAllComplianceStoryboards(options?: ResolveOptions): Storyboard[];
186
- /**
187
- * Find a storyboard by its internal `id` (the YAML's `id:` field).
188
- * Scans every bundle in the cache. Returns undefined if no match.
189
- */
186
+ /** Find a storyboard by its internal YAML id without reparsing a warm bundle. */
190
187
  export declare function getComplianceStoryboardById(id: string, options?: ResolveOptions): Storyboard | undefined;
191
188
  /** Find a bundle by its directory/file id (`media-buy`, `sales-guaranteed`, `capability-discovery`). */
192
189
  export declare function findBundleById(id: string, options?: ResolveOptions): BundleRef | undefined;
@@ -47,6 +47,7 @@ var import_errors = require('../../errors/index.js');
47
47
  var import_adcp_version_config = require('../../utils/adcp-version-config.js');
48
48
  var import_schema_loader = require('../../validation/schema-loader.js');
49
49
  var import_synthesize = require('./request-signing/synthesize.js');
50
+ var import_vector_loader = require('./request-signing/vector-loader.js');
50
51
  var import_provenance = require('./provenance.js');
51
52
  class CapabilityResolutionError extends import_errors.ADCPError {
52
53
  code;
@@ -434,23 +435,71 @@ function listBundles(options = {}) {
434
435
  }
435
436
  return bundles;
436
437
  }
437
- function listAllComplianceStoryboards(options = {}) {
438
- const seen = /* @__PURE__ */ new Set();
439
- const storyboards = [];
440
- for (const ref of listBundles(options)) {
441
- for (const sb of loadBundleStoryboards(ref)) {
442
- if (seen.has(sb.id)) continue;
443
- seen.add(sb.id);
444
- storyboards.push(sb);
438
+ const STORYBOARD_INDEX_CACHE_LIMIT = 8;
439
+ const storyboardIndexes = /* @__PURE__ */ new Map();
440
+ function customComplianceInventory(dir) {
441
+ if (!(0, import_fs.existsSync)(dir)) return "missing";
442
+ const entries = [];
443
+ const visitedDirectories = /* @__PURE__ */ new Set();
444
+ const visit = (file, relative) => {
445
+ const stat = (0, import_fs.statSync)(file, { bigint: true });
446
+ entries.push([relative, String(stat.mtimeNs), String(stat.ctimeNs), String(stat.size), String(stat.ino)]);
447
+ if (!stat.isDirectory()) return;
448
+ const identity = `${stat.dev}:${stat.ino}`;
449
+ if (visitedDirectories.has(identity)) return;
450
+ visitedDirectories.add(identity);
451
+ for (const child of (0, import_fs.readdirSync)(file).sort()) visit((0, import_path.join)(file, child), `${relative}/${child}`);
452
+ };
453
+ visit(dir, "");
454
+ return JSON.stringify(entries);
455
+ }
456
+ function complianceStoryboardIndex(options) {
457
+ const dir = (0, import_path.resolve)(getComplianceCacheDir(options));
458
+ const indexPath = (0, import_path.join)(dir, "index.json");
459
+ const stamp = (0, import_fs.existsSync)(indexPath) ? (0, import_fs.statSync)(indexPath) : void 0;
460
+ const schemaRoot = getConfiguredSchemaRoot(options);
461
+ const customRoot = Boolean(getConfiguredComplianceDir(options));
462
+ const inventory = customRoot ? customComplianceInventory(dir) : null;
463
+ const key = JSON.stringify([
464
+ dir,
465
+ options.version ?? import_version.ADCP_VERSION,
466
+ schemaRoot ? (0, import_path.resolve)(schemaRoot) : null,
467
+ options.hostedStableLineAlias ?? null,
468
+ stamp?.mtimeMs ?? null,
469
+ stamp?.size ?? null,
470
+ inventory
471
+ ]);
472
+ const cached = storyboardIndexes.get(key);
473
+ if (cached) {
474
+ storyboardIndexes.delete(key);
475
+ storyboardIndexes.set(key, cached);
476
+ return cached;
477
+ }
478
+ if (customRoot) (0, import_vector_loader.invalidateRequestSigningVectorCache)(dir);
479
+ const indexed = /* @__PURE__ */ new Map();
480
+ for (const ref of listBundles({ ...options, complianceDir: dir })) {
481
+ for (const storyboard of loadBundleStoryboards(ref)) {
482
+ if (!indexed.has(storyboard.id)) indexed.set(storyboard.id, storyboard);
445
483
  }
446
484
  }
447
- return storyboards;
485
+ storyboardIndexes.set(key, indexed);
486
+ while (storyboardIndexes.size > STORYBOARD_INDEX_CACHE_LIMIT) {
487
+ const oldest = storyboardIndexes.keys().next().value;
488
+ if (oldest !== void 0) storyboardIndexes.delete(oldest);
489
+ }
490
+ return indexed;
491
+ }
492
+ function cloneComplianceStoryboard(storyboard) {
493
+ const copy = structuredClone(storyboard);
494
+ const trustedRoot = (0, import_provenance.trustedStoryboardComplianceRoot)(storyboard);
495
+ return trustedRoot ? (0, import_provenance.markStoryboardComplianceRoot)(copy, trustedRoot) : copy;
496
+ }
497
+ function listAllComplianceStoryboards(options = {}) {
498
+ return [...complianceStoryboardIndex(options).values()].map(cloneComplianceStoryboard);
448
499
  }
449
500
  function getComplianceStoryboardById(id, options = {}) {
450
- for (const sb of listAllComplianceStoryboards(options)) {
451
- if (sb.id === id) return sb;
452
- }
453
- return void 0;
501
+ const storyboard = complianceStoryboardIndex(options).get(id);
502
+ return storyboard ? cloneComplianceStoryboard(storyboard) : void 0;
454
503
  }
455
504
  function findBundleById(id, options = {}) {
456
505
  return listBundles(options).find((b) => b.id === id);
@@ -12,7 +12,8 @@ import { ADCPError } from "../../errors/index.mjs";
12
12
  import { isAdcpVersionSupported } from "../../utils/adcp-version-config.mjs";
13
13
  import { hasSchemaBundle, resolveBundleKey } from "../../validation/schema-loader.mjs";
14
14
  import { synthesizeRequestSigningSteps } from "./request-signing/synthesize.mjs";
15
- import { markStoryboardComplianceRoot } from "./provenance.mjs";
15
+ import { invalidateRequestSigningVectorCache } from "./request-signing/vector-loader.mjs";
16
+ import { markStoryboardComplianceRoot, trustedStoryboardComplianceRoot } from "./provenance.mjs";
16
17
  class CapabilityResolutionError extends ADCPError {
17
18
  code;
18
19
  specialism;
@@ -399,23 +400,71 @@ function listBundles(options = {}) {
399
400
  }
400
401
  return bundles;
401
402
  }
402
- function listAllComplianceStoryboards(options = {}) {
403
- const seen = /* @__PURE__ */ new Set();
404
- const storyboards = [];
405
- for (const ref of listBundles(options)) {
406
- for (const sb of loadBundleStoryboards(ref)) {
407
- if (seen.has(sb.id)) continue;
408
- seen.add(sb.id);
409
- storyboards.push(sb);
403
+ const STORYBOARD_INDEX_CACHE_LIMIT = 8;
404
+ const storyboardIndexes = /* @__PURE__ */ new Map();
405
+ function customComplianceInventory(dir) {
406
+ if (!existsSync(dir)) return "missing";
407
+ const entries = [];
408
+ const visitedDirectories = /* @__PURE__ */ new Set();
409
+ const visit = (file, relative) => {
410
+ const stat = statSync(file, { bigint: true });
411
+ entries.push([relative, String(stat.mtimeNs), String(stat.ctimeNs), String(stat.size), String(stat.ino)]);
412
+ if (!stat.isDirectory()) return;
413
+ const identity = `${stat.dev}:${stat.ino}`;
414
+ if (visitedDirectories.has(identity)) return;
415
+ visitedDirectories.add(identity);
416
+ for (const child of readdirSync(file).sort()) visit(join(file, child), `${relative}/${child}`);
417
+ };
418
+ visit(dir, "");
419
+ return JSON.stringify(entries);
420
+ }
421
+ function complianceStoryboardIndex(options) {
422
+ const dir = resolve(getComplianceCacheDir(options));
423
+ const indexPath = join(dir, "index.json");
424
+ const stamp = existsSync(indexPath) ? statSync(indexPath) : void 0;
425
+ const schemaRoot = getConfiguredSchemaRoot(options);
426
+ const customRoot = Boolean(getConfiguredComplianceDir(options));
427
+ const inventory = customRoot ? customComplianceInventory(dir) : null;
428
+ const key = JSON.stringify([
429
+ dir,
430
+ options.version ?? ADCP_VERSION,
431
+ schemaRoot ? resolve(schemaRoot) : null,
432
+ options.hostedStableLineAlias ?? null,
433
+ stamp?.mtimeMs ?? null,
434
+ stamp?.size ?? null,
435
+ inventory
436
+ ]);
437
+ const cached = storyboardIndexes.get(key);
438
+ if (cached) {
439
+ storyboardIndexes.delete(key);
440
+ storyboardIndexes.set(key, cached);
441
+ return cached;
442
+ }
443
+ if (customRoot) invalidateRequestSigningVectorCache(dir);
444
+ const indexed = /* @__PURE__ */ new Map();
445
+ for (const ref of listBundles({ ...options, complianceDir: dir })) {
446
+ for (const storyboard of loadBundleStoryboards(ref)) {
447
+ if (!indexed.has(storyboard.id)) indexed.set(storyboard.id, storyboard);
410
448
  }
411
449
  }
412
- return storyboards;
450
+ storyboardIndexes.set(key, indexed);
451
+ while (storyboardIndexes.size > STORYBOARD_INDEX_CACHE_LIMIT) {
452
+ const oldest = storyboardIndexes.keys().next().value;
453
+ if (oldest !== void 0) storyboardIndexes.delete(oldest);
454
+ }
455
+ return indexed;
456
+ }
457
+ function cloneComplianceStoryboard(storyboard) {
458
+ const copy = structuredClone(storyboard);
459
+ const trustedRoot = trustedStoryboardComplianceRoot(storyboard);
460
+ return trustedRoot ? markStoryboardComplianceRoot(copy, trustedRoot) : copy;
461
+ }
462
+ function listAllComplianceStoryboards(options = {}) {
463
+ return [...complianceStoryboardIndex(options).values()].map(cloneComplianceStoryboard);
413
464
  }
414
465
  function getComplianceStoryboardById(id, options = {}) {
415
- for (const sb of listAllComplianceStoryboards(options)) {
416
- if (sb.id === id) return sb;
417
- }
418
- return void 0;
466
+ const storyboard = complianceStoryboardIndex(options).get(id);
467
+ return storyboard ? cloneComplianceStoryboard(storyboard) : void 0;
419
468
  }
420
469
  function findBundleById(id, options = {}) {
421
470
  return listBundles(options).find((b) => b.id === id);
@@ -10,12 +10,22 @@
10
10
  * (context_outputs/context_inputs) while still enabling stateful flows.
11
11
  */
12
12
  import type { StoryboardContext, ContextOutput, ContextInput, ContextProvenanceEntry } from './types.mjs';
13
- type ContextExtractor = (data: unknown) => Record<string, unknown>;
13
+ /**
14
+ * `adcpVersion` is the release the step was requested at. Media-buy mutation
15
+ * extractors use it to tell a 3.1+ task-envelope `status` from a 3.0
16
+ * lifecycle `status` when the response does not echo its version.
17
+ */
18
+ type ContextExtractor = (data: unknown, adcpVersion?: string) => Record<string, unknown>;
14
19
  export declare const CONTEXT_EXTRACTORS: Record<string, ContextExtractor>;
15
20
  /**
16
21
  * Extract context values from a task response.
22
+ *
23
+ * @param adcpVersion - Optional AdCP release the request was sent at. Used
24
+ * only when the response does not echo `adcp_version`, to read a
25
+ * create/update top-level `status` as the 3.1+ task status rather than a
26
+ * 3.0 media-buy lifecycle.
17
27
  */
18
- export declare function extractContext(taskName: string, data: unknown): Record<string, unknown>;
28
+ export declare function extractContext(taskName: string, data: unknown, adcpVersion?: string): Record<string, unknown>;
19
29
  /**
20
30
  * Propagate the alias cache from one context to another — call after
21
31
  * shallow-cloning context between storyboard steps so replay tests
@@ -132,7 +142,7 @@ export interface ContextWriteResult {
132
142
  * tagging it as a convention-based extraction. `response_path` is absent
133
143
  * for convention extractors — they're hardcoded functions, not YAML paths.
134
144
  */
135
- export declare function extractContextWithProvenance(taskName: string, data: unknown, stepId: string): ContextWriteResult;
145
+ export declare function extractContextWithProvenance(taskName: string, data: unknown, stepId: string, adcpVersion?: string): ContextWriteResult;
136
146
  /**
137
147
  * Like `applyContextOutputs`, but also returns provenance for each written
138
148
  * key carrying the YAML `response_path` so diagnostics can cite it verbatim.
@@ -10,12 +10,22 @@
10
10
  * (context_outputs/context_inputs) while still enabling stateful flows.
11
11
  */
12
12
  import type { StoryboardContext, ContextOutput, ContextInput, ContextProvenanceEntry } from './types';
13
- type ContextExtractor = (data: unknown) => Record<string, unknown>;
13
+ /**
14
+ * `adcpVersion` is the release the step was requested at. Media-buy mutation
15
+ * extractors use it to tell a 3.1+ task-envelope `status` from a 3.0
16
+ * lifecycle `status` when the response does not echo its version.
17
+ */
18
+ type ContextExtractor = (data: unknown, adcpVersion?: string) => Record<string, unknown>;
14
19
  export declare const CONTEXT_EXTRACTORS: Record<string, ContextExtractor>;
15
20
  /**
16
21
  * Extract context values from a task response.
22
+ *
23
+ * @param adcpVersion - Optional AdCP release the request was sent at. Used
24
+ * only when the response does not echo `adcp_version`, to read a
25
+ * create/update top-level `status` as the 3.1+ task status rather than a
26
+ * 3.0 media-buy lifecycle.
17
27
  */
18
- export declare function extractContext(taskName: string, data: unknown): Record<string, unknown>;
28
+ export declare function extractContext(taskName: string, data: unknown, adcpVersion?: string): Record<string, unknown>;
19
29
  /**
20
30
  * Propagate the alias cache from one context to another — call after
21
31
  * shallow-cloning context between storyboard steps so replay tests
@@ -132,7 +142,7 @@ export interface ContextWriteResult {
132
142
  * tagging it as a convention-based extraction. `response_path` is absent
133
143
  * for convention extractors — they're hardcoded functions, not YAML paths.
134
144
  */
135
- export declare function extractContextWithProvenance(taskName: string, data: unknown, stepId: string): ContextWriteResult;
145
+ export declare function extractContextWithProvenance(taskName: string, data: unknown, stepId: string, adcpVersion?: string): ContextWriteResult;
136
146
  /**
137
147
  * Like `applyContextOutputs`, but also returns provenance for each written
138
148
  * key carrying the YAML `response_path` so diagnostics can cite it verbatim.